1use crate::diagnostics::{BuildDiagnostics, SourceFile, Spanned};
16use smol_str::{SmolStr, StrExt};
17use std::fmt::Display;
18
19mod document;
20mod element;
21mod expressions;
22mod statements;
23mod r#type;
24
25mod prelude {
27 #[cfg(test)]
28 pub use super::DefaultParser;
29 #[cfg(test)]
30 pub use super::{syntax_nodes, SyntaxNode, SyntaxNodeVerify};
31 pub use super::{Parser, SyntaxKind};
32 #[cfg(test)]
33 pub use i_slint_parser_test_macro::parser_test;
34}
35
36#[cfg(test)]
37pub trait SyntaxNodeVerify {
38 const KIND: SyntaxKind;
40 fn verify(node: SyntaxNode) {
43 assert_eq!(node.kind(), Self::KIND)
44 }
45}
46
47pub use rowan::{TextRange, TextSize};
48
49#[cfg(test)]
51macro_rules! verify_node {
52 ($node:ident, [ $($t1:tt $($t2:ident)?),* ]) => {
54 $(verify_node!(@check_has_children $node, $t1 $($t2)* );)*
56
57 for c in $node.children() {
59 assert!(
60 false $(|| c.kind() == verify_node!(@extract_kind $t1 $($t2)*))*,
61 "Node is none of [{}]\n{:?}", stringify!($($t1 $($t2)*),*) ,c);
62 }
63
64 $(
66 for _c in $node.children().filter(|n| n.kind() == verify_node!(@extract_kind $t1 $($t2)*)) {
67 <verify_node!(@extract_type $t1 $($t2)*)>::verify(_c)
68 }
69 )*
70 };
71
72 (@check_has_children $node:ident, * $kind:ident) => {};
74 (@check_has_children $node:ident, ? $kind:ident) => {
76 let count = $node.children_with_tokens().filter(|n| n.kind() == SyntaxKind::$kind).count();
77 assert!(count <= 1, "Expecting one or zero sub-node of type {}, found {}\n{:?}", stringify!($kind), count, $node);
78 };
79 (@check_has_children $node:ident, $kind:ident) => {
81 let count = $node.children_with_tokens().filter(|n| n.kind() == SyntaxKind::$kind).count();
82 assert_eq!(count, 1, "Expecting exactly one sub-node of type {}\n{:?}", stringify!($kind), $node);
83 };
84 (@check_has_children $node:ident, $count:literal $kind:ident) => {
86 let count = $node.children_with_tokens().filter(|n| n.kind() == SyntaxKind::$kind).count();
87 assert_eq!(count, $count, "Expecting {} sub-node of type {}, found {}\n{:?}", $count, stringify!($kind), count, $node);
88 };
89
90 (@extract_kind * $kind:ident) => {SyntaxKind::$kind};
91 (@extract_kind ? $kind:ident) => {SyntaxKind::$kind};
92 (@extract_kind $count:literal $kind:ident) => {SyntaxKind::$kind};
93 (@extract_kind $kind:ident) => {SyntaxKind::$kind};
94
95 (@extract_type * $kind:ident) => {$crate::parser::syntax_nodes::$kind};
96 (@extract_type ? $kind:ident) => {$crate::parser::syntax_nodes::$kind};
97 (@extract_type $count:literal $kind:ident) => {$crate::parser::syntax_nodes::$kind};
98 (@extract_type $kind:ident) => {$crate::parser::syntax_nodes::$kind};
99}
100
101macro_rules! node_accessors {
102 ([ $($t1:tt $($t2:ident)?),* ]) => {
104 $(node_accessors!{@ $t1 $($t2)*} )*
105 };
106
107 (@ * $kind:ident) => {
108 #[allow(non_snake_case)]
109 pub fn $kind(&self) -> impl Iterator<Item = $kind> {
110 self.0.children().filter(|n| n.kind() == SyntaxKind::$kind).map(Into::into)
111 }
112 };
113 (@ ? $kind:ident) => {
114 #[allow(non_snake_case)]
115 pub fn $kind(&self) -> Option<$kind> {
116 self.0.child_node(SyntaxKind::$kind).map(Into::into)
117 }
118 };
119 (@ 2 $kind:ident) => {
120 #[allow(non_snake_case)]
121 #[track_caller]
122 pub fn $kind(&self) -> ($kind, $kind) {
123 let mut it = self.0.children().filter(|n| n.kind() == SyntaxKind::$kind);
124 let a = it.next().expect(stringify!(Missing first $kind));
125 let b = it.next().expect(stringify!(Missing second $kind));
126 debug_assert!(it.next().is_none(), stringify!(More $kind than expected));
127 (a.into(), b.into())
128 }
129 };
130 (@ 3 $kind:ident) => {
131 #[allow(non_snake_case)]
132 #[track_caller]
133 pub fn $kind(&self) -> ($kind, $kind, $kind) {
134 let mut it = self.0.children().filter(|n| n.kind() == SyntaxKind::$kind);
135 let a = it.next().expect(stringify!(Missing first $kind));
136 let b = it.next().expect(stringify!(Missing second $kind));
137 let c = it.next().expect(stringify!(Missing third $kind));
138 debug_assert!(it.next().is_none(), stringify!(More $kind than expected));
139 (a.into(), b.into(), c.into())
140 }
141 };
142 (@ $kind:ident) => {
143 #[allow(non_snake_case)]
144 #[track_caller]
145 pub fn $kind(&self) -> $kind {
146 self.0.child_node(SyntaxKind::$kind).expect(stringify!(Missing $kind)).into()
147 }
148 };
149
150}
151
152macro_rules! declare_syntax {
184 ({
185 $($token:ident -> $rule:expr ,)*
186 }
187 {
188 $( $(#[$attr:meta])* $nodekind:ident -> $children:tt ,)*
189 })
190 => {
191 #[repr(u16)]
192 #[derive(Debug, Copy, Clone, Eq, PartialEq, num_enum::IntoPrimitive, num_enum::TryFromPrimitive, Hash, Ord, PartialOrd)]
193 pub enum SyntaxKind {
194 Error,
195 Eof,
196
197 $(
199 $token,
201 )*
202
203 $(
205 $(#[$attr])*
206 $nodekind,
207 )*
208 }
209
210 impl Display for SyntaxKind {
211 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
212 match self {
213 $(Self::$token => {
214 if let Some(character) = <dyn std::any::Any>::downcast_ref::<&str>(& $rule) {
215 return write!(f, "'{}'", character)
216 }
217 })*
218 _ => ()
219 }
220 write!(f, "{:?}", self)
221 }
222 }
223
224
225 pub fn lex_next_token(text : &str, state: &mut crate::lexer::LexState) -> Option<(usize, SyntaxKind)> {
227 use crate::lexer::LexingRule;
228 $(
229 let len = ($rule).lex(text, state);
230 if len > 0 {
231 return Some((len, SyntaxKind::$token));
232 }
233 )*
234 None
235 }
236
237 pub mod syntax_nodes {
238 use super::*;
239 $(
240 #[derive(Debug, Clone, derive_more::Deref, derive_more::Into)]
241 pub struct $nodekind(SyntaxNode);
242 #[cfg(test)]
243 impl SyntaxNodeVerify for $nodekind {
244 const KIND: SyntaxKind = SyntaxKind::$nodekind;
245 #[track_caller]
246 fn verify(node: SyntaxNode) {
247 assert_eq!(node.kind(), Self::KIND);
248 verify_node!(node, $children);
249 }
250 }
251 impl $nodekind {
252 node_accessors!{$children}
253
254 pub fn new(node: SyntaxNode) -> Option<Self> {
256 (node.kind() == SyntaxKind::$nodekind).then(|| Self(node))
257 }
258 }
259
260 impl From<SyntaxNode> for $nodekind {
261 #[track_caller]
262 fn from(node: SyntaxNode) -> Self {
263 assert_eq!(node.kind(), SyntaxKind::$nodekind);
264 Self(node)
265 }
266 }
267
268 impl Spanned for $nodekind {
269 fn span(&self) -> crate::diagnostics::Span {
270 self.0.span()
271 }
272
273 fn source_file(&self) -> Option<&SourceFile> {
274 self.0.source_file()
275 }
276 }
277 )*
278 }
279 }
280}
281declare_syntax! {
282 {
287 Whitespace -> &crate::lexer::lex_whitespace,
288 Comment -> &crate::lexer::lex_comment,
289 StringLiteral -> &crate::lexer::lex_string,
290 NumberLiteral -> &crate::lexer::lex_number,
291 ColorLiteral -> &crate::lexer::lex_color,
292 Identifier -> &crate::lexer::lex_identifier,
293 DoubleArrow -> "<=>",
294 PlusEqual -> "+=",
295 MinusEqual -> "-=",
296 StarEqual -> "*=",
297 DivEqual -> "/=",
298 LessEqual -> "<=",
299 GreaterEqual -> ">=",
300 EqualEqual -> "==",
301 NotEqual -> "!=",
302 ColonEqual -> ":=",
303 FatArrow -> "=>",
304 Arrow -> "->",
305 OrOr -> "||",
306 AndAnd -> "&&",
307 LBrace -> "{",
308 RBrace -> "}",
309 LParent -> "(",
310 RParent -> ")",
311 LAngle -> "<",
312 RAngle -> ">",
313 LBracket -> "[",
314 RBracket -> "]",
315 Plus -> "+",
316 Minus -> "-",
317 Star -> "*",
318 Div -> "/",
319 Equal -> "=",
320 Colon -> ":",
321 Comma -> ",",
322 Semicolon -> ";",
323 Bang -> "!",
324 Dot -> ".",
325 Question -> "?",
326 Dollar -> "$",
327 At -> "@",
328 Pipe -> "|",
329 Percent -> "%",
330 }
331 {
333 Document -> [ *Component, *ExportsList, *ImportSpecifier, *StructDeclaration, *EnumDeclaration ],
334 Component -> [ DeclaredIdentifier, Element ],
336 SubElement -> [ Element ],
338 Element -> [ ?QualifiedName, *PropertyDeclaration, *Binding, *CallbackConnection,
339 *CallbackDeclaration, *ConditionalElement, *Function, *SubElement,
340 *RepeatedElement, *PropertyAnimation, *PropertyChangedCallback,
341 *TwoWayBinding, *States, *Transitions, ?ChildrenPlaceholder ],
342 RepeatedElement -> [ ?DeclaredIdentifier, ?RepeatedIndex, Expression , SubElement],
343 RepeatedIndex -> [],
344 ConditionalElement -> [ Expression , SubElement],
345 CallbackDeclaration -> [ DeclaredIdentifier, *CallbackDeclarationParameter, ?ReturnType, ?TwoWayBinding ],
346 CallbackDeclarationParameter -> [ ?DeclaredIdentifier, Type],
348 Function -> [DeclaredIdentifier, *ArgumentDeclaration, ?ReturnType, CodeBlock ],
349 ArgumentDeclaration -> [DeclaredIdentifier, Type],
350 ReturnType -> [Type],
352 CallbackConnection -> [ *DeclaredIdentifier, CodeBlock ],
353 PropertyDeclaration-> [ ?Type , DeclaredIdentifier, ?BindingExpression, ?TwoWayBinding ],
355 PropertyAnimation-> [ *QualifiedName, *Binding ],
357 PropertyChangedCallback-> [ DeclaredIdentifier, CodeBlock ],
359 QualifiedName-> [],
361 DeclaredIdentifier -> [],
363 ChildrenPlaceholder -> [],
364 Binding-> [ BindingExpression ],
365 TwoWayBinding -> [ Expression ],
367 BindingExpression-> [ ?CodeBlock, ?Expression ],
370 CodeBlock-> [ *Expression, *ReturnStatement ],
371 ReturnStatement -> [ ?Expression ],
372 Expression-> [ ?Expression, ?FunctionCallExpression, ?IndexExpression, ?SelfAssignment,
374 ?ConditionalExpression, ?QualifiedName, ?BinaryExpression, ?Array, ?ObjectLiteral,
375 ?UnaryOpExpression, ?CodeBlock, ?StringTemplate, ?AtImageUrl, ?AtGradient, ?AtTr,
376 ?MemberAccess ],
377 StringTemplate -> [*Expression],
379 AtImageUrl -> [],
381 AtGradient -> [*Expression],
383 AtTr -> [?TrContext, ?TrPlural, *Expression],
385 TrContext -> [],
387 TrPlural -> [Expression],
389 FunctionCallExpression -> [*Expression],
391 IndexExpression -> [2 Expression],
393 SelfAssignment -> [2 Expression],
395 ConditionalExpression -> [3 Expression],
397 BinaryExpression -> [2 Expression],
399 UnaryOpExpression -> [Expression],
401 MemberAccess -> [Expression],
403 Array -> [ *Expression ],
405 ObjectLiteral -> [ *ObjectMember ],
407 ObjectMember -> [ Expression ],
409 States -> [*State],
411 State -> [DeclaredIdentifier, ?Expression, *StatePropertyChange, *Transition],
413 StatePropertyChange -> [ QualifiedName, BindingExpression ],
415 Transitions -> [*Transition],
417 Transition -> [?DeclaredIdentifier, *PropertyAnimation],
419 ExportsList -> [ *ExportSpecifier, ?Component, *StructDeclaration, ?ExportModule, *EnumDeclaration ],
421 ExportSpecifier -> [ ExportIdentifier, ?ExportName ],
424 ExportIdentifier -> [],
425 ExportName -> [],
426 ExportModule -> [],
428 ImportSpecifier -> [ ?ImportIdentifierList ],
430 ImportIdentifierList -> [ *ImportIdentifier ],
431 ImportIdentifier -> [ ExternalName, ?InternalName ],
433 ExternalName -> [],
434 InternalName -> [],
435 Type -> [ ?QualifiedName, ?ObjectType, ?ArrayType ],
437 ObjectType ->[ *ObjectTypeMember ],
439 ObjectTypeMember -> [ Type ],
441 ArrayType -> [ Type ],
443 StructDeclaration -> [DeclaredIdentifier, ObjectType, ?AtRustAttr],
445 EnumDeclaration -> [DeclaredIdentifier, *EnumValue, ?AtRustAttr],
447 EnumValue -> [],
449 AtRustAttr -> [],
451 }
452}
453
454impl From<SyntaxKind> for rowan::SyntaxKind {
455 fn from(v: SyntaxKind) -> Self {
456 rowan::SyntaxKind(v.into())
457 }
458}
459
460#[derive(Clone, Debug)]
461pub struct Token {
462 pub kind: SyntaxKind,
463 pub text: SmolStr,
464 pub offset: usize,
465 #[cfg(feature = "proc_macro_span")]
466 pub span: Option<proc_macro::Span>,
467}
468
469impl Default for Token {
470 fn default() -> Self {
471 Token {
472 kind: SyntaxKind::Eof,
473 text: Default::default(),
474 offset: 0,
475 #[cfg(feature = "proc_macro_span")]
476 span: None,
477 }
478 }
479}
480
481impl Token {
482 pub fn as_str(&self) -> &str {
483 self.text.as_str()
484 }
485
486 pub fn kind(&self) -> SyntaxKind {
487 self.kind
488 }
489}
490
491mod parser_trait {
492 use super::*;
494
495 pub trait Parser: Sized {
496 type Checkpoint: Clone;
497
498 #[must_use = "The node will be finished when it is dropped"]
504 fn start_node(&mut self, kind: SyntaxKind) -> Node<Self> {
505 self.start_node_impl(kind, None, NodeToken(()));
506 Node(self)
507 }
508 #[must_use = "use start_node_at to use this checkpoint"]
509 fn checkpoint(&mut self) -> Self::Checkpoint;
510 #[must_use = "The node will be finished when it is dropped"]
511 fn start_node_at(
512 &mut self,
513 checkpoint: impl Into<Option<Self::Checkpoint>>,
514 kind: SyntaxKind,
515 ) -> Node<Self> {
516 self.start_node_impl(kind, checkpoint.into(), NodeToken(()));
517 Node(self)
518 }
519
520 fn finish_node_impl(&mut self, token: NodeToken);
522 fn start_node_impl(
524 &mut self,
525 kind: SyntaxKind,
526 checkpoint: Option<Self::Checkpoint>,
527 token: NodeToken,
528 );
529
530 fn peek(&mut self) -> Token {
532 self.nth(0)
533 }
534 fn nth(&mut self, n: usize) -> Token;
536 fn consume(&mut self);
537 fn error(&mut self, e: impl Into<String>);
538 fn warning(&mut self, e: impl Into<String>);
539
540 fn expect(&mut self, kind: SyntaxKind) -> bool {
543 if !self.test(kind) {
544 self.error(format!("Syntax error: expected {}", kind));
545 return false;
546 }
547 true
548 }
549
550 fn test(&mut self, kind: SyntaxKind) -> bool {
552 if self.nth(0).kind() != kind {
553 return false;
554 }
555 self.consume();
556 true
557 }
558
559 fn until(&mut self, kind: SyntaxKind) {
561 let mut parens = 0;
562 let mut braces = 0;
563 let mut brackets = 0;
564 loop {
565 match self.nth(0).kind() {
566 k if k == kind && parens == 0 && braces == 0 && brackets == 0 => break,
567 SyntaxKind::Eof => break,
568 SyntaxKind::LParent => parens += 1,
569 SyntaxKind::LBrace => braces += 1,
570 SyntaxKind::LBracket => brackets += 1,
571 SyntaxKind::RParent if parens == 0 => break,
572 SyntaxKind::RParent => parens -= 1,
573 SyntaxKind::RBrace if braces == 0 => break,
574 SyntaxKind::RBrace => braces -= 1,
575 SyntaxKind::RBracket if brackets == 0 => break,
576 SyntaxKind::RBracket => brackets -= 1,
577 _ => {}
578 };
579 self.consume();
580 }
581 self.expect(kind);
582 }
583 }
584
585 pub struct NodeToken(());
590 #[derive(derive_more::DerefMut)]
593 pub struct Node<'a, P: Parser>(&'a mut P);
594 impl<'a, P: Parser> Drop for Node<'a, P> {
595 fn drop(&mut self) {
596 self.0.finish_node_impl(NodeToken(()));
597 }
598 }
599 impl<'a, P: Parser> core::ops::Deref for Node<'a, P> {
600 type Target = P;
601 fn deref(&self) -> &Self::Target {
602 self.0
603 }
604 }
605}
606#[doc(inline)]
607pub use parser_trait::*;
608
609pub struct DefaultParser<'a> {
610 builder: rowan::GreenNodeBuilder<'static>,
611 tokens: Vec<Token>,
612 cursor: usize,
613 diags: &'a mut BuildDiagnostics,
614 source_file: SourceFile,
615}
616
617impl<'a> DefaultParser<'a> {
618 fn from_tokens(tokens: Vec<Token>, diags: &'a mut BuildDiagnostics) -> Self {
619 Self {
620 builder: Default::default(),
621 tokens,
622 cursor: 0,
623 diags,
624 source_file: Default::default(),
625 }
626 }
627
628 pub fn new(source: &str, diags: &'a mut BuildDiagnostics) -> Self {
630 Self::from_tokens(crate::lexer::lex(source), diags)
631 }
632
633 fn current_token(&self) -> Token {
634 self.tokens.get(self.cursor).cloned().unwrap_or_default()
635 }
636
637 pub fn consume_ws(&mut self) {
639 while matches!(self.current_token().kind, SyntaxKind::Whitespace | SyntaxKind::Comment) {
640 self.consume()
641 }
642 }
643}
644
645impl Parser for DefaultParser<'_> {
646 fn start_node_impl(
647 &mut self,
648 kind: SyntaxKind,
649 checkpoint: Option<Self::Checkpoint>,
650 _: NodeToken,
651 ) {
652 if kind != SyntaxKind::Document {
653 self.consume_ws();
654 }
655 match checkpoint {
656 None => self.builder.start_node(kind.into()),
657 Some(cp) => self.builder.start_node_at(cp, kind.into()),
658 }
659 }
660
661 fn finish_node_impl(&mut self, _: NodeToken) {
662 self.builder.finish_node();
663 }
664
665 fn nth(&mut self, mut n: usize) -> Token {
667 self.consume_ws();
668 let mut c = self.cursor;
669 while n > 0 {
670 n -= 1;
671 c += 1;
672 while c < self.tokens.len()
673 && matches!(self.tokens[c].kind, SyntaxKind::Whitespace | SyntaxKind::Comment)
674 {
675 c += 1;
676 }
677 }
678 self.tokens.get(c).cloned().unwrap_or_default()
679 }
680
681 fn consume(&mut self) {
683 let t = self.current_token();
684 self.builder.token(t.kind.into(), t.text.as_str());
685 if t.kind != SyntaxKind::Eof {
686 self.cursor += 1;
687 }
688 }
689
690 fn error(&mut self, e: impl Into<String>) {
692 let current_token = self.current_token();
693 #[allow(unused_mut)]
694 let mut span = crate::diagnostics::Span::new(current_token.offset);
695 #[cfg(feature = "proc_macro_span")]
696 {
697 span.span = current_token.span;
698 }
699
700 self.diags.push_error_with_span(
701 e.into(),
702 crate::diagnostics::SourceLocation {
703 source_file: Some(self.source_file.clone()),
704 span,
705 },
706 );
707 }
708
709 fn warning(&mut self, e: impl Into<String>) {
711 let current_token = self.current_token();
712 #[allow(unused_mut)]
713 let mut span = crate::diagnostics::Span::new(current_token.offset);
714 #[cfg(feature = "proc_macro_span")]
715 {
716 span.span = current_token.span;
717 }
718
719 self.diags.push_warning_with_span(
720 e.into(),
721 crate::diagnostics::SourceLocation {
722 source_file: Some(self.source_file.clone()),
723 span,
724 },
725 );
726 }
727
728 type Checkpoint = rowan::Checkpoint;
729 fn checkpoint(&mut self) -> Self::Checkpoint {
730 self.builder.checkpoint()
731 }
732}
733
734#[derive(Clone, Copy, Debug, Eq, Ord, Hash, PartialEq, PartialOrd)]
735pub enum Language {}
736impl rowan::Language for Language {
737 type Kind = SyntaxKind;
738 fn kind_from_raw(raw: rowan::SyntaxKind) -> Self::Kind {
739 SyntaxKind::try_from(raw.0).unwrap()
740 }
741 fn kind_to_raw(kind: Self::Kind) -> rowan::SyntaxKind {
742 kind.into()
743 }
744}
745
746#[derive(Debug, Clone, derive_more::Deref)]
747pub struct SyntaxNode {
748 #[deref]
749 pub node: rowan::SyntaxNode<Language>,
750 pub source_file: SourceFile,
751}
752
753#[derive(Debug, Clone, derive_more::Deref)]
754pub struct SyntaxToken {
755 #[deref]
756 pub token: rowan::SyntaxToken<Language>,
757 pub source_file: SourceFile,
758}
759
760impl SyntaxToken {
761 pub fn parent(&self) -> SyntaxNode {
762 SyntaxNode { node: self.token.parent().unwrap(), source_file: self.source_file.clone() }
763 }
764 pub fn parent_ancestors(&self) -> impl Iterator<Item = SyntaxNode> + '_ {
765 self.token
766 .parent_ancestors()
767 .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
768 }
769 pub fn next_token(&self) -> Option<SyntaxToken> {
770 let token = self
778 .token
779 .next_sibling_or_token()
780 .and_then(|e| match e {
781 rowan::NodeOrToken::Node(n) => n.first_token(),
782 rowan::NodeOrToken::Token(t) => Some(t),
783 })
784 .or_else(|| {
785 self.token.parent_ancestors().find_map(|it| it.next_sibling_or_token()).and_then(
786 |e| match e {
787 rowan::NodeOrToken::Node(n) => n.first_token(),
788 rowan::NodeOrToken::Token(t) => Some(t),
789 },
790 )
791 })?;
792 Some(SyntaxToken { token, source_file: self.source_file.clone() })
793 }
794 pub fn prev_token(&self) -> Option<SyntaxToken> {
795 let token = self.token.prev_token()?;
796 Some(SyntaxToken { token, source_file: self.source_file.clone() })
797 }
798 pub fn text(&self) -> &str {
799 self.token.text()
800 }
801}
802
803impl std::fmt::Display for SyntaxToken {
804 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
805 self.token.fmt(f)
806 }
807}
808
809impl SyntaxNode {
810 pub fn child_node(&self, kind: SyntaxKind) -> Option<SyntaxNode> {
811 self.node
812 .children()
813 .find(|n| n.kind() == kind)
814 .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
815 }
816 pub fn child_token(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
817 self.node
818 .children_with_tokens()
819 .find(|n| n.kind() == kind)
820 .and_then(|x| x.into_token())
821 .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
822 }
823 pub fn child_text(&self, kind: SyntaxKind) -> Option<SmolStr> {
824 self.node
825 .children_with_tokens()
826 .find(|n| n.kind() == kind)
827 .and_then(|x| x.as_token().map(|x| x.text().into()))
828 }
829 pub fn descendants(&self) -> impl Iterator<Item = SyntaxNode> {
830 let source_file = self.source_file.clone();
831 self.node
832 .descendants()
833 .map(move |node| SyntaxNode { node, source_file: source_file.clone() })
834 }
835 pub fn kind(&self) -> SyntaxKind {
836 self.node.kind()
837 }
838 pub fn children(&self) -> impl Iterator<Item = SyntaxNode> {
839 let source_file = self.source_file.clone();
840 self.node.children().map(move |node| SyntaxNode { node, source_file: source_file.clone() })
841 }
842 pub fn children_with_tokens(&self) -> impl Iterator<Item = NodeOrToken> {
843 let source_file = self.source_file.clone();
844 self.node.children_with_tokens().map(move |token| match token {
845 rowan::NodeOrToken::Node(node) => {
846 SyntaxNode { node, source_file: source_file.clone() }.into()
847 }
848 rowan::NodeOrToken::Token(token) => {
849 SyntaxToken { token, source_file: source_file.clone() }.into()
850 }
851 })
852 }
853 pub fn text(&self) -> rowan::SyntaxText {
854 self.node.text()
855 }
856 pub fn parent(&self) -> Option<SyntaxNode> {
857 self.node.parent().map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
858 }
859 pub fn first_token(&self) -> Option<SyntaxToken> {
860 self.node
861 .first_token()
862 .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
863 }
864 pub fn last_token(&self) -> Option<SyntaxToken> {
865 self.node
866 .last_token()
867 .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
868 }
869 pub fn token_at_offset(&self, offset: TextSize) -> rowan::TokenAtOffset<SyntaxToken> {
870 self.node
871 .token_at_offset(offset)
872 .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
873 }
874 pub fn first_child(&self) -> Option<SyntaxNode> {
875 self.node
876 .first_child()
877 .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
878 }
879 pub fn first_child_or_token(&self) -> Option<NodeOrToken> {
880 self.node.first_child_or_token().map(|n_o_t| match n_o_t {
881 rowan::NodeOrToken::Node(node) => {
882 NodeOrToken::Node(SyntaxNode { node, source_file: self.source_file.clone() })
883 }
884 rowan::NodeOrToken::Token(token) => {
885 NodeOrToken::Token(SyntaxToken { token, source_file: self.source_file.clone() })
886 }
887 })
888 }
889 pub fn next_sibling(&self) -> Option<SyntaxNode> {
890 self.node
891 .next_sibling()
892 .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
893 }
894}
895
896#[derive(Debug, Clone, derive_more::From)]
897pub enum NodeOrToken {
898 Node(SyntaxNode),
899 Token(SyntaxToken),
900}
901
902impl NodeOrToken {
903 pub fn kind(&self) -> SyntaxKind {
904 match self {
905 NodeOrToken::Node(n) => n.kind(),
906 NodeOrToken::Token(t) => t.kind(),
907 }
908 }
909
910 pub fn as_node(&self) -> Option<&SyntaxNode> {
911 match self {
912 NodeOrToken::Node(n) => Some(n),
913 NodeOrToken::Token(_) => None,
914 }
915 }
916
917 pub fn as_token(&self) -> Option<&SyntaxToken> {
918 match self {
919 NodeOrToken::Node(_) => None,
920 NodeOrToken::Token(t) => Some(t),
921 }
922 }
923
924 pub fn into_token(self) -> Option<SyntaxToken> {
925 match self {
926 NodeOrToken::Token(t) => Some(t),
927 _ => None,
928 }
929 }
930
931 pub fn into_node(self) -> Option<SyntaxNode> {
932 match self {
933 NodeOrToken::Node(n) => Some(n),
934 _ => None,
935 }
936 }
937
938 pub fn text_range(&self) -> TextRange {
939 match self {
940 NodeOrToken::Node(n) => n.text_range(),
941 NodeOrToken::Token(t) => t.text_range(),
942 }
943 }
944}
945
946impl Spanned for SyntaxNode {
947 fn span(&self) -> crate::diagnostics::Span {
948 crate::diagnostics::Span::new(self.node.text_range().start().into())
949 }
950
951 fn source_file(&self) -> Option<&SourceFile> {
952 Some(&self.source_file)
953 }
954}
955
956impl Spanned for Option<SyntaxNode> {
957 fn span(&self) -> crate::diagnostics::Span {
958 self.as_ref().map(|n| n.span()).unwrap_or_default()
959 }
960
961 fn source_file(&self) -> Option<&SourceFile> {
962 self.as_ref().and_then(|n| n.source_file())
963 }
964}
965
966impl Spanned for SyntaxToken {
967 fn span(&self) -> crate::diagnostics::Span {
968 crate::diagnostics::Span::new(self.token.text_range().start().into())
969 }
970
971 fn source_file(&self) -> Option<&SourceFile> {
972 Some(&self.source_file)
973 }
974}
975
976impl Spanned for NodeOrToken {
977 fn span(&self) -> crate::diagnostics::Span {
978 match self {
979 NodeOrToken::Node(n) => n.span(),
980 NodeOrToken::Token(t) => t.span(),
981 }
982 }
983
984 fn source_file(&self) -> Option<&SourceFile> {
985 match self {
986 NodeOrToken::Node(n) => n.source_file(),
987 NodeOrToken::Token(t) => t.source_file(),
988 }
989 }
990}
991
992impl Spanned for Option<NodeOrToken> {
993 fn span(&self) -> crate::diagnostics::Span {
994 self.as_ref().map(|t| t.span()).unwrap_or_default()
995 }
996 fn source_file(&self) -> Option<&SourceFile> {
997 self.as_ref().and_then(|t| t.source_file())
998 }
999}
1000
1001impl Spanned for Option<SyntaxToken> {
1002 fn span(&self) -> crate::diagnostics::Span {
1003 self.as_ref().map(|t| t.span()).unwrap_or_default()
1004 }
1005 fn source_file(&self) -> Option<&SourceFile> {
1006 self.as_ref().and_then(|t| t.source_file())
1007 }
1008}
1009
1010pub fn identifier_text(node: &SyntaxNode) -> Option<SmolStr> {
1012 node.child_text(SyntaxKind::Identifier).map(|x| normalize_identifier(&x))
1013}
1014
1015pub fn normalize_identifier(ident: &str) -> SmolStr {
1016 ident.replace_smolstr("_", "-")
1017}
1018
1019pub fn parse(
1021 source: String,
1022 path: Option<&std::path::Path>,
1023 build_diagnostics: &mut BuildDiagnostics,
1024) -> SyntaxNode {
1025 let mut p = DefaultParser::new(&source, build_diagnostics);
1026 p.source_file = std::rc::Rc::new(crate::diagnostics::SourceFileInner::new(
1027 path.map(crate::pathutils::clean_path).unwrap_or_default(),
1028 source,
1029 ));
1030 document::parse_document(&mut p);
1031 SyntaxNode {
1032 node: rowan::SyntaxNode::new_root(p.builder.finish()),
1033 source_file: p.source_file.clone(),
1034 }
1035}
1036
1037pub fn parse_file<P: AsRef<std::path::Path>>(
1038 path: P,
1039 build_diagnostics: &mut BuildDiagnostics,
1040) -> Option<SyntaxNode> {
1041 let path = crate::pathutils::clean_path(path.as_ref());
1042 let source = crate::diagnostics::load_from_path(&path)
1043 .map_err(|d| build_diagnostics.push_internal_error(d))
1044 .ok()?;
1045 Some(parse(source, Some(path.as_ref()), build_diagnostics))
1046}
1047
1048pub fn parse_tokens(
1049 tokens: Vec<Token>,
1050 source_file: SourceFile,
1051 diags: &mut BuildDiagnostics,
1052) -> SyntaxNode {
1053 let mut p = DefaultParser::from_tokens(tokens, diags);
1054 document::parse_document(&mut p);
1055 SyntaxNode { node: rowan::SyntaxNode::new_root(p.builder.finish()), source_file }
1056}