dev: complete labels with tolerating syntax error (#974)

This commit is contained in:
Myriad-Dreamin 2024-12-10 16:05:19 +08:00 committed by GitHub
parent 00195884de
commit 2f882378bc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 42 additions and 31 deletions

View file

@ -82,7 +82,7 @@ pub fn definition(
find_bib_definition(ctx, introspector, name)
.or_else(|| find_ref_definition(introspector, name, ref_expr))
}
DerefTarget::Normal(..) => None,
DerefTarget::LabelError(..) | DerefTarget::Normal(..) => None,
}
}

View file

@ -9,6 +9,7 @@ use super::{
TypeScheme, TypeVar,
};
use crate::syntax::{get_check_target, get_check_target_by_context, CheckTarget, ParamTarget};
use crate::ty::BuiltinTy;
/// With given type information, check the type of a literal expression again by
/// touching the possible related nodes.
@ -306,11 +307,12 @@ impl<'a> PostTypeChecker<'a> {
Some(resp.finalize())
}
CheckTarget::ImportPath(..) | CheckTarget::IncludePath(..) => Some(Ty::Builtin(
crate::ty::BuiltinTy::Path(crate::ty::PathPreference::Source {
BuiltinTy::Path(crate::ty::PathPreference::Source {
allow_package: true,
}),
)),
CheckTarget::Normal(target) => {
CheckTarget::LabelError(..) => Some(Ty::Builtin(BuiltinTy::Label)),
CheckTarget::Label(target) | CheckTarget::Normal(target) => {
let ty = self.check_context_or(&target, context_ty)?;
crate::log_debug_ct!("post check target normal: {ty:?}");
Some(ty)

View file

@ -1,6 +1,6 @@
---
source: crates/tinymist-query/src/completion.rs
description: Completion on t (43..44)
description: Completion on t (44..45)
expression: "JsonRepr::new_pure(results)"
input_file: crates/tinymist-query/src/fixtures/completion/complete_half_label.typ
snapshot_kind: text
@ -15,6 +15,7 @@ snapshot_kind: text
"labelDetails": {
"description": "H2"
},
"sortText": "001",
"textEdit": {
"newText": "test>",
"range": {

View file

@ -48,7 +48,7 @@ pub(crate) fn find_references(
) -> Option<Vec<LspLocation>> {
let finding_label = match target {
DerefTarget::VarAccess(..) | DerefTarget::Callee(..) => false,
DerefTarget::Label(..) | DerefTarget::Ref(..) => true,
DerefTarget::Label(..) | DerefTarget::LabelError(..) | DerefTarget::Ref(..) => true,
DerefTarget::ImportPath(..) | DerefTarget::IncludePath(..) | DerefTarget::Normal(..) => {
return None;
}

View file

@ -291,6 +291,7 @@ pub(crate) fn interpret_mode_at(mut leaf: Option<&LinkedNode>) -> InterpretMode
#[derive(Debug, Clone)]
pub enum DerefTarget<'a> {
Label(LinkedNode<'a>),
LabelError(LinkedNode<'a>),
Ref(LinkedNode<'a>),
VarAccess(LinkedNode<'a>),
Callee(LinkedNode<'a>),
@ -302,18 +303,23 @@ pub enum DerefTarget<'a> {
impl<'a> DerefTarget<'a> {
pub fn node(&self) -> &LinkedNode<'a> {
match self {
DerefTarget::Label(node) => node,
DerefTarget::Ref(node) => node,
DerefTarget::VarAccess(node) => node,
DerefTarget::Callee(node) => node,
DerefTarget::ImportPath(node) => node,
DerefTarget::IncludePath(node) => node,
DerefTarget::Normal(_, node) => node,
DerefTarget::Label(node)
| DerefTarget::LabelError(node)
| DerefTarget::Ref(node)
| DerefTarget::VarAccess(node)
| DerefTarget::Callee(node)
| DerefTarget::ImportPath(node)
| DerefTarget::IncludePath(node)
| DerefTarget::Normal(_, node) => node,
}
}
}
pub fn get_deref_target(node: LinkedNode, cursor: usize) -> Option<DerefTarget<'_>> {
if matches!(node.kind(), SyntaxKind::Error) && node.text().starts_with('<') {
return Some(DerefTarget::LabelError(node));
}
/// Skips trivia nodes that are on the same line as the cursor.
fn can_skip_trivia(node: &LinkedNode, cursor: usize) -> bool {
// A non-trivia node is our target so we stop at it.
@ -521,6 +527,8 @@ pub enum CheckTarget<'a> {
},
ImportPath(LinkedNode<'a>),
IncludePath(LinkedNode<'a>),
Label(LinkedNode<'a>),
LabelError(LinkedNode<'a>),
Normal(LinkedNode<'a>),
}
@ -533,7 +541,9 @@ impl<'a> CheckTarget<'a> {
ParamTarget::Named(node) => node.clone(),
},
CheckTarget::Paren { container, .. } => container.clone(),
CheckTarget::ImportPath(node)
CheckTarget::Label(node)
| CheckTarget::LabelError(node)
| CheckTarget::ImportPath(node)
| CheckTarget::IncludePath(node)
| CheckTarget::Normal(node) => node.clone(),
})
@ -607,6 +617,12 @@ pub fn get_check_target(node: LinkedNode) -> Option<CheckTarget<'_>> {
DerefTarget::Callee(callee) => {
return get_callee_target(callee, node);
}
DerefTarget::Label(node) => {
return Some(CheckTarget::Label(node));
}
DerefTarget::LabelError(node) => {
return Some(CheckTarget::LabelError(node));
}
DerefTarget::ImportPath(node) => {
return Some(CheckTarget::ImportPath(node));
}
@ -868,7 +884,7 @@ mod tests {
match kind {
Some(DerefTarget::VarAccess(..)) => 'v',
Some(DerefTarget::Normal(..)) => 'n',
Some(DerefTarget::Label(..)) => 'l',
Some(DerefTarget::Label(..) | DerefTarget::LabelError(..)) => 'l',
Some(DerefTarget::Ref(..)) => 'r',
Some(DerefTarget::Callee(..)) => 'c',
Some(DerefTarget::ImportPath(..)) => 'i',
@ -888,6 +904,7 @@ mod tests {
Some(CheckTarget::Paren { .. }) => 'P',
Some(CheckTarget::ImportPath(..)) => 'i',
Some(CheckTarget::IncludePath(..)) => 'I',
Some(CheckTarget::Label(..) | CheckTarget::LabelError(..)) => 'l',
Some(CheckTarget::Normal(..)) => 'n',
None => ' ',
}

View file

@ -40,8 +40,7 @@ pub fn autocomplete(
let _ = complete_comments(&mut ctx)
|| complete_type_and_syntax(&mut ctx).is_none() && {
crate::log_debug_ct!("continue after completing type and syntax");
complete_labels(&mut ctx)
|| complete_imports(&mut ctx)
complete_imports(&mut ctx)
|| complete_field_accesses(&mut ctx)
|| complete_markup(&mut ctx)
|| complete_math(&mut ctx)
@ -495,20 +494,6 @@ fn field_access_completions(
}
}
/// Complete labels.
fn complete_labels(ctx: &mut CompletionContext) -> bool {
// A label anywhere in code: "(<la|".
if (ctx.leaf.kind().is_error() && ctx.leaf.text().starts_with('<'))
|| ctx.leaf.kind() == SyntaxKind::Label
{
ctx.from = ctx.leaf.offset() + 1;
ctx.label_completions(false);
return true;
}
false
}
/// Complete imports.
fn complete_imports(ctx: &mut CompletionContext) -> bool {
// On the colon marker of an import list:

View file

@ -1475,7 +1475,13 @@ pub(crate) fn complete_type_and_syntax(ctx: &mut CompletionContext) -> Option<()
Some(CheckTarget::Normal(e)) if matches!(e.kind(), SyntaxKind::FieldAccess) => {
return None;
}
Some(CheckTarget::Paren { .. } | CheckTarget::Normal(..)) | None => {}
Some(
CheckTarget::Paren { .. }
| CheckTarget::Label(..)
| CheckTarget::LabelError(..)
| CheckTarget::Normal(..),
)
| None => {}
}
crate::log_debug_ct!("ctx.leaf {:?}", ctx.leaf.clone());