diff --git a/crates/tinymist-query/src/analysis/global.rs b/crates/tinymist-query/src/analysis/global.rs index 693b49ff..d185ea63 100644 --- a/crates/tinymist-query/src/analysis/global.rs +++ b/crates/tinymist-query/src/analysis/global.rs @@ -19,8 +19,7 @@ use typst::{model::Document, text::Font}; use crate::analysis::prelude::*; use crate::analysis::{ analyze_bib, analyze_expr_, analyze_import_, analyze_signature, post_type_check, BibInfo, - DefUseInfo, DefinitionLink, DocString, ImportInfo, PathPreference, Signature, SignatureTarget, - Ty, TypeScheme, + DefUseInfo, DocString, ImportInfo, PathPreference, Signature, SignatureTarget, Ty, TypeScheme, }; use crate::docs::{DocStringKind, SignatureDocs}; use crate::syntax::{ @@ -574,15 +573,8 @@ impl<'w> AnalysisContext<'w> { res } - pub(crate) fn signature_docs( - &mut self, - source: &Source, - def_ident: Option<&IdentRef>, - runtime_fn: &Value, - ) -> Option { - let def_use = self.def_use(source.clone())?; - let ty_chk = self.type_check(source)?; - crate::docs::signature_docs(self, Some(&(def_use, ty_chk)), def_ident, runtime_fn, None) + pub(crate) fn signature_docs(&mut self, runtime_fn: &Value) -> Option { + crate::docs::signature_docs(self, runtime_fn, None) } pub(crate) fn compute_docstring( @@ -739,28 +731,6 @@ impl<'w> AnalysisContext<'w> { self.type_of_span(rr.span()) } - pub(crate) fn user_type_of_ident( - &mut self, - source: &Source, - def_fid: TypstFileId, - def_ident: &IdentRef, - ) -> Option { - let ty_chk = self.type_check(source)?; - let def_use = self.def_use(source.clone())?; - - let (def_id, _) = def_use.get_def(def_fid, def_ident)?; - ty_chk.type_of_def(def_id) - } - - pub(crate) fn user_type_of_def(&mut self, source: &Source, def: &DefinitionLink) -> Option { - let def_at = def.def_at.clone()?; - let def_ident = IdentRef { - name: def.name.clone(), - range: def_at.1, - }; - self.user_type_of_ident(source, def_at.0, &def_ident) - } - pub(crate) fn type_of_span(&mut self, s: Span) -> Option { let id = s.id()?; let source = self.source_by_id(id).ok()?; diff --git a/crates/tinymist-query/src/analysis/post_tyck.rs b/crates/tinymist-query/src/analysis/post_tyck.rs index c150c343..38ca8dc9 100644 --- a/crates/tinymist-query/src/analysis/post_tyck.rs +++ b/crates/tinymist-query/src/analysis/post_tyck.rs @@ -13,18 +13,11 @@ use crate::syntax::{get_check_target, get_check_target_by_context, CheckTarget, /// With given type information, check the type of a literal expression again by /// touching the possible related nodes. pub(crate) fn post_type_check( - _ctx: &mut AnalysisContext, + ctx: &mut AnalysisContext, info: &TypeScheme, node: LinkedNode, ) -> Option { - let mut worker = PostTypeCheckWorker { - ctx: _ctx, - checked: HashMap::new(), - locals: TypeScheme::default(), - info, - }; - - worker.check(&node) + PostTypeChecker::new(ctx, info).check(&node) } #[derive(Default)] @@ -54,7 +47,7 @@ impl SignatureReceiver { fn check_signature<'a>( receiver: &'a mut SignatureReceiver, target: &'a ParamTarget, -) -> impl FnMut(&mut PostTypeCheckWorker, Sig, &[Interned], bool) -> Option<()> + 'a { +) -> impl FnMut(&mut PostTypeChecker, Sig, &[Interned], bool) -> Option<()> + 'a { move |worker, sig, args, pol| { let SigShape { sig: sig_ins, .. } = sig.shape(worker)?; @@ -99,16 +92,14 @@ fn check_signature<'a>( } } -// #[derive(BindTyCtx)] -// #[bind(info)] -struct PostTypeCheckWorker<'a, 'w> { +pub(crate) struct PostTypeChecker<'a, 'w> { ctx: &'a mut AnalysisContext<'w>, - checked: HashMap>, info: &'a TypeScheme, + checked: HashMap>, locals: TypeScheme, } -impl<'a, 'w> TyCtx for PostTypeCheckWorker<'a, 'w> { +impl<'a, 'w> TyCtx for PostTypeChecker<'a, 'w> { fn global_bounds(&self, var: &Interned, pol: bool) -> Option { self.info.global_bounds(var, pol) } @@ -118,7 +109,7 @@ impl<'a, 'w> TyCtx for PostTypeCheckWorker<'a, 'w> { } } -impl<'a, 'w> TyCtxMut for PostTypeCheckWorker<'a, 'w> { +impl<'a, 'w> TyCtxMut for PostTypeChecker<'a, 'w> { type Snap = ::Snap; fn start_scope(&mut self) -> Self::Snap { @@ -142,7 +133,16 @@ impl<'a, 'w> TyCtxMut for PostTypeCheckWorker<'a, 'w> { } } -impl<'a, 'w> PostTypeCheckWorker<'a, 'w> { +impl<'a, 'w> PostTypeChecker<'a, 'w> { + pub fn new(ctx: &'a mut AnalysisContext<'w>, info: &'a TypeScheme) -> Self { + Self { + ctx, + info, + checked: HashMap::new(), + locals: TypeScheme::default(), + } + } + fn check(&mut self, node: &LinkedNode) -> Option { let span = node.span(); if let Some(ty) = self.checked.get(&span) { @@ -341,7 +341,7 @@ impl<'a, 'w> PostTypeCheckWorker<'a, 'w> { trait PostSigChecker { fn check( &mut self, - checker: &mut PostTypeCheckWorker, + checker: &mut PostTypeChecker, sig: Sig, args: &[Interned], pol: bool, @@ -350,11 +350,11 @@ trait PostSigChecker { impl PostSigChecker for T where - T: FnMut(&mut PostTypeCheckWorker, Sig, &[Interned], bool) -> Option<()>, + T: FnMut(&mut PostTypeChecker, Sig, &[Interned], bool) -> Option<()>, { fn check( &mut self, - checker: &mut PostTypeCheckWorker, + checker: &mut PostTypeChecker, sig: Sig, args: &[Interned], pol: bool, @@ -365,7 +365,7 @@ where #[derive(BindTyCtx)] #[bind(0)] -struct PostSigCheckWorker<'x, 'a, 'w, T>(&'x mut PostTypeCheckWorker<'a, 'w>, &'x mut T); +struct PostSigCheckWorker<'x, 'a, 'w, T>(&'x mut PostTypeChecker<'a, 'w>, &'x mut T); impl<'x, 'a, 'w, T: PostSigChecker> SigChecker for PostSigCheckWorker<'x, 'a, 'w, T> { fn check( diff --git a/crates/tinymist-query/src/analysis/signature.rs b/crates/tinymist-query/src/analysis/signature.rs index 31feccea..3cd5fc53 100644 --- a/crates/tinymist-query/src/analysis/signature.rs +++ b/crates/tinymist-query/src/analysis/signature.rs @@ -3,6 +3,7 @@ use typst::foundations::{self, Closure, ParamInfo}; use super::{prelude::*, resolve_callee, BuiltinTy, SigTy, TypeSources}; +use crate::analysis::PostTypeChecker; use crate::docs::UntypedSymbolDocs; use crate::syntax::get_non_strict_def_target; use crate::upstream::truncated_repr; @@ -104,6 +105,13 @@ impl Signature { } } + /// Returns the all parameters of the function. + pub(crate) fn params(&self) -> impl Iterator)> { + let primary = self.primary().params(); + // todo: with stack + primary + } + pub(crate) fn type_sig(&self) -> Interned { let primary = self.primary().sig_ty.clone(); // todo: with stack @@ -166,6 +174,22 @@ impl PrimarySignature { self.has_spread_right() .then(|| &self.param_specs[self.pos_size() + self.sig_ty.names.names.len()]) } + + /// Returns the all parameters of the function. + pub fn params(&self) -> impl Iterator)> { + let pos = self.pos(); + let named = self.named(); + let rest = self.rest(); + let type_sig = &self.sig_ty; + let pos = pos + .iter() + .enumerate() + .map(|(i, pos)| (pos, type_sig.pos(i))); + let named = named.iter().map(|x| (x, type_sig.named(&x.name))); + let rest = rest.into_iter().map(|x| (x, type_sig.rest_param())); + + pos.chain(named).chain(rest) + } } /// Describes a function argument instance @@ -247,7 +271,7 @@ fn analyze_type_signature( let type_var = srcs.into_iter().next()?; match type_var { TypeSources::Var(v) => { - let sig_ty = ty.sig_repr(true)?; + let sig_ty = ty.sig_repr(true, &mut PostTypeChecker::new(ctx, &type_info))?; let docstring = match type_info.var_docs.get(&v.def).map(|x| x.as_ref()) { Some(UntypedSymbolDocs::Function(sig)) => sig, diff --git a/crates/tinymist-query/src/docs/package.rs b/crates/tinymist-query/src/docs/package.rs index 9efcf4c7..7c6815d9 100644 --- a/crates/tinymist-query/src/docs/package.rs +++ b/crates/tinymist-query/src/docs/package.rs @@ -13,7 +13,6 @@ use typst::syntax::{FileId, Span, VirtualPath}; use typst::World; use crate::docs::{file_id_repr, module_docs, symbol_docs, SymbolDocs, SymbolsInfo}; -use crate::syntax::IdentRef; use crate::ty::Ty; use crate::AnalysisContext; @@ -112,15 +111,6 @@ pub fn package_docs( log::debug!("module: {primary} -- {parent_ident}"); - let type_info = None.or_else(|| { - let file_id = fid?; - let src = world.source(file_id).ok()?; - let def_use = ctx.def_use(src.clone())?; - let ty_chck = ctx.type_check(&src)?; - Some((def_use, ty_chck)) - }); - let type_info = type_info.as_ref(); - let persist_fid = fid.map(|f| file_ids.insert_full(f).0); #[derive(Serialize)] @@ -157,15 +147,9 @@ pub fn package_docs( }); sym.head.loc = span; - let def_ident = sym.head.name_range.as_ref().map(|range| IdentRef { - name: sym.head.name.clone(), - range: range.clone(), - }); let docs = symbol_docs( ctx, - type_info, sym.head.kind, - def_ident.as_ref(), sym.head.value.as_ref(), sym.head.docs.as_deref(), Some(&mut doc_ty), diff --git a/crates/tinymist-query/src/docs/symbol.rs b/crates/tinymist-query/src/docs/symbol.rs index 855937e6..21d8bbc8 100644 --- a/crates/tinymist-query/src/docs/symbol.rs +++ b/crates/tinymist-query/src/docs/symbol.rs @@ -16,7 +16,6 @@ use typst::{ use super::tidy::*; use crate::analysis::{ParamAttrs, ParamSpec}; use crate::docs::library; -use crate::syntax::IdentRef; use crate::ty::Interned; use crate::{ty::Ty, AnalysisContext}; @@ -95,14 +94,12 @@ impl SymbolDocsT { pub(crate) fn symbol_docs( ctx: &mut AnalysisContext, - type_info: Option<&TypeInfo>, kind: DocStringKind, - def_ident: Option<&IdentRef>, sym_value: Option<&Value>, docs: Option<&str>, doc_ty: Option, ) -> Result { - let signature = sym_value.and_then(|e| signature_docs(ctx, type_info, def_ident, e, doc_ty)); + let signature = sym_value.and_then(|e| signature_docs(ctx, e, doc_ty)); if let Some(signature) = signature { return Ok(SymbolDocs::Function(Box::new(signature))); } @@ -237,8 +234,6 @@ impl ParamDocs { } } -type TypeInfo = (Arc, Arc); - fn format_ty(ty: Option<&Ty>, doc_ty: Option<&mut ShowTypeRepr>) -> TypeRepr { match doc_ty { Some(doc_ty) => doc_ty(ty), @@ -250,8 +245,6 @@ fn format_ty(ty: Option<&Ty>, doc_ty: Option<&mut ShowTypeRepr>) -> TypeRepr { pub(crate) fn signature_docs( ctx: &mut AnalysisContext, - type_info: Option<&TypeInfo>, - def_ident: Option<&IdentRef>, runtime_fn: &Value, mut doc_ty: Option, ) -> Option { @@ -278,35 +271,22 @@ pub(crate) fn signature_docs( } let sig = ctx.signature_dyn(func.clone()); - let def_id = type_info.and_then(|(def_use, _)| { - let def_fid = func.span().id()?; - let (def_id, _) = def_use.get_def(def_fid, def_ident?)?; - Some(def_id) - }); - let docstring = type_info.and_then(|(_, ty_chk)| ty_chk.var_docs.get(&def_id?)); - let type_sig = type_info.and_then(|(_, ty_chk)| ty_chk.type_of_def(def_id?)); - let type_sig = type_sig.and_then(|type_sig| type_sig.sig_repr(true)); + let type_sig = sig.type_sig().clone(); let pos_in = sig .primary() .pos() .iter() .enumerate() - .map(|(i, pos)| (pos, type_sig.as_ref().and_then(|sig| sig.pos(i)))); + .map(|(i, pos)| (pos, type_sig.pos(i))); let named_in = sig .primary() .named() .iter() - .map(|x| (x, type_sig.as_ref().and_then(|sig| sig.named(&x.name)))); - let rest_in = sig - .primary() - .rest() - .map(|x| (x, type_sig.as_ref().and_then(|sig| sig.rest_param()))); + .map(|x| (x, type_sig.named(&x.name))); + let rest_in = sig.primary().rest().map(|x| (x, type_sig.rest_param())); - let ret_in = type_sig - .as_ref() - .and_then(|sig| sig.body.as_ref()) - .or_else(|| sig.primary().sig_ty.body.as_ref()); + let ret_in = type_sig.body.as_ref(); let pos = pos_in .map(|(param, ty)| ParamDocs::new(param, ty, doc_ty.as_mut())) @@ -324,7 +304,7 @@ pub(crate) fn signature_docs( let ret_ty = format_ty(ret_in, doc_ty.as_mut()); Some(SignatureDocs { - docs: docstring.map(|x| x.docs().clone()).unwrap_or_default(), + docs: sig.primary().docs.clone().unwrap_or_default(), pos, named, rest, diff --git a/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_named.typ.snap b/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_named.typ.snap index 92041d59..06c95de2 100644 --- a/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_named.typ.snap +++ b/crates/tinymist-query/src/fixtures/call_info/snaps/test@user_named.typ.snap @@ -3,4 +3,5 @@ source: crates/tinymist-query/src/analysis.rs expression: CallSnapshot(result.as_deref()) input_file: crates/tinymist-query/src/fixtures/call_info/user_named.typ --- - +y: 1 -> CallParamInfo { kind: Named, is_content_block: false, param_name: "y" } +1 -> CallParamInfo { kind: Positional, is_content_block: false, param_name: "x" } diff --git a/crates/tinymist-query/src/fixtures/hover/snaps/test@annotate_fn.typ.snap b/crates/tinymist-query/src/fixtures/hover/snaps/test@annotate_fn.typ.snap index 4da70af6..16ea49b2 100644 --- a/crates/tinymist-query/src/fixtures/hover/snaps/test@annotate_fn.typ.snap +++ b/crates/tinymist-query/src/fixtures/hover/snaps/test@annotate_fn.typ.snap @@ -4,6 +4,6 @@ expression: "JsonRepr::new_redacted(result, &REDACT_LOC)" input_file: crates/tinymist-query/src/fixtures/hover/annotate_fn.typ --- { - "contents": "```typc\nlet touying-fn-wrapper(fn: (..: []) => any | function, ..args: arguments, max-repetitions: int | none = none, repetitions: int | none = none);\n```\n\n---\n\n\n #let fn = `(..fn-args) => any`;\n\n - fn (function, fn): The `fn`.\n - max-repetitions (int): The `max-repetitions`.\n - repetitions (int): The `repetitions`.\n - args (any, fn-args): The `args`.", + "contents": "```typc\nlet touying-fn-wrapper(fn, ..args, max-repetitions = none, repetitions = none);\n```\n\n---\n\n\n #let fn = `(..fn-args) => any`;\n\n - fn (function, fn): The `fn`.\n - max-repetitions (int): The `max-repetitions`.\n - repetitions (int): The `repetitions`.\n - args (any, fn-args): The `args`.", "range": "8:20:8:38" } diff --git a/crates/tinymist-query/src/hover.rs b/crates/tinymist-query/src/hover.rs index cc139715..fa22873b 100644 --- a/crates/tinymist-query/src/hover.rs +++ b/crates/tinymist-query/src/hover.rs @@ -251,10 +251,7 @@ fn def_tooltip( Some(LspHoverContents::Array(results)) } LexicalKind::Var(LexicalVarKind::Function) => { - let sig = lnk - .value - .as_ref() - .and_then(|e| ctx.signature_docs(source, lnk.to_ident_ref().as_ref(), e)); + let sig = lnk.value.as_ref().and_then(|e| ctx.signature_docs(e)); results.push(MarkedString::LanguageString(LanguageString { language: "typc".to_owned(), diff --git a/crates/tinymist-query/src/signature_help.rs b/crates/tinymist-query/src/signature_help.rs index 47b0dfc7..5ecd0957 100644 --- a/crates/tinymist-query/src/signature_help.rs +++ b/crates/tinymist-query/src/signature_help.rs @@ -43,8 +43,6 @@ impl SemanticRequest for SignatureHelpRequest { let def_link = find_definition(ctx, source.clone(), None, deref_target)?; - let type_sig = ctx.user_type_of_def(&source, &def_link); - let documentation = DocTooltip::get(ctx, &def_link) .as_deref() .map(markdown_docs); @@ -63,13 +61,8 @@ impl SemanticRequest for SignatureHelpRequest { } let sig = ctx.signature_dyn(function.clone()); - let pos = sig.primary().pos(); - let named = sig.primary().named(); - let rest = sig.primary().rest(); - let type_sig = type_sig.and_then(|type_sig| type_sig.sig_repr(true)); - - log::info!("got type signature {type_sig:?}"); + log::debug!("got signature {sig:?}"); let mut active_parameter = None; @@ -77,20 +70,10 @@ impl SemanticRequest for SignatureHelpRequest { let mut params = Vec::new(); label.push('('); - let pos = pos - .iter() - .enumerate() - .map(|(i, pos)| (pos, type_sig.as_ref().and_then(|sig| sig.pos(i)))); - let named = named - .iter() - .map(|x| (x, type_sig.as_ref().and_then(|sig| sig.named(&x.name)))); - let rest = rest - .into_iter() - .map(|x| (x, type_sig.as_ref().and_then(|sig| sig.rest_param()))); let mut real_offset = 0; let focus_name = OnceCell::new(); - for (i, (param, ty)) in pos.chain(named).chain(rest).enumerate() { + for (i, (param, ty)) in sig.params().enumerate() { if is_set && !param.attrs.settable { continue; } @@ -137,10 +120,7 @@ impl SemanticRequest for SignatureHelpRequest { }); } label.push(')'); - let ret = type_sig - .as_ref() - .and_then(|sig| sig.body.as_ref()) - .or_else(|| sig.primary().sig_ty.body.as_ref()); + let ret = sig.type_sig().body.clone(); if let Some(ret_ty) = ret { label.push_str(" -> "); label.push_str(ret_ty.describe().as_deref().unwrap_or("any")); diff --git a/crates/tinymist-query/src/ty/sig.rs b/crates/tinymist-query/src/ty/sig.rs index 65360642..8c8aef46 100644 --- a/crates/tinymist-query/src/ty/sig.rs +++ b/crates/tinymist-query/src/ty/sig.rs @@ -97,7 +97,7 @@ impl Ty { } /// Get the signature representation of the given type. - pub fn sig_repr(&self, pol: bool) -> Option> { + pub fn sig_repr(&self, pol: bool, ctx: &mut impl TyCtxMut) -> Option> { // todo: union sig // let mut pos = vec![]; // let mut named = HashMap::new(); @@ -108,12 +108,12 @@ impl Ty { #[derive(BindTyCtx)] #[bind(0)] - struct SigReprDriver<'a, C: TyCtx>(&'a C, &'a mut Option>); + struct SigReprDriver<'a, C: TyCtxMut>(&'a mut C, &'a mut Option>); - impl SigChecker for SigReprDriver<'_, C> { + impl SigChecker for SigReprDriver<'_, C> { fn check(&mut self, sig: Sig, _ctx: &mut SigCheckContext, _pol: bool) -> Option<()> { // todo: bind type context - let sig = sig.shape(&mut ())?; + let sig = sig.shape(self.0)?; *self.1 = Some(sig.sig.clone()); Some(()) } @@ -123,7 +123,7 @@ impl Ty { pol, SigSurfaceKind::Call, // todo: bind type context - &mut SigReprDriver(&(), &mut primary), + &mut SigReprDriver(ctx, &mut primary), ); primary diff --git a/tests/e2e/main.rs b/tests/e2e/main.rs index d4b4f985..32fb8f8f 100644 --- a/tests/e2e/main.rs +++ b/tests/e2e/main.rs @@ -385,7 +385,7 @@ fn e2e() { }); let hash = replay_log(&tinymist_binary, &root.join("vscode")); - insta::assert_snapshot!(hash, @"siphash128_13:925d0549a37fe091a774d04fce8614e4"); + insta::assert_snapshot!(hash, @"siphash128_13:93099dba5af1df251bc257e227a2ee2"); } }