diff --git a/crates/tinymist-analysis/src/syntax/matcher.rs b/crates/tinymist-analysis/src/syntax/matcher.rs index a99c4119..32f2451f 100644 --- a/crates/tinymist-analysis/src/syntax/matcher.rs +++ b/crates/tinymist-analysis/src/syntax/matcher.rs @@ -1088,6 +1088,18 @@ impl<'a> SyntaxContext<'a> { | SyntaxContext::Normal(node) => node.clone(), }) } + + /// Gets the argument container node. + pub fn arg_container(&self) -> Option<&LinkedNode<'a>> { + match self { + Self::Arg { args, .. } + | Self::Element { + container: args, .. + } => Some(args), + Self::Paren { container, .. } => Some(container), + _ => None, + } + } } /// Kind of argument source. @@ -1342,6 +1354,37 @@ fn arg_context<'a>( } } +/// The cursor is on an invalid position. +pub enum BadCompletionCursor { + /// The cursor is outside of the argument list. + ArgListPos, +} + +/// Checks if the cursor is on an invalid position for completion. +pub fn bad_completion_cursor( + syntax: Option<&SyntaxClass>, + syntax_context: Option<&SyntaxContext>, + leaf: &LinkedNode, +) -> Option { + // The cursor is on `f()|` + if (matches!(syntax, Some(SyntaxClass::Callee(..))) && { + syntax_context + .and_then(SyntaxContext::arg_container) + .is_some_and(|container| { + container.rightmost_leaf().map(|s| s.offset()) == Some(leaf.offset()) + }) + // The cursor is on `f[]|` + }) || (matches!( + syntax, + Some(SyntaxClass::Normal(SyntaxKind::ContentBlock, _)) + ) && matches!(leaf.kind(), SyntaxKind::RightBracket)) + { + return Some(BadCompletionCursor::ArgListPos); + } + + None +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/tinymist-query/src/analysis/completion.rs b/crates/tinymist-query/src/analysis/completion.rs index f1369586..a7dca8f7 100644 --- a/crates/tinymist-query/src/analysis/completion.rs +++ b/crates/tinymist-query/src/analysis/completion.rs @@ -10,6 +10,7 @@ use lsp_types::InsertTextFormat; use once_cell::sync::Lazy; use regex::{Captures, Regex}; use serde::{Deserialize, Serialize}; +use tinymist_analysis::syntax::bad_completion_cursor; use tinymist_derive::BindTyCtx; use tinymist_project::LspWorld; use tinymist_std::path::unix_slash; @@ -174,13 +175,7 @@ impl<'a> CompletionCursor<'a> { let syntax_context = classify_context(leaf.clone(), Some(cursor)); let surrounding_syntax = surrounding_syntax(&leaf); - // todo: don't match here? - if matches!(syntax, Some(SyntaxClass::Callee(..))) - && matches!(syntax_context.as_ref(), Some( - SyntaxContext::Element { container, .. } | - SyntaxContext::Arg { args: container, .. } | - SyntaxContext::Paren { container, .. }) if container.rightmost_leaf().map(|s| s.offset()) == Some(leaf.offset())) - { + if bad_completion_cursor(syntax.as_ref(), syntax_context.as_ref(), &leaf).is_some() { return None; } diff --git a/crates/tinymist-query/src/fixtures/completion/arg_range2.typ b/crates/tinymist-query/src/fixtures/completion/arg_range2.typ new file mode 100644 index 00000000..9a2e607b --- /dev/null +++ b/crates/tinymist-query/src/fixtures/completion/arg_range2.typ @@ -0,0 +1,2 @@ +/// contains: alignment +#align()[/* range 0..1 */] diff --git a/crates/tinymist-query/src/fixtures/completion/arg_range3.typ b/crates/tinymist-query/src/fixtures/completion/arg_range3.typ new file mode 100644 index 00000000..3d6b04df --- /dev/null +++ b/crates/tinymist-query/src/fixtures/completion/arg_range3.typ @@ -0,0 +1,2 @@ +/// contains: alignment +#align()[]/* range 0..1 */ diff --git a/crates/tinymist-query/src/fixtures/completion/arg_range4.typ b/crates/tinymist-query/src/fixtures/completion/arg_range4.typ new file mode 100644 index 00000000..2b04b2d2 --- /dev/null +++ b/crates/tinymist-query/src/fixtures/completion/arg_range4.typ @@ -0,0 +1,4 @@ +/// contains: alignment +#align()[ + +]/* range 0..1 */ diff --git a/crates/tinymist-query/src/fixtures/completion/arg_range5.typ b/crates/tinymist-query/src/fixtures/completion/arg_range5.typ new file mode 100644 index 00000000..0402fbaa --- /dev/null +++ b/crates/tinymist-query/src/fixtures/completion/arg_range5.typ @@ -0,0 +1,4 @@ +/// contains: alignment +#align()[/* range 0..1 */ + +] diff --git a/crates/tinymist-query/src/fixtures/completion/bracket_strong_delta.typ b/crates/tinymist-query/src/fixtures/completion/bracket_strong_delta.typ index 5b33fed4..725fdc09 100644 --- a/crates/tinymist-query/src/fixtures/completion/bracket_strong_delta.typ +++ b/crates/tinymist-query/src/fixtures/completion/bracket_strong_delta.typ @@ -1,3 +1,3 @@ /// contains: delta -#strong(/* range after 1..2 */[]; +#strong(/* range 0..1 */[]; diff --git a/crates/tinymist-query/src/fixtures/completion/bracket_strong_delta2.typ b/crates/tinymist-query/src/fixtures/completion/bracket_strong_delta2.typ index a06df5ef..25777678 100644 --- a/crates/tinymist-query/src/fixtures/completion/bracket_strong_delta2.typ +++ b/crates/tinymist-query/src/fixtures/completion/bracket_strong_delta2.typ @@ -1,3 +1,3 @@ /// contains: delta -#strong(/* range after 1..2 */[]); +#strong(/* range 0..1 */[]); diff --git a/crates/tinymist-query/src/fixtures/completion/snaps/test@arg_range2.typ.snap b/crates/tinymist-query/src/fixtures/completion/snaps/test@arg_range2.typ.snap new file mode 100644 index 00000000..c45ca000 --- /dev/null +++ b/crates/tinymist-query/src/fixtures/completion/snaps/test@arg_range2.typ.snap @@ -0,0 +1,31 @@ +--- +source: crates/tinymist-query/src/completion.rs +description: Completion on / (33..34) +expression: "JsonRepr::new_pure(results)" +input_file: crates/tinymist-query/src/fixtures/completion/arg_range2.typ +--- +[ + { + "isIncomplete": false, + "items": [ + { + "kind": 15, + "label": "alignment", + "sortText": "000", + "textEdit": { + "newText": "${1:alignment}", + "range": { + "end": { + "character": 9, + "line": 1 + }, + "start": { + "character": 9, + "line": 1 + } + } + } + } + ] + } +] diff --git a/crates/tinymist-query/src/fixtures/completion/snaps/test@arg_range3.typ.snap b/crates/tinymist-query/src/fixtures/completion/snaps/test@arg_range3.typ.snap new file mode 100644 index 00000000..888f6e9f --- /dev/null +++ b/crates/tinymist-query/src/fixtures/completion/snaps/test@arg_range3.typ.snap @@ -0,0 +1,9 @@ +--- +source: crates/tinymist-query/src/completion.rs +description: Completion on / (34..35) +expression: "JsonRepr::new_pure(results)" +input_file: crates/tinymist-query/src/fixtures/completion/arg_range3.typ +--- +[ + null +] diff --git a/crates/tinymist-query/src/fixtures/completion/snaps/test@arg_range4.typ.snap b/crates/tinymist-query/src/fixtures/completion/snaps/test@arg_range4.typ.snap new file mode 100644 index 00000000..f00cdf13 --- /dev/null +++ b/crates/tinymist-query/src/fixtures/completion/snaps/test@arg_range4.typ.snap @@ -0,0 +1,9 @@ +--- +source: crates/tinymist-query/src/completion.rs +description: Completion on / (36..37) +expression: "JsonRepr::new_pure(results)" +input_file: crates/tinymist-query/src/fixtures/completion/arg_range4.typ +--- +[ + null +] diff --git a/crates/tinymist-query/src/fixtures/completion/snaps/test@arg_range5.typ.snap b/crates/tinymist-query/src/fixtures/completion/snaps/test@arg_range5.typ.snap new file mode 100644 index 00000000..70a9f7b8 --- /dev/null +++ b/crates/tinymist-query/src/fixtures/completion/snaps/test@arg_range5.typ.snap @@ -0,0 +1,31 @@ +--- +source: crates/tinymist-query/src/completion.rs +description: Completion on / (33..34) +expression: "JsonRepr::new_pure(results)" +input_file: crates/tinymist-query/src/fixtures/completion/arg_range5.typ +--- +[ + { + "isIncomplete": false, + "items": [ + { + "kind": 15, + "label": "alignment", + "sortText": "000", + "textEdit": { + "newText": "${1:alignment}", + "range": { + "end": { + "character": 9, + "line": 1 + }, + "start": { + "character": 9, + "line": 1 + } + } + } + } + ] + } +] diff --git a/crates/tinymist-query/src/fixtures/completion/snaps/test@bracket_strong_delta.typ.snap b/crates/tinymist-query/src/fixtures/completion/snaps/test@bracket_strong_delta.typ.snap index 79c4cf29..5ea49e54 100644 --- a/crates/tinymist-query/src/fixtures/completion/snaps/test@bracket_strong_delta.typ.snap +++ b/crates/tinymist-query/src/fixtures/completion/snaps/test@bracket_strong_delta.typ.snap @@ -1,6 +1,6 @@ --- source: crates/tinymist-query/src/completion.rs -description: "Completion on ] (52..53)" +description: Completion on / (29..30) expression: "JsonRepr::new_pure(results)" input_file: crates/tinymist-query/src/fixtures/completion/bracket_strong_delta.typ --- @@ -19,11 +19,11 @@ input_file: crates/tinymist-query/src/fixtures/completion/bracket_strong_delta.t "newText": "delta: ${1:})", "range": { "end": { - "character": 31, + "character": 8, "line": 2 }, "start": { - "character": 31, + "character": 8, "line": 2 } } diff --git a/crates/tinymist-query/src/fixtures/completion/snaps/test@bracket_strong_delta2.typ.snap b/crates/tinymist-query/src/fixtures/completion/snaps/test@bracket_strong_delta2.typ.snap index 91251ed9..52e9b5ec 100644 --- a/crates/tinymist-query/src/fixtures/completion/snaps/test@bracket_strong_delta2.typ.snap +++ b/crates/tinymist-query/src/fixtures/completion/snaps/test@bracket_strong_delta2.typ.snap @@ -1,6 +1,6 @@ --- source: crates/tinymist-query/src/completion.rs -description: "Completion on ] (52..53)" +description: Completion on / (29..30) expression: "JsonRepr::new_pure(results)" input_file: crates/tinymist-query/src/fixtures/completion/bracket_strong_delta2.typ --- @@ -19,11 +19,11 @@ input_file: crates/tinymist-query/src/fixtures/completion/bracket_strong_delta2. "newText": "delta: ${1:}", "range": { "end": { - "character": 31, + "character": 8, "line": 2 }, "start": { - "character": 31, + "character": 8, "line": 2 } }