1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
use crate::{diagnostic::ParseDiagnostic, lexer::LexerCheckpoint};
use biome_rowan::{SyntaxKind, TextRange, TextSize, TriviaPieceKind};
/// A comment or a whitespace trivia in the source code.
#[derive(Debug, Copy, Clone)]
pub struct Trivia {
/// The kind of the trivia token.
kind: TriviaPieceKind,
/// The range of the trivia in the source text
range: TextRange,
/// Whatever this is the trailing or leading trivia of a non-trivia token.
trailing: bool,
}
impl Trivia {
pub fn new(kind: TriviaPieceKind, range: TextRange, trailing: bool) -> Self {
Self {
kind,
range,
trailing,
}
}
/// Returns the kind of the token
pub fn kind(&self) -> TriviaPieceKind {
self.kind
}
/// Returns the token's length in bytes
pub fn len(&self) -> TextSize {
self.range.len()
}
/// Returns the byte offset of the trivia in the source text
pub fn offset(&self) -> TextSize {
self.range.start()
}
/// Returns `true` if this is the trailing trivia of a non-trivia token or false otherwise.
pub fn trailing(&self) -> bool {
self.trailing
}
/// Returns the text range of this trivia
pub fn text_range(&self) -> TextRange {
self.range
}
}
pub trait TokenSource {
type Kind: SyntaxKind;
/// Returns the kind of the current non-trivia token
fn current(&self) -> Self::Kind;
/// Returns the range of the current non-trivia token
fn current_range(&self) -> TextRange;
/// Returns the source text
fn text(&self) -> &str;
/// Returns the byte offset of the current token from the start of the source document
fn position(&self) -> TextSize {
self.current_range().start()
}
/// Returns true if the current token is preceded by a line break
fn has_preceding_line_break(&self) -> bool;
fn bump(&mut self);
fn skip_as_trivia(&mut self);
/// Ends this token source and returns the source text's trivia
fn finish(self) -> (Vec<Trivia>, Vec<ParseDiagnostic>);
}
pub trait BumpWithContext: TokenSource {
type Context;
fn bump_with_context(&mut self, context: Self::Context);
/// Skips the current token as skipped token trivia
fn skip_as_trivia_with_context(&mut self, context: Self::Context);
}
/// Token source that supports inspecting the 'nth' token (lookahead)
pub trait NthToken: TokenSource {
/// Gets the kind of the nth non-trivia token
fn nth(&mut self, n: usize) -> Self::Kind;
/// Returns true if the nth non-trivia token is preceded by a line break
fn has_nth_preceding_line_break(&mut self, n: usize) -> bool;
}
#[derive(Debug)]
pub struct TokenSourceCheckpoint<K>
where
K: SyntaxKind,
{
pub lexer_checkpoint: LexerCheckpoint<K>,
/// A `u32` should be enough because `TextSize` is also limited to `u32`.
/// The worst case is a document where every character is its own token. This would
/// result in `u32::MAX` tokens
pub trivia_len: u32,
}
impl<K> TokenSourceCheckpoint<K>
where
K: SyntaxKind,
{
/// byte offset in the source text
pub fn current_start(&self) -> TextSize {
self.lexer_checkpoint.current_start()
}
pub fn trivia_position(&self) -> usize {
self.trivia_len as usize
}
}