1use crate::diagnostics::{BuildDiagnostics, SourceFile, Spanned};
16use smol_str::SmolStr;
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 pub use super::{Parser, SyntaxKind};
30 #[cfg(test)]
31 pub use super::{SyntaxNode, SyntaxNodeVerify, syntax_nodes};
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> + use<> {
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 {
334 Document -> [ *Component, *ExportsList, *ImportSpecifier, *StructDeclaration, *EnumDeclaration ],
335 Component -> [ DeclaredIdentifier, ?UsesSpecifier, ?ImplementsSpecifier, Element ],
337 SubElement -> [ Element ],
339 Element -> [ ?QualifiedName, *PropertyDeclaration, *Binding, *CallbackConnection,
340 *CallbackDeclaration, *ConditionalElement, *Function, *SubElement,
341 *RepeatedElement, *PropertyAnimation, *PropertyChangedCallback,
342 *TwoWayBinding, *States, *Transitions, ?ChildrenPlaceholder ],
343 RepeatedElement -> [ ?DeclaredIdentifier, ?RepeatedIndex, Expression , SubElement],
344 RepeatedIndex -> [],
345 ConditionalElement -> [ Expression , SubElement],
346 CallbackDeclaration -> [ DeclaredIdentifier, *CallbackDeclarationParameter, ?ReturnType, ?TwoWayBinding ],
347 CallbackDeclarationParameter -> [ ?DeclaredIdentifier, Type],
349 Function -> [DeclaredIdentifier, *ArgumentDeclaration, ?ReturnType, ?CodeBlock ],
350 ArgumentDeclaration -> [DeclaredIdentifier, Type],
351 ReturnType -> [Type],
353 CallbackConnection -> [ *DeclaredIdentifier, ?CodeBlock, ?Expression ],
354 PropertyDeclaration-> [ ?Type , DeclaredIdentifier, ?BindingExpression, ?TwoWayBinding ],
356 PropertyAnimation-> [ *QualifiedName, *Binding ],
358 PropertyChangedCallback-> [ DeclaredIdentifier, ?CodeBlock, ?Expression ],
360 QualifiedName-> [],
362 DeclaredIdentifier -> [],
364 ChildrenPlaceholder -> [],
365 Binding-> [ BindingExpression ],
366 TwoWayBinding -> [ Expression ],
368 BindingExpression-> [ ?CodeBlock, ?Expression ],
371 CodeBlock-> [ *Expression, *LetStatement, *ReturnStatement ],
372 LetStatement -> [ DeclaredIdentifier, ?Type, Expression ],
373 ReturnStatement -> [ ?Expression ],
374 Expression-> [ ?Expression, ?FunctionCallExpression, ?IndexExpression, ?SelfAssignment,
376 ?ConditionalExpression, ?QualifiedName, ?BinaryExpression, ?Array, ?ObjectLiteral,
377 ?UnaryOpExpression, ?CodeBlock, ?StringTemplate, ?AtImageUrl, ?AtGradient, ?AtTr,
378 ?MemberAccess, ?AtKeys ],
379 StringTemplate -> [*Expression],
381 AtImageUrl -> [],
383 AtGradient -> [*Expression],
385 AtTr -> [?TrContext, ?TrPlural, *Expression],
387 AtMarkdown -> [*Expression],
388 TrContext -> [],
390 TrPlural -> [Expression],
392 AtKeys -> [],
394 FunctionCallExpression -> [*Expression],
396 IndexExpression -> [2 Expression],
398 SelfAssignment -> [2 Expression],
400 ConditionalExpression -> [3 Expression],
402 BinaryExpression -> [2 Expression],
404 UnaryOpExpression -> [Expression],
406 MemberAccess -> [Expression],
408 Array -> [ *Expression ],
410 ObjectLiteral -> [ *ObjectMember ],
412 ObjectMember -> [ Expression ],
414 States -> [*State],
416 State -> [DeclaredIdentifier, ?Expression, *StatePropertyChange, *Transition],
418 StatePropertyChange -> [ QualifiedName, BindingExpression ],
420 Transitions -> [*Transition],
422 Transition -> [?DeclaredIdentifier, *PropertyAnimation],
424 ExportsList -> [ *ExportSpecifier, ?Component, *StructDeclaration, ?ExportModule, *EnumDeclaration ],
426 ExportSpecifier -> [ ExportIdentifier, ?ExportName ],
429 ExportIdentifier -> [],
430 ExportName -> [],
431 ExportModule -> [],
433 ImportSpecifier -> [ ?ImportIdentifierList ],
435 ImportIdentifierList -> [ *ImportIdentifier ],
436 ImportIdentifier -> [ ExternalName, ?InternalName ],
438 ExternalName -> [],
439 InternalName -> [],
440 Type -> [ ?QualifiedName, ?ObjectType, ?ArrayType ],
442 ObjectType ->[ *ObjectTypeMember ],
444 ObjectTypeMember -> [ Type ],
446 ArrayType -> [ Type ],
448 StructDeclaration -> [DeclaredIdentifier, ObjectType, *AtRustAttr],
450 EnumDeclaration -> [DeclaredIdentifier, *EnumValue, *AtRustAttr],
452 EnumValue -> [],
454 AtRustAttr -> [],
456 UsesSpecifier -> [ *UsesIdentifier ],
458 UsesIdentifier -> [QualifiedName, DeclaredIdentifier],
460 ImplementsSpecifier -> [ QualifiedName ],
462 }
463}
464
465impl From<SyntaxKind> for rowan::SyntaxKind {
466 fn from(v: SyntaxKind) -> Self {
467 rowan::SyntaxKind(v.into())
468 }
469}
470
471#[derive(Clone, Debug)]
472pub struct Token {
473 pub kind: SyntaxKind,
474 pub text: SmolStr,
475 pub offset: usize,
476 pub length: usize,
477 #[cfg(feature = "proc_macro_span")]
478 pub span: Option<proc_macro::Span>,
479}
480
481impl Default for Token {
482 fn default() -> Self {
483 Token {
484 kind: SyntaxKind::Eof,
485 text: Default::default(),
486 offset: 0,
487 length: 0,
488 #[cfg(feature = "proc_macro_span")]
489 span: None,
490 }
491 }
492}
493
494impl Token {
495 pub fn as_str(&self) -> &str {
496 self.text.as_str()
497 }
498
499 pub fn kind(&self) -> SyntaxKind {
500 self.kind
501 }
502}
503
504mod parser_trait {
505 use super::*;
507
508 pub trait Parser: Sized {
509 type Checkpoint: Clone;
510
511 #[must_use = "The node will be finished when it is dropped"]
517 fn start_node(&mut self, kind: SyntaxKind) -> Node<'_, Self> {
518 self.start_node_impl(kind, None, NodeToken(()));
519 Node(self)
520 }
521 #[must_use = "use start_node_at to use this checkpoint"]
522 fn checkpoint(&mut self) -> Self::Checkpoint;
523 #[must_use = "The node will be finished when it is dropped"]
524 fn start_node_at(
525 &mut self,
526 checkpoint: impl Into<Option<Self::Checkpoint>>,
527 kind: SyntaxKind,
528 ) -> Node<'_, Self> {
529 self.start_node_impl(kind, checkpoint.into(), NodeToken(()));
530 Node(self)
531 }
532
533 fn finish_node_impl(&mut self, token: NodeToken);
535 fn start_node_impl(
537 &mut self,
538 kind: SyntaxKind,
539 checkpoint: Option<Self::Checkpoint>,
540 token: NodeToken,
541 );
542
543 fn peek(&mut self) -> Token {
545 self.nth(0)
546 }
547 fn nth(&mut self, n: usize) -> Token;
549 fn consume(&mut self);
551 fn error(&mut self, e: impl Into<String>);
552 fn warning(&mut self, e: impl Into<String>);
553
554 fn expect(&mut self, kind: SyntaxKind) -> bool {
557 if !self.test(kind) {
558 self.error(format!("Syntax error: expected {kind}"));
559 return false;
560 }
561 true
562 }
563
564 fn test(&mut self, kind: SyntaxKind) -> bool {
566 if self.nth(0).kind() != kind {
567 return false;
568 }
569 self.consume();
570 true
571 }
572
573 fn until(&mut self, kind: SyntaxKind) {
575 let mut parens = 0;
576 let mut braces = 0;
577 let mut brackets = 0;
578 loop {
579 match self.nth(0).kind() {
580 k if k == kind && parens == 0 && braces == 0 && brackets == 0 => break,
581 SyntaxKind::Eof => break,
582 SyntaxKind::LParent => parens += 1,
583 SyntaxKind::LBrace => braces += 1,
584 SyntaxKind::LBracket => brackets += 1,
585 SyntaxKind::RParent if parens == 0 => break,
586 SyntaxKind::RParent => parens -= 1,
587 SyntaxKind::RBrace if braces == 0 => break,
588 SyntaxKind::RBrace => braces -= 1,
589 SyntaxKind::RBracket if brackets == 0 => break,
590 SyntaxKind::RBracket => brackets -= 1,
591 _ => {}
592 };
593 self.consume();
594 }
595 self.expect(kind);
596 }
597 }
598
599 pub struct NodeToken(());
604 #[derive(derive_more::DerefMut)]
607 pub struct Node<'a, P: Parser>(&'a mut P);
608 impl<P: Parser> Drop for Node<'_, P> {
609 fn drop(&mut self) {
610 self.0.finish_node_impl(NodeToken(()));
611 }
612 }
613 impl<P: Parser> core::ops::Deref for Node<'_, P> {
614 type Target = P;
615 fn deref(&self) -> &Self::Target {
616 self.0
617 }
618 }
619}
620#[doc(inline)]
621pub use parser_trait::*;
622
623pub struct DefaultParser<'a> {
624 builder: rowan::GreenNodeBuilder<'static>,
625 tokens: Vec<Token>,
627 cursor: usize,
629 diags: &'a mut BuildDiagnostics,
630 source_file: SourceFile,
631}
632
633impl<'a> DefaultParser<'a> {
634 fn from_tokens(tokens: Vec<Token>, diags: &'a mut BuildDiagnostics) -> Self {
635 Self {
636 builder: Default::default(),
637 tokens,
638 cursor: 0,
639 diags,
640 source_file: Default::default(),
641 }
642 }
643
644 pub fn new(source: &str, diags: &'a mut BuildDiagnostics) -> Self {
647 Self::from_tokens(crate::lexer::lex(source), diags)
648 }
649
650 fn current_token(&self) -> Token {
651 self.tokens.get(self.cursor).cloned().unwrap_or_default()
652 }
653
654 pub fn consume_ws(&mut self) {
656 while matches!(self.current_token().kind, SyntaxKind::Whitespace | SyntaxKind::Comment) {
657 self.consume()
658 }
659 }
660}
661
662impl Parser for DefaultParser<'_> {
663 fn start_node_impl(
664 &mut self,
665 kind: SyntaxKind,
666 checkpoint: Option<Self::Checkpoint>,
667 _: NodeToken,
668 ) {
669 if kind != SyntaxKind::Document {
670 self.consume_ws();
671 }
672 match checkpoint {
673 None => self.builder.start_node(kind.into()),
674 Some(cp) => self.builder.start_node_at(cp, kind.into()),
675 }
676 }
677
678 fn finish_node_impl(&mut self, _: NodeToken) {
679 self.builder.finish_node();
680 }
681
682 fn nth(&mut self, mut n: usize) -> Token {
684 self.consume_ws();
685 let mut c = self.cursor;
686 while n > 0 {
687 n -= 1;
688 c += 1;
689 while c < self.tokens.len()
690 && matches!(self.tokens[c].kind, SyntaxKind::Whitespace | SyntaxKind::Comment)
691 {
692 c += 1;
693 }
694 }
695 self.tokens.get(c).cloned().unwrap_or_default()
696 }
697
698 fn consume(&mut self) {
700 let t = self.current_token();
701 self.builder.token(t.kind.into(), t.text.as_str());
702 if t.kind != SyntaxKind::Eof {
703 self.cursor += 1;
704 }
705 }
706
707 fn error(&mut self, e: impl Into<String>) {
709 let current_token = self.current_token();
710 #[allow(unused_mut)]
711 let mut span = crate::diagnostics::Span::new(current_token.offset, current_token.length);
712 #[cfg(feature = "proc_macro_span")]
713 {
714 span.span = current_token.span;
715 }
716
717 self.diags.push_error_with_span(
718 e.into(),
719 crate::diagnostics::SourceLocation {
720 source_file: Some(self.source_file.clone()),
721 span,
722 },
723 );
724 }
725
726 fn warning(&mut self, e: impl Into<String>) {
728 let current_token = self.current_token();
729 #[allow(unused_mut)]
730 let mut span = crate::diagnostics::Span::new(current_token.offset, current_token.length);
731 #[cfg(feature = "proc_macro_span")]
732 {
733 span.span = current_token.span;
734 }
735
736 self.diags.push_warning_with_span(
737 e.into(),
738 crate::diagnostics::SourceLocation {
739 source_file: Some(self.source_file.clone()),
740 span,
741 },
742 );
743 }
744
745 type Checkpoint = rowan::Checkpoint;
746 fn checkpoint(&mut self) -> Self::Checkpoint {
747 self.builder.checkpoint()
748 }
749}
750
751#[derive(Clone, Copy, Debug, Eq, Ord, Hash, PartialEq, PartialOrd)]
752pub enum Language {}
753impl rowan::Language for Language {
754 type Kind = SyntaxKind;
755 fn kind_from_raw(raw: rowan::SyntaxKind) -> Self::Kind {
756 SyntaxKind::try_from(raw.0).unwrap()
757 }
758 fn kind_to_raw(kind: Self::Kind) -> rowan::SyntaxKind {
759 kind.into()
760 }
761}
762
763#[derive(Debug, Clone, derive_more::Deref)]
764pub struct SyntaxNode {
765 #[deref]
766 pub node: rowan::SyntaxNode<Language>,
767 pub source_file: SourceFile,
768}
769
770#[derive(Debug, Clone, derive_more::Deref)]
771pub struct SyntaxToken {
772 #[deref]
773 pub token: rowan::SyntaxToken<Language>,
774 pub source_file: SourceFile,
775}
776
777impl SyntaxToken {
778 pub fn parent(&self) -> SyntaxNode {
779 SyntaxNode { node: self.token.parent().unwrap(), source_file: self.source_file.clone() }
780 }
781 pub fn parent_ancestors(&self) -> impl Iterator<Item = SyntaxNode> + '_ {
782 self.token
783 .parent_ancestors()
784 .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
785 }
786 pub fn next_token(&self) -> Option<SyntaxToken> {
787 let token = self
795 .token
796 .next_sibling_or_token()
797 .and_then(|e| match e {
798 rowan::NodeOrToken::Node(n) => n.first_token(),
799 rowan::NodeOrToken::Token(t) => Some(t),
800 })
801 .or_else(|| {
802 self.token.parent_ancestors().find_map(|it| it.next_sibling_or_token()).and_then(
803 |e| match e {
804 rowan::NodeOrToken::Node(n) => n.first_token(),
805 rowan::NodeOrToken::Token(t) => Some(t),
806 },
807 )
808 })?;
809 Some(SyntaxToken { token, source_file: self.source_file.clone() })
810 }
811 pub fn prev_token(&self) -> Option<SyntaxToken> {
812 let token = self.token.prev_token()?;
813 Some(SyntaxToken { token, source_file: self.source_file.clone() })
814 }
815 pub fn text(&self) -> &str {
816 self.token.text()
817 }
818}
819
820impl std::fmt::Display for SyntaxToken {
821 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
822 self.token.fmt(f)
823 }
824}
825
826impl SyntaxNode {
827 pub fn child_node(&self, kind: SyntaxKind) -> Option<SyntaxNode> {
828 self.node
829 .children()
830 .find(|n| n.kind() == kind)
831 .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
832 }
833 pub fn child_token(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
834 self.node
835 .children_with_tokens()
836 .find(|n| n.kind() == kind)
837 .and_then(|x| x.into_token())
838 .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
839 }
840 pub fn child_text(&self, kind: SyntaxKind) -> Option<SmolStr> {
841 self.node
842 .children_with_tokens()
843 .find(|n| n.kind() == kind)
844 .and_then(|x| x.as_token().map(|x| x.text().into()))
845 }
846 pub fn descendants(&self) -> impl Iterator<Item = SyntaxNode> + use<> {
847 let source_file = self.source_file.clone();
848 self.node
849 .descendants()
850 .map(move |node| SyntaxNode { node, source_file: source_file.clone() })
851 }
852 pub fn kind(&self) -> SyntaxKind {
853 self.node.kind()
854 }
855 pub fn children(&self) -> impl Iterator<Item = SyntaxNode> + use<> {
856 let source_file = self.source_file.clone();
857 self.node.children().map(move |node| SyntaxNode { node, source_file: source_file.clone() })
858 }
859 pub fn children_with_tokens(&self) -> impl Iterator<Item = NodeOrToken> + use<> {
860 let source_file = self.source_file.clone();
861 self.node.children_with_tokens().map(move |token| match token {
862 rowan::NodeOrToken::Node(node) => {
863 SyntaxNode { node, source_file: source_file.clone() }.into()
864 }
865 rowan::NodeOrToken::Token(token) => {
866 SyntaxToken { token, source_file: source_file.clone() }.into()
867 }
868 })
869 }
870 pub fn text(&self) -> rowan::SyntaxText {
871 self.node.text()
872 }
873 pub fn parent(&self) -> Option<SyntaxNode> {
874 self.node.parent().map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
875 }
876 pub fn first_token(&self) -> Option<SyntaxToken> {
877 self.node
878 .first_token()
879 .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
880 }
881 pub fn last_token(&self) -> Option<SyntaxToken> {
882 self.node
883 .last_token()
884 .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
885 }
886 pub fn token_at_offset(&self, offset: TextSize) -> rowan::TokenAtOffset<SyntaxToken> {
887 self.node
888 .token_at_offset(offset)
889 .map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
890 }
891 pub fn first_child(&self) -> Option<SyntaxNode> {
892 self.node
893 .first_child()
894 .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
895 }
896 pub fn first_child_or_token(&self) -> Option<NodeOrToken> {
897 self.node.first_child_or_token().map(|n_o_t| match n_o_t {
898 rowan::NodeOrToken::Node(node) => {
899 NodeOrToken::Node(SyntaxNode { node, source_file: self.source_file.clone() })
900 }
901 rowan::NodeOrToken::Token(token) => {
902 NodeOrToken::Token(SyntaxToken { token, source_file: self.source_file.clone() })
903 }
904 })
905 }
906 pub fn next_sibling(&self) -> Option<SyntaxNode> {
907 self.node
908 .next_sibling()
909 .map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
910 }
911}
912
913#[derive(Debug, Clone, derive_more::From)]
914pub enum NodeOrToken {
915 Node(SyntaxNode),
916 Token(SyntaxToken),
917}
918
919impl NodeOrToken {
920 pub fn kind(&self) -> SyntaxKind {
921 match self {
922 NodeOrToken::Node(n) => n.kind(),
923 NodeOrToken::Token(t) => t.kind(),
924 }
925 }
926
927 pub fn as_node(&self) -> Option<&SyntaxNode> {
928 match self {
929 NodeOrToken::Node(n) => Some(n),
930 NodeOrToken::Token(_) => None,
931 }
932 }
933
934 pub fn as_token(&self) -> Option<&SyntaxToken> {
935 match self {
936 NodeOrToken::Node(_) => None,
937 NodeOrToken::Token(t) => Some(t),
938 }
939 }
940
941 pub fn into_token(self) -> Option<SyntaxToken> {
942 match self {
943 NodeOrToken::Token(t) => Some(t),
944 _ => None,
945 }
946 }
947
948 pub fn into_node(self) -> Option<SyntaxNode> {
949 match self {
950 NodeOrToken::Node(n) => Some(n),
951 _ => None,
952 }
953 }
954
955 pub fn text_range(&self) -> TextRange {
956 match self {
957 NodeOrToken::Node(n) => n.text_range(),
958 NodeOrToken::Token(t) => t.text_range(),
959 }
960 }
961}
962
963impl Spanned for SyntaxNode {
964 fn span(&self) -> crate::diagnostics::Span {
965 let range = self.node.text_range();
966 crate::diagnostics::Span::new(range.start().into(), range.len().into())
967 }
968
969 fn source_file(&self) -> Option<&SourceFile> {
970 Some(&self.source_file)
971 }
972}
973
974impl Spanned for Option<SyntaxNode> {
975 fn span(&self) -> crate::diagnostics::Span {
976 self.as_ref().map(|n| n.span()).unwrap_or_default()
977 }
978
979 fn source_file(&self) -> Option<&SourceFile> {
980 self.as_ref().and_then(|n| n.source_file())
981 }
982}
983
984impl Spanned for SyntaxToken {
985 fn span(&self) -> crate::diagnostics::Span {
986 let range = self.token.text_range();
987 crate::diagnostics::Span::new(range.start().into(), range.len().into())
988 }
989
990 fn source_file(&self) -> Option<&SourceFile> {
991 Some(&self.source_file)
992 }
993}
994
995impl Spanned for NodeOrToken {
996 fn span(&self) -> crate::diagnostics::Span {
997 match self {
998 NodeOrToken::Node(n) => n.span(),
999 NodeOrToken::Token(t) => t.span(),
1000 }
1001 }
1002
1003 fn source_file(&self) -> Option<&SourceFile> {
1004 match self {
1005 NodeOrToken::Node(n) => n.source_file(),
1006 NodeOrToken::Token(t) => t.source_file(),
1007 }
1008 }
1009}
1010
1011impl Spanned for Option<NodeOrToken> {
1012 fn span(&self) -> crate::diagnostics::Span {
1013 self.as_ref().map(|t| t.span()).unwrap_or_default()
1014 }
1015 fn source_file(&self) -> Option<&SourceFile> {
1016 self.as_ref().and_then(|t| t.source_file())
1017 }
1018}
1019
1020impl Spanned for Option<SyntaxToken> {
1021 fn span(&self) -> crate::diagnostics::Span {
1022 self.as_ref().map(|t| t.span()).unwrap_or_default()
1023 }
1024 fn source_file(&self) -> Option<&SourceFile> {
1025 self.as_ref().and_then(|t| t.source_file())
1026 }
1027}
1028
1029pub fn identifier_text(node: &SyntaxNode) -> Option<SmolStr> {
1031 node.child_text(SyntaxKind::Identifier).map(|x| normalize_identifier(&x))
1032}
1033
1034pub fn normalize_identifier(ident: &str) -> SmolStr {
1035 let mut builder = smol_str::SmolStrBuilder::default();
1036 for (pos, c) in ident.chars().enumerate() {
1037 match (pos, c) {
1038 (0, '-') | (0, '_') => builder.push('_'),
1039 (_, '_') => builder.push('-'),
1040 (_, c) => builder.push(c),
1041 }
1042 }
1043 builder.finish()
1044}
1045
1046#[test]
1047fn test_normalize_identifier() {
1048 assert_eq!(normalize_identifier("true"), SmolStr::new("true"));
1049 assert_eq!(normalize_identifier("foo_bar"), SmolStr::new("foo-bar"));
1050 assert_eq!(normalize_identifier("-foo_bar"), SmolStr::new("_foo-bar"));
1051 assert_eq!(normalize_identifier("-foo-bar"), SmolStr::new("_foo-bar"));
1052 assert_eq!(normalize_identifier("foo_bar_"), SmolStr::new("foo-bar-"));
1053 assert_eq!(normalize_identifier("foo_bar-"), SmolStr::new("foo-bar-"));
1054 assert_eq!(normalize_identifier("_foo_bar_"), SmolStr::new("_foo-bar-"));
1055 assert_eq!(normalize_identifier("__1"), SmolStr::new("_-1"));
1056 assert_eq!(normalize_identifier("--1"), SmolStr::new("_-1"));
1057 assert_eq!(normalize_identifier("--1--"), SmolStr::new("_-1--"));
1058}
1059
1060pub fn parse(
1062 source: String,
1063 path: Option<&std::path::Path>,
1064 build_diagnostics: &mut BuildDiagnostics,
1065) -> SyntaxNode {
1066 let mut p = DefaultParser::new(&source, build_diagnostics);
1067 p.source_file = std::rc::Rc::new(crate::diagnostics::SourceFileInner::new(
1068 path.map(crate::pathutils::clean_path).unwrap_or_default(),
1069 source,
1070 ));
1071 document::parse_document(&mut p);
1072 SyntaxNode {
1073 node: rowan::SyntaxNode::new_root(p.builder.finish()),
1074 source_file: p.source_file.clone(),
1075 }
1076}
1077
1078pub fn parse_file<P: AsRef<std::path::Path>>(
1079 path: P,
1080 build_diagnostics: &mut BuildDiagnostics,
1081) -> Option<SyntaxNode> {
1082 let path = crate::pathutils::clean_path(path.as_ref());
1083 let source = crate::diagnostics::load_from_path(&path)
1084 .map_err(|d| build_diagnostics.push_internal_error(d))
1085 .ok()?;
1086 Some(parse(source, Some(path.as_ref()), build_diagnostics))
1087}
1088
1089pub fn parse_tokens(
1090 tokens: Vec<Token>,
1091 source_file: SourceFile,
1092 diags: &mut BuildDiagnostics,
1093) -> SyntaxNode {
1094 let mut p = DefaultParser::from_tokens(tokens, diags);
1095 document::parse_document(&mut p);
1096 SyntaxNode { node: rowan::SyntaxNode::new_root(p.builder.finish()), source_file }
1097}