summaryrefslogtreecommitdiff
path: root/crates/typst-syntax
diff options
context:
space:
mode:
authorTulio Martins <113527485+tulio240@users.noreply.github.com>2024-05-30 04:56:40 -0300
committerGitHub <noreply@github.com>2024-05-30 07:56:40 +0000
commit06a925a0ee0e1e7b93428d8b4952512a2e48ed79 (patch)
tree02725b8b534eff798ba96949073edc6766f45fa6 /crates/typst-syntax
parent5f6d942519b36eb839a0a11e4ef3f1ea4013a8b5 (diff)
Add nested import syntax (#4228)
Co-authored-by: LuizAugustoPapa <luiz.papa@aluno.puc-rio.br> Co-authored-by: PepinhoJp <pepinho.jp@gmail.com> Co-authored-by: PgBiel <9021226+PgBiel@users.noreply.github.com>
Diffstat (limited to 'crates/typst-syntax')
-rw-r--r--crates/typst-syntax/src/ast.rs44
-rw-r--r--crates/typst-syntax/src/highlight.rs1
-rw-r--r--crates/typst-syntax/src/kind.rs3
-rw-r--r--crates/typst-syntax/src/parser.rs7
4 files changed, 48 insertions, 7 deletions
diff --git a/crates/typst-syntax/src/ast.rs b/crates/typst-syntax/src/ast.rs
index 01e0944d..1cd9cd42 100644
--- a/crates/typst-syntax/src/ast.rs
+++ b/crates/typst-syntax/src/ast.rs
@@ -2040,29 +2040,54 @@ impl<'a> ImportItems<'a> {
pub fn iter(self) -> impl DoubleEndedIterator<Item = ImportItem<'a>> {
self.0.children().filter_map(|child| match child.kind() {
SyntaxKind::RenamedImportItem => child.cast().map(ImportItem::Renamed),
- SyntaxKind::Ident => child.cast().map(ImportItem::Simple),
+ SyntaxKind::ImportItemPath => child.cast().map(ImportItem::Simple),
_ => Option::None,
})
}
}
+node! {
+ /// A path to a submodule's imported name: `a.b.c`.
+ ImportItemPath
+}
+
+impl<'a> ImportItemPath<'a> {
+ /// An iterator over the path's components.
+ pub fn iter(self) -> impl DoubleEndedIterator<Item = Ident<'a>> {
+ self.0.children().filter_map(SyntaxNode::cast)
+ }
+
+ /// The name of the imported item. This is the last segment in the path.
+ pub fn name(self) -> Ident<'a> {
+ self.iter().last().unwrap_or_default()
+ }
+}
+
/// An imported item, potentially renamed to another identifier.
#[derive(Debug, Copy, Clone, Hash)]
pub enum ImportItem<'a> {
/// A non-renamed import (the item's name in the scope is the same as its
/// name).
- Simple(Ident<'a>),
+ Simple(ImportItemPath<'a>),
/// A renamed import (the item was bound to a different name in the scope
/// than the one it was defined as).
Renamed(RenamedImportItem<'a>),
}
impl<'a> ImportItem<'a> {
+ /// The path to the imported item.
+ pub fn path(self) -> ImportItemPath<'a> {
+ match self {
+ Self::Simple(path) => path,
+ Self::Renamed(renamed_item) => renamed_item.path(),
+ }
+ }
+
/// The original name of the imported item, at its source. This will be the
/// equal to the bound name if the item wasn't renamed with 'as'.
pub fn original_name(self) -> Ident<'a> {
match self {
- Self::Simple(name) => name,
+ Self::Simple(path) => path.name(),
Self::Renamed(renamed_item) => renamed_item.original_name(),
}
}
@@ -2071,7 +2096,7 @@ impl<'a> ImportItem<'a> {
/// name, if it was renamed; otherwise, it's just its original name.
pub fn bound_name(self) -> Ident<'a> {
match self {
- Self::Simple(name) => name,
+ Self::Simple(path) => path.name(),
Self::Renamed(renamed_item) => renamed_item.new_name(),
}
}
@@ -2083,17 +2108,22 @@ node! {
}
impl<'a> RenamedImportItem<'a> {
- /// The original name of the imported item (`a` in `a as d`).
- pub fn original_name(self) -> Ident<'a> {
+ /// The path to the imported item.
+ pub fn path(self) -> ImportItemPath<'a> {
self.0.cast_first_match().unwrap_or_default()
}
+ /// The original name of the imported item (`a` in `a as d` or `c.b.a as d`).
+ pub fn original_name(self) -> Ident<'a> {
+ self.path().name()
+ }
+
/// The new name of the imported item (`d` in `a as d`).
pub fn new_name(self) -> Ident<'a> {
self.0
.children()
.filter_map(SyntaxNode::cast)
- .nth(1)
+ .last()
.unwrap_or_default()
}
}
diff --git a/crates/typst-syntax/src/highlight.rs b/crates/typst-syntax/src/highlight.rs
index b6aa9e8d..0c1f3d5f 100644
--- a/crates/typst-syntax/src/highlight.rs
+++ b/crates/typst-syntax/src/highlight.rs
@@ -277,6 +277,7 @@ pub fn highlight(node: &LinkedNode) -> Option<Tag> {
SyntaxKind::ForLoop => None,
SyntaxKind::ModuleImport => None,
SyntaxKind::ImportItems => None,
+ SyntaxKind::ImportItemPath => None,
SyntaxKind::RenamedImportItem => None,
SyntaxKind::ModuleInclude => None,
SyntaxKind::LoopBreak => None,
diff --git a/crates/typst-syntax/src/kind.rs b/crates/typst-syntax/src/kind.rs
index 4c3d178f..7505dbc6 100644
--- a/crates/typst-syntax/src/kind.rs
+++ b/crates/typst-syntax/src/kind.rs
@@ -262,6 +262,8 @@ pub enum SyntaxKind {
ModuleImport,
/// Items to import from a module: `a, b, c`.
ImportItems,
+ /// A path to an imported name from a submodule: `a.b.c`.
+ ImportItemPath,
/// A renamed import item: `a as d`.
RenamedImportItem,
/// A module include: `include "chapter1.typ"`.
@@ -488,6 +490,7 @@ impl SyntaxKind {
Self::ForLoop => "for-loop expression",
Self::ModuleImport => "`import` expression",
Self::ImportItems => "import items",
+ Self::ImportItemPath => "imported item path",
Self::RenamedImportItem => "renamed import item",
Self::ModuleInclude => "`include` expression",
Self::LoopBreak => "`break` expression",
diff --git a/crates/typst-syntax/src/parser.rs b/crates/typst-syntax/src/parser.rs
index d8ac1198..d341bca2 100644
--- a/crates/typst-syntax/src/parser.rs
+++ b/crates/typst-syntax/src/parser.rs
@@ -1003,6 +1003,13 @@ fn import_items(p: &mut Parser) {
p.unexpected();
}
+ // Nested import path: `a.b.c`
+ while p.eat_if(SyntaxKind::Dot) {
+ p.expect(SyntaxKind::Ident);
+ }
+
+ p.wrap(item_marker, SyntaxKind::ImportItemPath);
+
// Rename imported item.
if p.eat_if(SyntaxKind::As) {
p.expect(SyntaxKind::Ident);