Skip to content

Commit

Permalink
Add a debug helper for syntax tree as DOT
Browse files Browse the repository at this point in the history
  • Loading branch information
Wilfred committed Nov 15, 2024
1 parent 4df51dc commit d5b1e26
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 0 deletions.
23 changes: 23 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,29 @@ fn main() {
}
}
}
Mode::DumpSyntaxDotty {
path,
ignore_comments,
language_overrides,
} => {
let path = Path::new(&path);
let bytes = read_or_die(path);
let src = String::from_utf8_lossy(&bytes).to_string();

let language = guess(path, &src, &language_overrides);
match language {
Some(lang) => {
let ts_lang = tsp::from_language(lang);
let arena = Arena::new();
let ast = tsp::parse(&arena, &src, &ts_lang, ignore_comments);
init_all_info(&ast, &[]);
syntax::print_as_dot(&ast);
}
None => {
eprintln!("No tree-sitter parser for file: {:?}", path);
}
}
}
Mode::ListLanguages {
use_color,
language_overrides,
Expand Down
22 changes: 22 additions & 0 deletions src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,15 @@ fn app() -> clap::Command<'static> {
"Parse a single file with tree-sitter and display the difftastic syntax tree.",
).help_heading("DEBUG OPTIONS"),
)
.arg(
Arg::new("dump-syntax-dotty")
.long("dump-syntax-dotty")
.takes_value(true)
.value_name("PATH")
.long_help(
"Parse a single file with tree-sitter and display the difftastic syntax tree, as a dotty graph.",
).help_heading("DEBUG OPTIONS"),
)
.arg(
Arg::new("dump-ts")
.long("dump-ts")
Expand Down Expand Up @@ -485,6 +494,11 @@ pub(crate) enum Mode {
ignore_comments: bool,
language_overrides: Vec<(LanguageOverride, Vec<glob::Pattern>)>,
},
DumpSyntaxDotty {
path: String,
ignore_comments: bool,
language_overrides: Vec<(LanguageOverride, Vec<glob::Pattern>)>,
},
}

fn common_path_suffix(lhs_path: &Path, rhs_path: &Path) -> Option<String> {
Expand Down Expand Up @@ -644,6 +658,14 @@ pub(crate) fn parse_args() -> Mode {
};
}

if let Some(path) = matches.value_of("dump-syntax-dotty") {
return Mode::DumpSyntaxDotty {
path: path.to_owned(),
ignore_comments,
language_overrides,
};
}

if let Some(path) = matches.value_of("dump-ts") {
return Mode::DumpTreeSitter {
path: path.to_owned(),
Expand Down
37 changes: 37 additions & 0 deletions src/parse/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,43 @@ pub(crate) fn init_all_info<'a>(lhs_roots: &[&'a Syntax<'a>], rhs_roots: &[&'a S
init_next_prev(rhs_roots);
}

pub(crate) fn print_as_dot<'a>(roots: &[&'a Syntax<'a>]) {
println!("digraph {{");
print_as_dot_(roots);
println!("}}");
}

fn print_as_dot_<'a>(nodes: &[&'a Syntax<'a>]) {
for node in nodes {
let label = match node {
List {
open_content,
close_content,
..
} => {
if open_content != "" {
&format!("[label=\"{open_content}{close_content}\"]")
} else {
&"[style=dotted]".to_owned()
}
}
Atom { content, .. } => {
let content = content.replace("\"", "\\\"");
&format!("[label=\"{content}\"]")
}
};

println!(" id{} {};", node.id().get(), label);

if let List { children, .. } = node {
for child in children {
println!(" id{} -> id{};", node.id().get(), child.id().get());
}
print_as_dot_(children);
}
}
}

fn init_info<'a>(lhs_roots: &[&'a Syntax<'a>], rhs_roots: &[&'a Syntax<'a>]) {
let mut id = NonZeroU32::new(1).unwrap();
init_info_on_side(lhs_roots, &mut id);
Expand Down

0 comments on commit d5b1e26

Please sign in to comment.