Skip to content

Instantly share code, notes, and snippets.

@mkatychev
Last active October 24, 2025 19:38
Show Gist options
  • Select an option

  • Save mkatychev/f205b30697927ee329ac9b5a64f1508d to your computer and use it in GitHub Desktop.

Select an option

Save mkatychev/f205b30697927ee329ac9b5a64f1508d to your computer and use it in GitHub Desktop.
To run: `cargo +nightly -Zscript ./wit_doc_comment.rs`
---cargo
[dependencies]
tree-sitter-wit = { git = "https://github.com/bytecodealliance/tree-sitter-wit", version = "1.2.0" }
tree-sitter = "0.25.10"
---
use tree_sitter::{Parser, Point, Query, QueryCursor, StreamingIterator};
const WIT_FILE: &str = "
/// DOC COMMENT `wasmcloud`
package wasmcloud:bus@1.0.0;
// NOT a doc comment!
interface lattice {
/// NO MATCH doc comment, it does not immediately precede an object
no-match: func() -> bool;
/// DOC COMMENT `call-target-interface`
resource call-target-interface {
constructor(namespace: string, %package: string, %interface: string);
}
/// DOC COMMENT for call-target-interface
set-link-name: func(name: string, interfaces: list<call-target-interface>);
}
";
// match a doc comment string that is immediately followed by a node without the
// `doc` field (!doc)
const QUERY_STR: &str = "((_ (doc_comment)) @obj_comment . (_ !doc) @obj)";
fn main() {
let mut parser = Parser::new();
parser
.set_language(&tree_sitter_wit::LANGUAGE.into())
.expect("Error loading WIT grammar");
let tree = parser.parse(WIT_FILE, None).unwrap();
let root_node = tree.root_node();
let query = Query::new(&tree_sitter_wit::LANGUAGE.into(), QUERY_STR).unwrap();
let mut cursor = QueryCursor::new();
let mut matches = cursor.matches(&query, root_node, WIT_FILE.as_bytes());
while let Some(mat) = matches.next() {
let [end, obj] = mat.captures.try_into().unwrap();
// https://docs.rs/tree-sitter/latest/tree_sitter/struct.Node.html#method.is_named
if !obj.node.is_named() {
continue;
}
// struct Point { row, column }
let comment_start: Point = end.node.start_position();
let obj_start: Point = obj.node.start_position();
// this means our obj is not immediately preceded by doc comment
if comment_start.row + 1 != obj_start.row {
continue;
}
let doc_comment_str = &WIT_FILE[end.node.byte_range()].trim();
let obj_str = &WIT_FILE[obj.node.byte_range()].trim();
println!("<\n doc_comment[{comment_start}]: {doc_comment_str}");
println!(" obj[{obj_start}]: {obj_str}\n>");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment