feat: go to definition of include paths (#156)

This commit is contained in:
Myriad-Dreamin 2024-04-04 11:11:23 +08:00 committed by GitHub
parent 36eea552ac
commit 1c5c6bd929
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 36 additions and 13 deletions

View file

@ -200,6 +200,7 @@ impl<'a, 'b, 'w> DefUseCollector<'a, 'b, 'w> {
for e in e {
match &e.info.kind {
LexicalKind::Heading(..) => unreachable!(),
LexicalKind::Mod(LexicalModKind::PathInclude) => {}
LexicalKind::Var(LexicalVarKind::Label) => {
self.insert(Ns::Label, e);
}

View file

@ -102,7 +102,7 @@ impl StatefulRequest for CompletionRequest {
match_ident = Some(v);
}
}
Some(DerefTarget::ImportPath(v)) => {
Some(DerefTarget::ImportPath(v) | DerefTarget::IncludePath(v)) => {
if !v.text().starts_with(r#""@"#) {
completion_result = complete_path(ctx, v, &source, cursor);
}

View file

@ -7,8 +7,8 @@ use typst::syntax::FileId as TypstFileId;
use crate::{
prelude::*,
syntax::{
find_source_by_import, get_deref_target, DerefTarget, IdentRef, LexicalKind,
LexicalModKind, LexicalVarKind,
find_source_by_expr, get_deref_target, DerefTarget, IdentRef, LexicalKind, LexicalModKind,
LexicalVarKind,
},
SemanticRequest,
};
@ -95,8 +95,8 @@ pub(crate) fn find_definition(
DerefTarget::ImportPath(path) => {
let parent = path.parent()?;
let def_fid = parent.span().id()?;
let e = parent.cast::<ast::ModuleImport>()?;
let source = find_source_by_import(ctx.world(), def_fid, e)?;
let import_node = parent.cast::<ast::ModuleImport>()?;
let source = find_source_by_expr(ctx.world(), def_fid, import_node.source())?;
return Some(DefinitionLink {
kind: LexicalKind::Mod(LexicalModKind::PathVar),
name: String::new(),
@ -106,6 +106,20 @@ pub(crate) fn find_definition(
name_range: None,
});
}
DerefTarget::IncludePath(path) => {
let parent = path.parent()?;
let def_fid = parent.span().id()?;
let include_node = parent.cast::<ast::ModuleInclude>()?;
let source = find_source_by_expr(ctx.world(), def_fid, include_node.source())?;
return Some(DefinitionLink {
kind: LexicalKind::Mod(LexicalModKind::PathInclude),
name: String::new(),
value: None,
fid: source.id(),
def_range: (LinkedNode::new(source.root())).range(),
name_range: None,
});
}
};
// syntatic definition
@ -177,6 +191,7 @@ pub(crate) fn find_definition(
| LexicalKind::Mod(
LexicalModKind::Module(..)
| LexicalModKind::PathVar
| LexicalModKind::PathInclude
| LexicalModKind::ModuleAlias
| LexicalModKind::Alias { .. }
| LexicalModKind::Ident,

View file

@ -48,7 +48,7 @@ pub(crate) fn find_references(
let node = match deref_target {
DerefTarget::VarAccess(node) => node,
DerefTarget::Callee(node) => node,
DerefTarget::ImportPath(..) => {
DerefTarget::ImportPath(..) | DerefTarget::IncludePath(..) => {
return None;
}
};

View file

@ -40,14 +40,13 @@ pub fn find_source_by_import_path(
}
/// Find a source instance by its import node.
pub fn find_source_by_import(
pub fn find_source_by_expr(
world: &dyn World,
current: TypstFileId,
import_node: ast::ModuleImport,
e: ast::Expr,
) -> Option<Source> {
// todo: this could be vaild: import("path.typ"), where v is parenthesized
let v = import_node.source();
match v {
match e {
ast::Expr::Str(s) => find_source_by_import_path(world, current, s.get().as_str()),
_ => None,
}

View file

@ -75,6 +75,9 @@ pub enum LexicalModKind {
/// `import "foo.typ"`
/// ^^^
PathVar,
/// `include "foo.typ"`
/// ^^^
PathInclude,
/// `import "foo": bar`
/// ^^^
Ident,

View file

@ -16,6 +16,7 @@ pub enum DerefTarget<'a> {
VarAccess(LinkedNode<'a>),
Callee(LinkedNode<'a>),
ImportPath(LinkedNode<'a>),
IncludePath(LinkedNode<'a>),
}
impl<'a> DerefTarget<'a> {
@ -24,6 +25,7 @@ impl<'a> DerefTarget<'a> {
DerefTarget::VarAccess(node) => node,
DerefTarget::Callee(node) => node,
DerefTarget::ImportPath(node) => node,
DerefTarget::IncludePath(node) => node,
}
}
}
@ -113,11 +115,14 @@ pub fn get_deref_target(node: LinkedNode, cursor: usize) -> Option<DerefTarget>
}
ast::Expr::Str(..) => {
let parent = ancestor.parent()?;
if parent.kind() != SyntaxKind::ModuleImport {
return None;
if parent.kind() == SyntaxKind::ModuleImport {
return Some(DerefTarget::ImportPath(ancestor.find(may_ident.span())?));
}
if parent.kind() == SyntaxKind::ModuleInclude {
return Some(DerefTarget::IncludePath(ancestor.find(may_ident.span())?));
}
return Some(DerefTarget::ImportPath(ancestor.find(may_ident.span())?));
return None;
}
ast::Expr::Import(..) => {
return None;