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 { for e in e {
match &e.info.kind { match &e.info.kind {
LexicalKind::Heading(..) => unreachable!(), LexicalKind::Heading(..) => unreachable!(),
LexicalKind::Mod(LexicalModKind::PathInclude) => {}
LexicalKind::Var(LexicalVarKind::Label) => { LexicalKind::Var(LexicalVarKind::Label) => {
self.insert(Ns::Label, e); self.insert(Ns::Label, e);
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -16,6 +16,7 @@ pub enum DerefTarget<'a> {
VarAccess(LinkedNode<'a>), VarAccess(LinkedNode<'a>),
Callee(LinkedNode<'a>), Callee(LinkedNode<'a>),
ImportPath(LinkedNode<'a>), ImportPath(LinkedNode<'a>),
IncludePath(LinkedNode<'a>),
} }
impl<'a> DerefTarget<'a> { impl<'a> DerefTarget<'a> {
@ -24,6 +25,7 @@ impl<'a> DerefTarget<'a> {
DerefTarget::VarAccess(node) => node, DerefTarget::VarAccess(node) => node,
DerefTarget::Callee(node) => node, DerefTarget::Callee(node) => node,
DerefTarget::ImportPath(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(..) => { ast::Expr::Str(..) => {
let parent = ancestor.parent()?; let parent = ancestor.parent()?;
if parent.kind() != SyntaxKind::ModuleImport { if parent.kind() == SyntaxKind::ModuleImport {
return None; 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(..) => { ast::Expr::Import(..) => {
return None; return None;