mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-08-03 17:58:17 +00:00
docs: add a few comments to completion (#1084)
This commit is contained in:
parent
81d3ea64c2
commit
98c61d0023
11 changed files with 85 additions and 27 deletions
|
@ -95,22 +95,32 @@ pub struct CompletionFeat {
|
|||
}
|
||||
|
||||
impl CompletionFeat {
|
||||
pub(crate) fn any_ufcs(&self) -> bool {
|
||||
self.ufcs() || self.ufcs_left() || self.ufcs_right()
|
||||
}
|
||||
/// Whether to enable any postfix completion.
|
||||
pub(crate) fn postfix(&self) -> bool {
|
||||
self.postfix.unwrap_or(true)
|
||||
}
|
||||
|
||||
/// Whether to enable any ufcs completion.
|
||||
pub(crate) fn any_ufcs(&self) -> bool {
|
||||
self.ufcs() || self.ufcs_left() || self.ufcs_right()
|
||||
}
|
||||
|
||||
/// Whether to enable ufcs completion.
|
||||
pub(crate) fn ufcs(&self) -> bool {
|
||||
self.postfix() && self.postfix_ufcs.unwrap_or(true)
|
||||
}
|
||||
|
||||
/// Whether to enable ufcs completion (left variant).
|
||||
pub(crate) fn ufcs_left(&self) -> bool {
|
||||
self.postfix() && self.postfix_ufcs_left.unwrap_or(true)
|
||||
}
|
||||
|
||||
/// Whether to enable ufcs completion (right variant).
|
||||
pub(crate) fn ufcs_right(&self) -> bool {
|
||||
self.postfix() && self.postfix_ufcs_right.unwrap_or(true)
|
||||
}
|
||||
|
||||
/// Gets the postfix snippets.
|
||||
pub(crate) fn postfix_snippets(&self) -> &EcoVec<PostfixSnippet> {
|
||||
self.postfix_snippets
|
||||
.as_ref()
|
||||
|
@ -189,6 +199,7 @@ impl<'a> CompletionCursor<'a> {
|
|||
)
|
||||
}
|
||||
|
||||
/// Whether the cursor is related to a callee item.
|
||||
fn is_callee(&self) -> bool {
|
||||
matches!(self.syntax, Some(SyntaxClass::Callee(..)))
|
||||
}
|
||||
|
@ -206,19 +217,7 @@ impl<'a> CompletionCursor<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
fn lsp_range_of(&mut self, rng: Range<usize>) -> LspRange {
|
||||
// self.ctx.to_lsp_range(rng, &self.source)
|
||||
if let Some((last_rng, last_lsp_rng)) = &self.last_lsp_range_pair {
|
||||
if *last_rng == rng {
|
||||
return *last_lsp_rng;
|
||||
}
|
||||
}
|
||||
|
||||
let lsp_rng = self.ctx.to_lsp_range(rng.clone(), &self.source);
|
||||
self.last_lsp_range_pair = Some((rng, lsp_rng));
|
||||
lsp_rng
|
||||
}
|
||||
|
||||
/// Gets the argument cursor.
|
||||
fn arg_cursor(&self) -> &Option<SyntaxNode> {
|
||||
self.arg_cursor.get_or_init(|| {
|
||||
let mut args_node = None;
|
||||
|
@ -249,6 +248,21 @@ impl<'a> CompletionCursor<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Gets the LSP range of a given range with caching.
|
||||
fn lsp_range_of(&mut self, rng: Range<usize>) -> LspRange {
|
||||
// self.ctx.to_lsp_range(rng, &self.source)
|
||||
if let Some((last_rng, last_lsp_rng)) = &self.last_lsp_range_pair {
|
||||
if *last_rng == rng {
|
||||
return *last_lsp_rng;
|
||||
}
|
||||
}
|
||||
|
||||
let lsp_rng = self.ctx.to_lsp_range(rng.clone(), &self.source);
|
||||
self.last_lsp_range_pair = Some((rng, lsp_rng));
|
||||
lsp_rng
|
||||
}
|
||||
|
||||
/// Makes a full completion item from a cursor-insensitive completion.
|
||||
fn lsp_item_of(&mut self, item: &Completion) -> LspCompletion {
|
||||
// Determine range to replace
|
||||
let mut snippet = item.apply.as_ref().unwrap_or(&item.label).clone();
|
||||
|
@ -289,6 +303,7 @@ impl<'a> CompletionCursor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Alias for a completion cursor, [`CompletionCursor`].
|
||||
type Cursor<'a> = CompletionCursor<'a>;
|
||||
|
||||
/// Autocomplete a cursor position in a source file.
|
||||
|
@ -426,7 +441,7 @@ impl<'a> CompletionWorker<'a> {
|
|||
worker: self,
|
||||
cursor,
|
||||
};
|
||||
let _ = pair.complete_root();
|
||||
let _ = pair.complete_cursor();
|
||||
|
||||
// Filter
|
||||
if let Some(from_ident) = cursor.ident_cursor() {
|
||||
|
@ -469,9 +484,11 @@ struct CompletionPair<'a, 'b, 'c> {
|
|||
type Pair<'a, 'b, 'c> = CompletionPair<'a, 'b, 'c>;
|
||||
|
||||
impl CompletionPair<'_, '_, '_> {
|
||||
pub(crate) fn complete_root(&mut self) -> Option<()> {
|
||||
/// Starts the completion on a cursor.
|
||||
pub(crate) fn complete_cursor(&mut self) -> Option<()> {
|
||||
use SurroundingSyntax::*;
|
||||
|
||||
// Special completions, we should remove them finally
|
||||
if matches!(
|
||||
self.cursor.leaf.kind(),
|
||||
SyntaxKind::LineComment | SyntaxKind::BlockComment
|
||||
|
@ -479,14 +496,18 @@ impl CompletionPair<'_, '_, '_> {
|
|||
return self.complete_comments().then_some(());
|
||||
}
|
||||
|
||||
let scope = self.cursor.surrounding_syntax;
|
||||
let surrounding_syntax = self.cursor.surrounding_syntax;
|
||||
let mode = interpret_mode_at(Some(&self.cursor.leaf));
|
||||
if matches!(scope, ImportList) {
|
||||
|
||||
// Special completions 2, we should remove them finally
|
||||
if matches!(surrounding_syntax, ImportList) {
|
||||
return self.complete_imports().then_some(());
|
||||
}
|
||||
|
||||
// Checks and completes `self.cursor.syntax_context`
|
||||
match self.cursor.syntax_context.clone() {
|
||||
Some(SyntaxContext::Element { container, .. }) => {
|
||||
// The existing dictionary fields are not interesting
|
||||
if let Some(container) = container.cast::<ast::Dict>() {
|
||||
for named in container.items() {
|
||||
if let ast::DictItem::Named(named) = named {
|
||||
|
@ -496,6 +517,7 @@ impl CompletionPair<'_, '_, '_> {
|
|||
};
|
||||
}
|
||||
Some(SyntaxContext::Arg { args, .. }) => {
|
||||
// The existing arguments are not interesting
|
||||
let args = args.cast::<ast::Args>()?;
|
||||
for arg in args.items() {
|
||||
if let ast::Arg::Named(named) = arg {
|
||||
|
@ -550,6 +572,7 @@ impl CompletionPair<'_, '_, '_> {
|
|||
| None => {}
|
||||
}
|
||||
|
||||
// Triggers a complete type checking.
|
||||
let ty = self
|
||||
.worker
|
||||
.ctx
|
||||
|
@ -557,11 +580,11 @@ impl CompletionPair<'_, '_, '_> {
|
|||
.filter(|ty| !matches!(ty, Ty::Any));
|
||||
|
||||
crate::log_debug_ct!(
|
||||
"complete_type: {:?} -> ({scope:?}, {ty:#?})",
|
||||
"complete_type: {:?} -> ({surrounding_syntax:?}, {ty:#?})",
|
||||
self.cursor.leaf
|
||||
);
|
||||
|
||||
// adjust the completion position
|
||||
// Adjusts the completion position
|
||||
// todo: syntax class seems not being considering `is_ident_like`
|
||||
// todo: merge ident_content_offset and label_content_offset
|
||||
if is_ident_like(&self.cursor.leaf) {
|
||||
|
@ -575,8 +598,9 @@ impl CompletionPair<'_, '_, '_> {
|
|||
self.cursor.from = offset;
|
||||
}
|
||||
|
||||
// Completion by types.
|
||||
if let Some(ty) = ty {
|
||||
let filter = |ty: &Ty| match scope {
|
||||
let filter = |ty: &Ty| match surrounding_syntax {
|
||||
SurroundingSyntax::StringContent => match ty {
|
||||
Ty::Builtin(BuiltinTy::Path(..) | BuiltinTy::TextFont) => true,
|
||||
Ty::Value(val) => matches!(val.val, Value::Str(..)),
|
||||
|
@ -593,8 +617,9 @@ impl CompletionPair<'_, '_, '_> {
|
|||
};
|
||||
ctx.type_completion(&ty, None);
|
||||
}
|
||||
|
||||
let mut type_completions = std::mem::take(&mut self.worker.completions);
|
||||
|
||||
// Completion by [`crate::syntax::InterpretMode`].
|
||||
match mode {
|
||||
InterpretMode::Code => {
|
||||
self.complete_code();
|
||||
|
@ -605,7 +630,7 @@ impl CompletionPair<'_, '_, '_> {
|
|||
InterpretMode::Raw => {
|
||||
self.complete_markup();
|
||||
}
|
||||
InterpretMode::Markup => match scope {
|
||||
InterpretMode::Markup => match surrounding_syntax {
|
||||
Regular => {
|
||||
self.complete_markup();
|
||||
}
|
||||
|
@ -617,7 +642,8 @@ impl CompletionPair<'_, '_, '_> {
|
|||
InterpretMode::Comment | InterpretMode::String => {}
|
||||
};
|
||||
|
||||
match scope {
|
||||
// Snippet completions associated by surrounding_syntax.
|
||||
match surrounding_syntax {
|
||||
Regular | StringContent | ImportList | SetRule => {}
|
||||
Selector => {
|
||||
self.snippet_completion(
|
||||
|
@ -653,6 +679,7 @@ impl CompletionPair<'_, '_, '_> {
|
|||
}
|
||||
}
|
||||
|
||||
// todo: filter completions by type
|
||||
// ctx.strict_scope_completions(false, |value| value.ty() == *ty);
|
||||
// let length_ty = Type::of::<Length>();
|
||||
// ctx.strict_scope_completions(false, |value| value.ty() == length_ty);
|
||||
|
@ -666,6 +693,7 @@ impl CompletionPair<'_, '_, '_> {
|
|||
self.worker.completions
|
||||
);
|
||||
|
||||
// Sorts completions
|
||||
type_completions.sort_by(|a, b| {
|
||||
a.sort_text
|
||||
.as_ref()
|
||||
|
@ -709,7 +737,7 @@ impl CompletionPair<'_, '_, '_> {
|
|||
if self.cursor.before.ends_with(',') || self.cursor.before.ends_with(':') {
|
||||
self.worker.enrich(" ", "");
|
||||
}
|
||||
match scope {
|
||||
match surrounding_syntax {
|
||||
Regular | ImportList | ShowTransform | SetRule | StringContent => {}
|
||||
Selector => {
|
||||
self.worker.enrich("", ": ${}");
|
||||
|
@ -721,6 +749,7 @@ impl CompletionPair<'_, '_, '_> {
|
|||
Some(())
|
||||
}
|
||||
|
||||
/// Pushes a cursor-insensitive completion item.
|
||||
fn push_completion(&mut self, completion: Completion) {
|
||||
self.worker
|
||||
.completions
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Completion for field access on nodes.
|
||||
|
||||
use super::*;
|
||||
impl CompletionPair<'_, '_, '_> {
|
||||
/// Add completions for all fields on a node.
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Completion for import items.
|
||||
|
||||
use super::*;
|
||||
impl CompletionPair<'_, '_, '_> {
|
||||
/// Complete imports.
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Completion kind analysis.
|
||||
|
||||
use super::*;
|
||||
|
||||
pub(crate) struct CompletionKindChecker {
|
||||
|
@ -6,11 +8,13 @@ pub(crate) struct CompletionKindChecker {
|
|||
}
|
||||
|
||||
impl CompletionKindChecker {
|
||||
/// Reset the checker status for a fresh checking.
|
||||
fn reset(&mut self) {
|
||||
self.symbols.clear();
|
||||
self.functions.clear();
|
||||
}
|
||||
|
||||
/// Check the completion kind of a type.
|
||||
pub fn check(&mut self, ty: &Ty) {
|
||||
self.reset();
|
||||
match ty {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Completion by [`crate::syntax::InterpretMode`].
|
||||
|
||||
use super::*;
|
||||
impl CompletionPair<'_, '_, '_> {
|
||||
/// Complete in comments. Or rather, don't!
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Completion of paths (string literal).
|
||||
|
||||
use super::*;
|
||||
impl CompletionPair<'_, '_, '_> {
|
||||
pub fn complete_path(&mut self, preference: &PathPreference) -> Option<Vec<CompletionItem>> {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Completion of definitions in scope.
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(BindTyCtx)]
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
//! Snippet completions.
|
||||
//!
|
||||
//! A prefix snippet is a snippet that completes non-existing items. For example
|
||||
//! `RR` is completed as `ℝ`.
|
||||
//!
|
||||
//! A postfix snippet is a snippet that modifies existing items by the dot
|
||||
//! accessor syntax. For example `$ RR.abs| $` is completed as `$ abs(RR) $`.
|
||||
|
||||
use super::*;
|
||||
|
||||
impl CompletionPair<'_, '_, '_> {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Completion by types.
|
||||
|
||||
use super::*;
|
||||
|
||||
pub(crate) struct TypeCompletionWorker<'a, 'b, 'c, 'd> {
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
//! Completion by typst specific semantics, like `font`, `package`, `label`, or
|
||||
//! `typst::foundations::Value`.
|
||||
|
||||
use super::*;
|
||||
impl CompletionPair<'_, '_, '_> {
|
||||
/// Add completions for all font families.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue