From b61eee4306f5d67c3f48874c45b7c846b31d9e21 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Mon, 7 Aug 2023 16:15:38 +0200 Subject: [PATCH] Fix autocomplete for functions in modules --- crates/typst/src/ide/complete.rs | 59 +++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/crates/typst/src/ide/complete.rs b/crates/typst/src/ide/complete.rs index b6992e19a..dcde0985c 100644 --- a/crates/typst/src/ide/complete.rs +++ b/crates/typst/src/ide/complete.rs @@ -8,7 +8,9 @@ use unscanny::Scanner; use super::analyze::analyze_labels; use super::{analyze_expr, analyze_import, plain_docs_sentence, summarize_font_family}; use crate::doc::Frame; -use crate::eval::{fields_on, format_str, methods_on, CastInfo, Library, Scope, Value}; +use crate::eval::{ + fields_on, format_str, methods_on, CastInfo, Func, Library, Scope, Value, +}; use crate::syntax::{ ast, is_id_continue, is_id_start, is_ident, LinkedNode, Source, SyntaxKind, }; @@ -606,7 +608,7 @@ fn complete_params(ctx: &mut CompletionContext) -> bool { if let Some(grand) = parent.parent(); if let Some(expr) = grand.cast::(); let set = matches!(expr, ast::Expr::Set(_)); - if let Some(ast::Expr::Ident(callee)) = match expr { + if let Some(callee) = match expr { ast::Expr::FuncCall(call) => Some(call.callee()), ast::Expr::Set(set) => Some(set.target()), _ => None, @@ -669,16 +671,12 @@ fn complete_params(ctx: &mut CompletionContext) -> bool { /// Add completions for the parameters of a function. fn param_completions( ctx: &mut CompletionContext, - callee: &ast::Ident, + callee: &ast::Expr, set: bool, exclude: &[ast::Ident], ) { - let info = if_chain! { - if let Some(Value::Func(func)) = ctx.global.get(callee); - if let Some(info) = func.info(); - then { info } - else { return; } - }; + let Some(func) = resolve_global_callee(ctx, callee) else { return }; + let Some(info) = func.info() else { return }; for param in &info.params { if exclude.iter().any(|ident| ident.as_str() == param.name) { @@ -711,21 +709,18 @@ fn param_completions( /// Add completions for the values of a named function parameter. fn named_param_value_completions( ctx: &mut CompletionContext, - callee: &ast::Ident, + callee: &ast::Expr, name: &str, ) { - let param = if_chain! { - if let Some(Value::Func(func)) = ctx.global.get(callee); - if let Some(info) = func.info(); - if let Some(param) = info.param(name); - if param.named; - then { param } - else { return; } - }; + let Some(func) = resolve_global_callee(ctx, callee) else { return }; + let Some(info) = func.info() else { return }; + let Some(param) = info.param(name) else { return }; + if !param.named { + return; + } ctx.cast_completions(¶m.cast); - - if callee.as_str() == "text" && name == "font" { + if name == "font" { ctx.font_completions(); } @@ -734,6 +729,30 @@ fn named_param_value_completions( } } +/// Resolve a callee expression to a global function. +fn resolve_global_callee<'a>( + ctx: &CompletionContext<'a>, + callee: &ast::Expr, +) -> Option<&'a Func> { + let value = match callee { + ast::Expr::Ident(ident) => ctx.global.get(ident)?, + ast::Expr::FieldAccess(access) => match access.target() { + ast::Expr::Ident(target) => match ctx.global.get(&target)? { + Value::Module(module) => module.get(&access.field()).ok()?, + Value::Func(func) => func.get(&access.field()).ok()?, + _ => return None, + }, + _ => return None, + }, + _ => return None, + }; + + match value { + Value::Func(func) => Some(func), + _ => None, + } +} + /// Complete in code mode. fn complete_code(ctx: &mut CompletionContext) -> bool { if matches!(