Skip to main content

ktrs_parser/builder/
marker.rs

1//! `PsiBuilder.Marker` as a copyable handle. Every operation takes the owner of the builder
2//! (`&mut Parser`, `&mut PsiBuilder`, ...) explicitly: Java `m.done(BLOCK)` is `m.done(self, BLOCK)`.
3
4use ktrs_syntax::SyntaxKind;
5
6use super::binders::EdgeBinder;
7use super::psi_builder::PsiBuilder;
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
10pub struct Marker(pub(crate) i32);
11
12/// Anything that owns the underlying [`PsiBuilder`] (the builder itself, the Kotlin
13/// semantic-whitespace wrapper, the `Parser`).
14pub trait MarkerHost {
15    fn psi_builder(&mut self) -> &mut PsiBuilder;
16}
17
18impl MarkerHost for PsiBuilder {
19    fn psi_builder(&mut self) -> &mut PsiBuilder {
20        self
21    }
22}
23
24#[allow(clippy::should_implement_trait)]
25impl Marker {
26    /// A new marker starting at the same lexeme, placed before `self` in the production.
27    pub fn precede<H: MarkerHost + ?Sized>(self, host: &mut H) -> Marker {
28        host.psi_builder().precede(self)
29    }
30
31    pub fn drop<H: MarkerHost + ?Sized>(self, host: &mut H) {
32        host.psi_builder().drop_marker(self);
33    }
34
35    /// Rewinds the lexer to this marker and discards it and everything produced after it.
36    /// Token remaps done since are *not* undone (same as IntelliJ).
37    pub fn rollback_to<H: MarkerHost + ?Sized>(self, host: &mut H) {
38        host.psi_builder().rollback_to(self);
39    }
40
41    pub fn done<H: MarkerHost + ?Sized>(self, host: &mut H, kind: SyntaxKind) {
42        host.psi_builder().process_done(self, kind, None, None);
43    }
44
45    /// Done, and the whole range becomes one leaf of `kind` (a lazy leaf is reparsed on build).
46    pub fn collapse<H: MarkerHost + ?Sized>(self, host: &mut H, kind: SyntaxKind) {
47        let builder = host.psi_builder();
48        builder.process_done(self, kind, None, None);
49        builder.mark_collapsed(self);
50    }
51
52    pub fn done_before<H: MarkerHost + ?Sized>(self, host: &mut H, kind: SyntaxKind, before: Marker) {
53        host.psi_builder().process_done(self, kind, None, Some(before));
54    }
55
56    /// `doneBefore(type, before, errorMessage)`.
57    pub fn done_before_3<H: MarkerHost + ?Sized>(self, host: &mut H, kind: SyntaxKind, before: Marker, error_message: &str) {
58        host.psi_builder().done_before_with_error_item(self, kind, before, error_message);
59    }
60
61    pub fn error<H: MarkerHost + ?Sized>(self, host: &mut H, message: &str) {
62        host.psi_builder().process_done(self, SyntaxKind::ERROR_ELEMENT, Some(message), None);
63    }
64
65    pub fn error_before<H: MarkerHost + ?Sized>(self, host: &mut H, message: &str, before: Marker) {
66        host.psi_builder().process_done(self, SyntaxKind::ERROR_ELEMENT, Some(message), Some(before));
67    }
68
69    /// `None` keeps the current binder for that edge (Java passes `null`).
70    pub fn set_custom_edge_token_binders<H: MarkerHost + ?Sized>(
71        self,
72        host: &mut H,
73        left: Option<EdgeBinder>,
74        right: Option<EdgeBinder>,
75    ) {
76        host.psi_builder().set_binders(self, left, right);
77    }
78}