Fix autocomplete for functions in modules

This commit is contained in:
Laurenz 2023-08-07 16:15:38 +02:00
parent 07c80e9a81
commit b61eee4306

View File

@ -8,7 +8,9 @@ use unscanny::Scanner;
use super::analyze::analyze_labels; use super::analyze::analyze_labels;
use super::{analyze_expr, analyze_import, plain_docs_sentence, summarize_font_family}; use super::{analyze_expr, analyze_import, plain_docs_sentence, summarize_font_family};
use crate::doc::Frame; 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::{ use crate::syntax::{
ast, is_id_continue, is_id_start, is_ident, LinkedNode, Source, SyntaxKind, 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(grand) = parent.parent();
if let Some(expr) = grand.cast::<ast::Expr>(); if let Some(expr) = grand.cast::<ast::Expr>();
let set = matches!(expr, ast::Expr::Set(_)); 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::FuncCall(call) => Some(call.callee()),
ast::Expr::Set(set) => Some(set.target()), ast::Expr::Set(set) => Some(set.target()),
_ => None, _ => None,
@ -669,16 +671,12 @@ fn complete_params(ctx: &mut CompletionContext) -> bool {
/// Add completions for the parameters of a function. /// Add completions for the parameters of a function.
fn param_completions( fn param_completions(
ctx: &mut CompletionContext, ctx: &mut CompletionContext,
callee: &ast::Ident, callee: &ast::Expr,
set: bool, set: bool,
exclude: &[ast::Ident], exclude: &[ast::Ident],
) { ) {
let info = if_chain! { let Some(func) = resolve_global_callee(ctx, callee) else { return };
if let Some(Value::Func(func)) = ctx.global.get(callee); let Some(info) = func.info() else { return };
if let Some(info) = func.info();
then { info }
else { return; }
};
for param in &info.params { for param in &info.params {
if exclude.iter().any(|ident| ident.as_str() == param.name) { 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. /// Add completions for the values of a named function parameter.
fn named_param_value_completions( fn named_param_value_completions(
ctx: &mut CompletionContext, ctx: &mut CompletionContext,
callee: &ast::Ident, callee: &ast::Expr,
name: &str, name: &str,
) { ) {
let param = if_chain! { let Some(func) = resolve_global_callee(ctx, callee) else { return };
if let Some(Value::Func(func)) = ctx.global.get(callee); let Some(info) = func.info() else { return };
if let Some(info) = func.info(); let Some(param) = info.param(name) else { return };
if let Some(param) = info.param(name); if !param.named {
if param.named; return;
then { param } }
else { return; }
};
ctx.cast_completions(&param.cast); ctx.cast_completions(&param.cast);
if name == "font" {
if callee.as_str() == "text" && name == "font" {
ctx.font_completions(); 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. /// Complete in code mode.
fn complete_code(ctx: &mut CompletionContext) -> bool { fn complete_code(ctx: &mut CompletionContext) -> bool {
if matches!( if matches!(