mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-07-24 13:13:43 +00:00
dev: prefer less uses of analzer_expr
during definition analysis (#192)
* dev: prefer less uses of `analzer_expr` during definition analysis * dev: improve pipeline of resolving syntactic definition
This commit is contained in:
parent
68ce4701c6
commit
a09c068d1d
2 changed files with 30 additions and 53 deletions
|
@ -74,62 +74,40 @@ pub fn find_definition(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// syntactic definition
|
// Lexical reference
|
||||||
let def_use = ctx.def_use(source)?;
|
|
||||||
let ident_ref = match use_site.cast::<ast::Expr>()? {
|
let ident_ref = match use_site.cast::<ast::Expr>()? {
|
||||||
ast::Expr::Ident(e) => IdentRef {
|
ast::Expr::Ident(e) => Some(IdentRef {
|
||||||
name: e.get().to_string(),
|
name: e.get().to_string(),
|
||||||
range: use_site.range(),
|
range: use_site.range(),
|
||||||
},
|
}),
|
||||||
ast::Expr::MathIdent(e) => IdentRef {
|
ast::Expr::MathIdent(e) => Some(IdentRef {
|
||||||
name: e.get().to_string(),
|
name: e.get().to_string(),
|
||||||
range: use_site.range(),
|
range: use_site.range(),
|
||||||
},
|
}),
|
||||||
ast::Expr::FieldAccess(..) => {
|
ast::Expr::FieldAccess(..) => {
|
||||||
debug!("find field access");
|
debug!("find field access");
|
||||||
return None;
|
|
||||||
|
None
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
debug!("unsupported kind {kind:?}", kind = use_site.kind());
|
debug!("unsupported kind {kind:?}", kind = use_site.kind());
|
||||||
return None;
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let def_id = def_use.get_ref(&ident_ref);
|
|
||||||
let def_id = def_id.or_else(|| Some(def_use.get_def(source_id, &ident_ref)?.0));
|
|
||||||
let def_info = def_id.and_then(|def_id| def_use.get_def_by_id(def_id));
|
|
||||||
|
|
||||||
let values = analyze_expr(ctx.world(), &use_site);
|
// Syntactic definition
|
||||||
for v in values {
|
let def_use = ctx.def_use(source);
|
||||||
// mostly builtin functions
|
let def_info = ident_ref
|
||||||
if let Value::Func(f) = v.0 {
|
.as_ref()
|
||||||
use typst::foundations::func::Repr;
|
.zip(def_use.as_ref())
|
||||||
match f.inner() {
|
.and_then(|(ident_ref, def_use)| {
|
||||||
// The with function should be resolved as the with position
|
let def_id = def_use.get_ref(ident_ref);
|
||||||
Repr::Closure(..) | Repr::With(..) => continue,
|
let def_id = def_id.or_else(|| Some(def_use.get_def(source_id, ident_ref)?.0))?;
|
||||||
Repr::Native(..) | Repr::Element(..) => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = f
|
def_use.get_def_by_id(def_id)
|
||||||
.name()
|
});
|
||||||
.or_else(|| def_info.as_ref().map(|(_, r)| r.name.as_str()));
|
|
||||||
|
|
||||||
if let Some(name) = name {
|
|
||||||
let span = f.span();
|
|
||||||
let fid = span.id()?;
|
|
||||||
let source = ctx.source_by_id(fid).ok()?;
|
|
||||||
|
|
||||||
return Some(DefinitionLink {
|
|
||||||
kind: LexicalKind::Var(LexicalVarKind::Function),
|
|
||||||
name: name.to_owned(),
|
|
||||||
value: Some(Value::Func(f.clone())),
|
|
||||||
// value: None,
|
|
||||||
def_at: Some((fid, source.find(span)?.range())),
|
|
||||||
name_range: def_info.map(|(_, r)| r.range.clone()),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Global definition
|
||||||
let Some((def_fid, def)) = def_info else {
|
let Some((def_fid, def)) = def_info else {
|
||||||
return resolve_global_value(ctx, use_site.clone(), false).and_then(move |f| {
|
return resolve_global_value(ctx, use_site.clone(), false).and_then(move |f| {
|
||||||
value_to_def(
|
value_to_def(
|
||||||
|
@ -191,14 +169,6 @@ pub fn find_definition(
|
||||||
/// Resolve a callee expression to a function.
|
/// Resolve a callee expression to a function.
|
||||||
pub fn resolve_callee(ctx: &mut AnalysisContext, callee: LinkedNode) -> Option<Func> {
|
pub fn resolve_callee(ctx: &mut AnalysisContext, callee: LinkedNode) -> Option<Func> {
|
||||||
{
|
{
|
||||||
let values = analyze_expr(ctx.world(), &callee);
|
|
||||||
|
|
||||||
values.into_iter().find_map(|v| match v.0 {
|
|
||||||
Value::Func(f) => Some(f),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
.or_else(|| {
|
|
||||||
let source = ctx.source_by_id(callee.span().id()?).ok()?;
|
let source = ctx.source_by_id(callee.span().id()?).ok()?;
|
||||||
let node = source.find(callee.span())?;
|
let node = source.find(callee.span())?;
|
||||||
let cursor = node.offset();
|
let cursor = node.offset();
|
||||||
|
@ -211,9 +181,17 @@ pub fn resolve_callee(ctx: &mut AnalysisContext, callee: LinkedNode) -> Option<F
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
.or_else(|| {
|
||||||
|
resolve_global_value(ctx, callee.clone(), false).and_then(|v| match v {
|
||||||
|
Value::Func(f) => Some(f),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
resolve_global_value(ctx, callee, false).and_then(|v| match v {
|
let values = analyze_expr(ctx.world(), &callee);
|
||||||
|
|
||||||
|
values.into_iter().find_map(|v| match v.0 {
|
||||||
Value::Func(f) => Some(f),
|
Value::Func(f) => Some(f),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
use log::debug;
|
|
||||||
use lsp_types::{InlayHintKind, InlayHintLabel};
|
use lsp_types::{InlayHintKind, InlayHintLabel};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -69,14 +68,14 @@ impl SemanticRequest for InlayHintRequest {
|
||||||
let range = ctx.to_typst_range(self.range, &source)?;
|
let range = ctx.to_typst_range(self.range, &source)?;
|
||||||
|
|
||||||
let hints = inlay_hint(ctx, &source, range, ctx.position_encoding()).ok()?;
|
let hints = inlay_hint(ctx, &source, range, ctx.position_encoding()).ok()?;
|
||||||
debug!(
|
log::debug!(
|
||||||
"got inlay hints on {source:?} => {hints:?}",
|
"got inlay hints on {source:?} => {hints:?}",
|
||||||
source = source.id(),
|
source = source.id(),
|
||||||
hints = hints.len()
|
hints = hints.len()
|
||||||
);
|
);
|
||||||
if hints.is_empty() {
|
if hints.is_empty() {
|
||||||
let root = LinkedNode::new(source.root());
|
let root = LinkedNode::new(source.root());
|
||||||
debug!("debug root {root:#?}");
|
log::debug!("debug root {root:#?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(hints)
|
Some(hints)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue