feat(rome_rowan): `with_*_trivia_pieces`
MODIFY
crates/rome_js_analyze/src/analyzers/jsx/no_implicit_boolean.rs
crates/rome_js_analyze/src/analyzers/jsx/no_implicit_boolean.rs
@@ -97,9 +97,8 @@ impl Rule for NoImplicitBoolean {
let last_token_of_name_syntax = name_syntax.last_token()?;
// drop the trailing trivia of name_syntax, at CST level it means
// clean the trailing trivia of last token of name_syntax
- let next_last_token_of_name_syntax = last_token_of_name_syntax
- .clone()
- .with_trailing_trivia(std::iter::empty());
+ let next_last_token_of_name_syntax =
+ last_token_of_name_syntax.with_trailing_trivia(std::iter::empty());
let next_name = name.replace_token_discard_trivia(
last_token_of_name_syntax,

MODIFY
crates/rome_rowan/src/ast/batch.rs
crates/rome_rowan/src/ast/batch.rs
@@ -131,58 +131,58 @@ where
prev_element: SyntaxElement<L>,
next_element: SyntaxElement<L>,
) {
- let (prev_leading, prev_trailing): (Vec<_>, Vec<_>) = match &prev_element {
+ let (prev_leading_trivia, prev_trailing_trivia) = match &prev_element {
SyntaxElement::Node(node) => (
- node.first_token()
- .map(|token| token.leading_trivia().pieces().collect())
- .unwrap_or_default(),
- node.last_token()
- .map(|token| token.trailing_trivia().pieces().collect())
- .unwrap_or_default(),
- ),
- SyntaxElement::Token(token) => (
- token.leading_trivia().pieces().collect(),
- token.trailing_trivia().pieces().collect(),
+ node.first_token().map(|token| token.leading_trivia()),
+ node.last_token().map(|token| token.trailing_trivia()),
),
+ SyntaxElement::Token(token) => {
+ (Some(token.leading_trivia()), Some(token.trailing_trivia()))
+ }
};
let next_element = match next_element {
SyntaxElement::Node(mut node) => {
if let Some(token) = node.first_token() {
- let new_token = token.clone().with_leading_trivia(
- prev_leading
- .iter()
- .map(|piece| (piece.kind(), piece.text())),
- );
+ let new_token = match prev_leading_trivia {
+ Some(prev_leading_trivia) => {
+ token.with_leading_trivia_pieces(prev_leading_trivia.pieces())
+ }
+ None => token.with_leading_trivia_pieces(empty()),
+ };
node = node.replace_child(token.into(), new_token.into()).unwrap();
}
if let Some(token) = node.last_token() {
- let new_token = token.clone().with_trailing_trivia(
- prev_trailing
- .iter()
- .map(|piece| (piece.kind(), piece.text())),
- );
+ let new_token = match prev_trailing_trivia {
+ Some(prev_trailing_trivia) => {
+ token.with_trailing_trivia_pieces(prev_trailing_trivia.pieces())
+ }
+ None => token.with_trailing_trivia_pieces(empty()),
+ };
node = node.replace_child(token.into(), new_token.into()).unwrap();
}
SyntaxElement::Node(node)
}
- SyntaxElement::Token(token) => SyntaxElement::Token(
- token
- .with_leading_trivia(
- prev_leading
- .iter()
- .map(|piece| (piece.kind(), piece.text())),
- )
- .with_trailing_trivia(
- prev_trailing
- .iter()
- .map(|piece| (piece.kind(), piece.text())),
- ),
- ),
+ SyntaxElement::Token(token) => {
+ let new_token = match prev_leading_trivia {
+ Some(prev_leading_trivia) => {
+ token.with_leading_trivia_pieces(prev_leading_trivia.pieces())
+ }
+ None => token.with_leading_trivia_pieces(empty()),
+ };
+
+ let new_token = match prev_trailing_trivia {
+ Some(prev_trailing_trivia) => {
+ new_token.with_trailing_trivia_pieces(prev_trailing_trivia.pieces())
+ }
+ None => new_token.with_trailing_trivia_pieces(empty()),
+ };
+ SyntaxElement::Token(new_token)
+ }
};
self.push_change(prev_element, Some(next_element))

MODIFY
crates/rome_rowan/src/ast/mutation.rs
crates/rome_rowan/src/ast/mutation.rs
@@ -95,12 +95,9 @@ where
let next_last = next_node.syntax().last_token();
if let (Some(prev_last), Some(next_last)) = (prev_last, next_last) {
- let pieces: Vec<_> = prev_last.trailing_trivia().pieces().collect();
-
next_node = next_node.replace_token_discard_trivia(
next_last.clone(),
- next_last
- .with_trailing_trivia(pieces.iter().map(|piece| (piece.kind(), piece.text()))),
+ next_last.with_trailing_trivia_pieces(prev_last.trailing_trivia().pieces()),
)?;
}
@@ -130,22 +127,14 @@ where
where
Self: Sized,
{
- let leading_trivia: Vec<_> = prev_token.leading_trivia().pieces().collect();
- let trailing_trivia: Vec<_> = prev_token.trailing_trivia().pieces().collect();
+ let leading_trivia = prev_token.leading_trivia().pieces();
+ let trailing_trivia = prev_token.trailing_trivia().pieces();
self.replace_token_discard_trivia(
prev_token,
next_token
- .with_leading_trivia(
- leading_trivia
- .iter()
- .map(|piece| (piece.kind(), piece.text())),
- )
- .with_trailing_trivia(
- trailing_trivia
- .iter()
- .map(|piece| (piece.kind(), piece.text())),
- ),
+ .with_leading_trivia_pieces(leading_trivia)
+ .with_trailing_trivia_pieces(trailing_trivia),
)
}

MODIFY
crates/rome_rowan/src/cursor/trivia.rs
crates/rome_rowan/src/cursor/trivia.rs
@@ -52,7 +52,7 @@ impl SyntaxTrivia {
}
/// Get the number of TriviaPiece inside this trivia
- fn len(&self) -> usize {
+ pub(crate) fn len(&self) -> usize {
self.green_trivia().len()
}

MODIFY
crates/rome_rowan/src/syntax/node.rs
crates/rome_rowan/src/syntax/node.rs
@@ -255,7 +255,7 @@ impl<L: Language> SyntaxNode<L> {
/// Returns the index of this node inside of its parent
#[inline]
- pub(crate) fn index(&self) -> usize {
+ pub fn index(&self) -> usize {
self.raw.index()
}

MODIFY
crates/rome_rowan/src/syntax/token.rs
crates/rome_rowan/src/syntax/token.rs
@@ -2,8 +2,8 @@ use crate::green::{GreenToken, GreenTrivia};
use crate::syntax::SyntaxTrivia;
use crate::syntax_token_text::SyntaxTokenText;
use crate::{
- cursor, Direction, Language, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, TriviaPiece,
- TriviaPieceKind,
+ cursor, Direction, Language, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode,
+ SyntaxTriviaPiece, TriviaPiece, TriviaPieceKind,
};
use std::fmt;
use std::marker::PhantomData;
@@ -189,12 +189,13 @@ impl<L: Language> SyntaxToken<L> {
/// Return a new version of this token with its leading trivia replaced with `trivia`
#[must_use = "syntax elements are immutable, the result of update methods must be propagated to have any effect"]
- pub fn with_leading_trivia<'a, I>(self, trivia: I) -> Self
+ pub fn with_leading_trivia<'a, I>(&self, trivia: I) -> Self
where
- I: Iterator<Item = (TriviaPieceKind, &'a str)> + ExactSizeIterator,
+ I: IntoIterator<Item = (TriviaPieceKind, &'a str)>,
+ I::IntoIter: ExactSizeIterator,
{
let mut token_text = String::new();
- let trivia = trivia.map(|(kind, text)| {
+ let trivia = trivia.into_iter().map(|(kind, text)| {
token_text.push_str(text);
TriviaPiece::new(kind, TextSize::of(text))
});
@@ -216,11 +217,42 @@ impl<L: Language> SyntaxToken<L> {
}
}
+ /// Return a new version of this token with its leading trivia replaced with `trivia`
+ #[must_use = "syntax elements are immutable, the result of update methods must be propagated to have any effect"]
+ pub fn with_leading_trivia_pieces<I>(&self, trivia: I) -> Self
+ where
+ I: IntoIterator<Item = SyntaxTriviaPiece<L>>,
+ I::IntoIter: ExactSizeIterator,
+ {
+ let mut token_text = String::new();
+ let trivia = trivia.into_iter().map(|piece| {
+ token_text.push_str(piece.text());
+ piece.into_raw_piece()
+ });
+
+ let leading = GreenTrivia::new(trivia);
+
+ // Copy over token text and trailing trivia
+ let leading_len = self.raw.green().leading_trivia().text_len();
+ token_text.push_str(&self.text()[usize::from(leading_len)..]);
+
+ Self {
+ raw: cursor::SyntaxToken::new_detached(GreenToken::with_trivia(
+ self.kind().to_raw(),
+ &token_text,
+ leading,
+ self.green_token().trailing_trivia().clone(),
+ )),
+ _p: PhantomData,
+ }
+ }
+
/// Return a new version of this token with its trailing trivia replaced with `trivia`
#[must_use = "syntax elements are immutable, the result of update methods must be propagated to have any effect"]
- pub fn with_trailing_trivia<'a, I>(self, trivia: I) -> Self
+ pub fn with_trailing_trivia<'a, I>(&self, trivia: I) -> Self
where
- I: Iterator<Item = (TriviaPieceKind, &'a str)> + ExactSizeIterator,
+ I: IntoIterator<Item = (TriviaPieceKind, &'a str)>,
+ I::IntoIter: ExactSizeIterator,
{
let mut token_text = String::new();
@@ -228,7 +260,7 @@ impl<L: Language> SyntaxToken<L> {
let trailing_len = self.green_token().trailing_trivia().text_len();
token_text.push_str(&self.text()[..usize::from(self.text().text_len() - trailing_len)]);
- let trivia = trivia.map(|(kind, text)| {
+ let trivia = trivia.into_iter().map(|(kind, text)| {
token_text.push_str(text);
TriviaPiece::new(kind, TextSize::of(text))
});
@@ -246,6 +278,37 @@ impl<L: Language> SyntaxToken<L> {
}
}
+ /// Return a new version of this token with its trailing trivia replaced with `trivia`
+ #[must_use = "syntax elements are immutable, the result of update methods must be propagated to have any effect"]
+ pub fn with_trailing_trivia_pieces<I>(&self, trivia: I) -> Self
+ where
+ I: IntoIterator<Item = SyntaxTriviaPiece<L>>,
+ I::IntoIter: ExactSizeIterator,
+ {
+ let mut token_text = String::new();
+
+ // copy over leading trivia and token text
+ let trailing_len = self.green_token().trailing_trivia().text_len();
+ token_text.push_str(&self.text()[..usize::from(self.text().text_len() - trailing_len)]);
+
+ let trivia = trivia.into_iter().map(|piece| {
+ token_text.push_str(piece.text());
+ piece.into_raw_piece()
+ });
+
+ let trailing = GreenTrivia::new(trivia);
+
+ Self {
+ raw: cursor::SyntaxToken::new_detached(GreenToken::with_trivia(
+ self.kind().to_raw(),
+ &token_text,
+ self.green_token().leading_trivia().clone(),
+ trailing,
+ )),
+ _p: PhantomData,
+ }
+ }
+
/// Returns the token leading trivia.
///
/// ```

MODIFY
crates/rome_rowan/src/syntax/trivia.rs
crates/rome_rowan/src/syntax/trivia.rs
@@ -224,6 +224,10 @@ pub struct SyntaxTriviaPiece<L: Language> {
}
impl<L: Language> SyntaxTriviaPiece<L> {
+ pub(crate) fn into_raw_piece(self) -> TriviaPiece {
+ self.trivia
+ }
+
/// Returns the internal kind of this trivia piece
pub fn kind(&self) -> TriviaPieceKind {
self.trivia.kind()
@@ -627,6 +631,14 @@ impl<L: Language> SyntaxTrivia<L> {
pub fn text_range(&self) -> TextRange {
self.raw.text_range()
}
+
+ pub fn is_empty(&self) -> bool {
+ self.raw.len() == 0
+ }
+
+ pub fn has_skipped(&self) -> bool {
+ self.pieces().any(|piece| piece.is_skipped())
+ }
}
fn print_debug_str<S: AsRef<str>>(text: S, f: &mut fmt::Formatter<'_>) -> fmt::Result {

feat(rome_rowan): `with_*_trivia_pieces` (#3091)