use super::red::{SyntaxNode, SyntaxToken};
use super::walk::{Visitor, WalkOptions, WalkResult, walk};
#[derive(Clone, Debug)]
pub struct EmitOptions {
pub include_trivia: bool,
pub skip_kind: Option<u16>,
}
impl Default for EmitOptions {
fn default() -> Self {
Self {
include_trivia: true,
skip_kind: None,
}
}
}
impl EmitOptions {
#[must_use]
pub const fn semantic_only() -> Self {
Self {
include_trivia: false,
skip_kind: None,
}
}
#[must_use]
pub fn full() -> Self {
Self::default()
}
}
struct EmitVisitor {
out: String,
options: EmitOptions,
}
impl Visitor for EmitVisitor {
fn visit_token(&mut self, token: &SyntaxToken) -> WalkResult {
if let Some(skip) = self.options.skip_kind {
if token.kind() == skip {
return WalkResult::Continue(());
}
}
if token.is_trivia() && !self.options.include_trivia {
return WalkResult::Continue(());
}
self.out.push_str(token.text());
WalkResult::Continue(())
}
}
#[must_use]
pub fn syntax_root_to_string(root: &SyntaxNode, options: &EmitOptions) -> String {
let mut visitor = EmitVisitor {
out: String::new(),
options: options.clone(),
};
let walk_opts = if options.include_trivia {
WalkOptions::full()
} else {
WalkOptions::semantic_only()
};
let _ = walk(root, &mut visitor, &walk_opts);
visitor.out
}