feat: don't trigger trivial completion when the trigger char is an ascii punctuation (#748)

This commit is contained in:
Myriad-Dreamin 2024-10-29 22:32:12 +08:00 committed by GitHub
parent e8f5f6185a
commit 493f8a8695
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 162 additions and 6 deletions

View file

@ -46,6 +46,8 @@ pub struct CompletionRequest {
pub position: LspPosition, pub position: LspPosition,
/// Whether the completion is triggered explicitly. /// Whether the completion is triggered explicitly.
pub explicit: bool, pub explicit: bool,
/// The character that triggered the completion, if any.
pub trigger_character: Option<char>,
/// Whether to trigger suggest completion, a.k.a. auto-completion. /// Whether to trigger suggest completion, a.k.a. auto-completion.
pub trigger_suggest: bool, pub trigger_suggest: bool,
/// Whether to trigger named parameter completion. /// Whether to trigger named parameter completion.
@ -145,6 +147,7 @@ impl StatefulRequest for CompletionRequest {
&source, &source,
cursor, cursor,
explicit, explicit,
self.trigger_character,
self.trigger_suggest, self.trigger_suggest,
self.trigger_parameter_hints, self.trigger_parameter_hints,
self.trigger_named_completion, self.trigger_named_completion,
@ -336,6 +339,11 @@ mod tests {
let docs = find_module_level_docs(&source).unwrap_or_default(); let docs = find_module_level_docs(&source).unwrap_or_default();
let properties = get_test_properties(&docs); let properties = get_test_properties(&docs);
let trigger_character = properties
.get("trigger_character")
.map(|v| v.chars().next().unwrap());
let mut includes = HashSet::new(); let mut includes = HashSet::new();
let mut excludes = HashSet::new(); let mut excludes = HashSet::new();
@ -389,6 +397,7 @@ mod tests {
path: ctx.path_for_id(id).unwrap(), path: ctx.path_for_id(id).unwrap(),
position: ctx.to_lsp_pos(s, &source), position: ctx.to_lsp_pos(s, &source),
explicit: false, explicit: false,
trigger_character,
trigger_suggest: true, trigger_suggest: true,
trigger_parameter_hints: true, trigger_parameter_hints: true,
trigger_named_completion: true, trigger_named_completion: true,

View file

@ -0,0 +1,2 @@
// contains: attach
$: /* range -1..0 */$

View file

@ -0,0 +1,3 @@
// contains: attach
// trigger_character: :
$: /* range -1..0 */$

View file

@ -0,0 +1,2 @@
// contains: attach
$: /* range -1..0 */$

View file

@ -0,0 +1,3 @@
// contains: attach
// trigger_character: :
$: /* range -1..0 */$

View file

@ -0,0 +1,3 @@
// contains: length
// trigger_character: :
#set text(baseline: /* range -1..0 */)

View file

@ -0,0 +1,33 @@
---
source: crates/tinymist-query/src/completion.rs
description: Completion on (22..23)
expression: "JsonRepr::new_pure(results)"
input_file: crates/tinymist-query/src/fixtures/completion/colon_markup.typ
---
[
{
"isIncomplete": false,
"items": [
{
"kind": 3,
"label": "attach",
"labelDetails": {
"description": "(content, b: content | none, bl: content | none, br: content | none, t: content | none, tl: content | none, tr: content | none) => attach"
},
"textEdit": {
"newText": "attach(${1:})",
"range": {
"end": {
"character": 2,
"line": 1
},
"start": {
"character": 1,
"line": 1
}
}
}
}
]
}
]

View file

@ -0,0 +1,12 @@
---
source: crates/tinymist-query/src/completion.rs
description: Completion on (46..47)
expression: "JsonRepr::new_pure(results)"
input_file: crates/tinymist-query/src/fixtures/completion/colon_markup2.typ
---
[
{
"isIncomplete": false,
"items": []
}
]

View file

@ -0,0 +1,33 @@
---
source: crates/tinymist-query/src/completion.rs
description: Completion on (22..23)
expression: "JsonRepr::new_pure(results)"
input_file: crates/tinymist-query/src/fixtures/completion/colon_math.typ
---
[
{
"isIncomplete": false,
"items": [
{
"kind": 3,
"label": "attach",
"labelDetails": {
"description": "(content, b: content | none, bl: content | none, br: content | none, t: content | none, tl: content | none, tr: content | none) => attach"
},
"textEdit": {
"newText": "attach(${1:})",
"range": {
"end": {
"character": 2,
"line": 1
},
"start": {
"character": 1,
"line": 1
}
}
}
}
]
}
]

View file

@ -0,0 +1,12 @@
---
source: crates/tinymist-query/src/completion.rs
description: Completion on (46..47)
expression: "JsonRepr::new_pure(results)"
input_file: crates/tinymist-query/src/fixtures/completion/colon_math2.typ
---
[
{
"isIncomplete": false,
"items": []
}
]

View file

@ -0,0 +1,31 @@
---
source: crates/tinymist-query/src/completion.rs
description: Completion on (63..64)
expression: "JsonRepr::new_pure(results)"
input_file: crates/tinymist-query/src/fixtures/completion/colon_param.typ
---
[
{
"isIncomplete": false,
"items": [
{
"kind": 15,
"label": "length",
"sortText": "000",
"textEdit": {
"newText": " ${1:length}",
"range": {
"end": {
"character": 19,
"line": 2
},
"start": {
"character": 19,
"line": 2
}
}
}
}
]
}
]

View file

@ -187,7 +187,7 @@ fn complete_markup(ctx: &mut CompletionContext) -> bool {
} }
// Anywhere: "|". // Anywhere: "|".
if ctx.explicit { if !is_triggerred_by_punc(ctx.trigger_character) && ctx.explicit {
ctx.from = ctx.cursor; ctx.from = ctx.cursor;
markup_completions(ctx); markup_completions(ctx);
return true; return true;
@ -316,14 +316,16 @@ fn complete_math(ctx: &mut CompletionContext) -> bool {
} }
// Behind existing atom or identifier: "$a|$" or "$abc|$". // Behind existing atom or identifier: "$a|$" or "$abc|$".
if matches!(ctx.leaf.kind(), SyntaxKind::Text | SyntaxKind::MathIdent) { if !is_triggerred_by_punc(ctx.trigger_character)
&& matches!(ctx.leaf.kind(), SyntaxKind::Text | SyntaxKind::MathIdent)
{
ctx.from = ctx.leaf.offset(); ctx.from = ctx.leaf.offset();
math_completions(ctx); math_completions(ctx);
return true; return true;
} }
// Anywhere: "$|$". // Anywhere: "$|$".
if ctx.explicit { if !is_triggerred_by_punc(ctx.trigger_character) && ctx.explicit {
ctx.from = ctx.cursor; ctx.from = ctx.cursor;
math_completions(ctx); math_completions(ctx);
return true; return true;
@ -959,6 +961,7 @@ pub struct CompletionContext<'a, 'b> {
pub leaf: LinkedNode<'a>, pub leaf: LinkedNode<'a>,
pub cursor: usize, pub cursor: usize,
pub explicit: bool, pub explicit: bool,
pub trigger_character: Option<char>,
pub trigger_suggest: bool, pub trigger_suggest: bool,
pub trigger_parameter_hints: bool, pub trigger_parameter_hints: bool,
pub trigger_named_completion: bool, pub trigger_named_completion: bool,
@ -980,6 +983,7 @@ impl<'a, 'w> CompletionContext<'a, 'w> {
source: &'a Source, source: &'a Source,
cursor: usize, cursor: usize,
explicit: bool, explicit: bool,
trigger_character: Option<char>,
trigger_suggest: bool, trigger_suggest: bool,
trigger_parameter_hints: bool, trigger_parameter_hints: bool,
trigger_named_completion: bool, trigger_named_completion: bool,
@ -996,6 +1000,7 @@ impl<'a, 'w> CompletionContext<'a, 'w> {
root, root,
leaf, leaf,
cursor, cursor,
trigger_character,
trigger_suggest, trigger_suggest,
trigger_parameter_hints, trigger_parameter_hints,
trigger_named_completion, trigger_named_completion,
@ -1298,3 +1303,7 @@ fn slice_at(s: &str, mut rng: Range<usize>) -> &str {
&s[rng] &s[rng]
} }
fn is_triggerred_by_punc(trigger_character: Option<char>) -> bool {
trigger_character.is_some_and(|c| c.is_ascii_punctuation())
}

View file

@ -746,10 +746,13 @@ impl LanguageState {
fn completion(&mut self, req_id: RequestId, params: CompletionParams) -> ScheduledResult { fn completion(&mut self, req_id: RequestId, params: CompletionParams) -> ScheduledResult {
let (path, position) = as_path_pos(params.text_document_position); let (path, position) = as_path_pos(params.text_document_position);
let explicit = params let explicit = params.context.as_ref().map_or(false, |context| {
context.trigger_kind == CompletionTriggerKind::INVOKED
});
let trigger_character = params
.context .context
.map(|context| context.trigger_kind == CompletionTriggerKind::INVOKED) .and_then(|c| c.trigger_character)
.unwrap_or(false); .and_then(|c| c.chars().next());
let trigger_suggest = self.config.trigger_suggest; let trigger_suggest = self.config.trigger_suggest;
let trigger_parameter_hints = self.config.trigger_parameter_hints; let trigger_parameter_hints = self.config.trigger_parameter_hints;
let trigger_named_completion = self.config.trigger_named_completion; let trigger_named_completion = self.config.trigger_named_completion;
@ -760,6 +763,7 @@ impl LanguageState {
path, path,
position, position,
explicit, explicit,
trigger_character,
trigger_suggest, trigger_suggest,
trigger_parameter_hints, trigger_parameter_hints,
trigger_named_completion trigger_named_completion