type_sitter_proc/lib.rs
1#![doc = include_str!("../README.md")]
2
3use crate::generate_queries_args::GenerateQueriesArgs;
4use generate_nodes_args::GenerateNodesArgs;
5use syn::parse_macro_input;
6
7mod generate_nodes_args;
8mod generate_queries_args;
9
10/// Generate typed AST node wrappers.
11///
12/// # Parameters
13/// - `0`: Path to the `node-types.json` file of the language, relative to the crate root.
14///
15/// # Note
16///
17/// If you included the tree-sitter language as a dependency that is downloaded from the internet,
18/// you need to vendor it or at least vendor its `node-types.json`, because this macro needs its
19/// path and I don't know how to get it from the crate.
20///
21/// # Example
22///
23/// ```ignore
24/// # Doc tests give hygiene errors, so instead we use crate `type-sitter` to test these
25/// use type_sitter_proc::generate_nodes;
26///
27/// generate_nodes!("vendor/tree-sitter-json/src/node-types.json");
28/// ```
29#[proc_macro]
30pub fn generate_nodes(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
31 let args = parse_macro_input!(item as GenerateNodesArgs);
32 type_sitter_gen::generate_nodes(args.path.as_path())
33 .map(|g| g.collapse())
34 .unwrap_or_else(|err| err.to_compile_error())
35 .into()
36}
37
38/// Generate typed wrappers for tree-sitter queries.
39///
40/// # Parameters
41/// - `0`: Path to the queries, relative to the crate root. Must point to a `.scm` or directory of
42/// `.scm` files. If a directory, this function will generate submodules for each `.scm`.
43/// - `1`: the path to the tree-sitter language root, relative to the crate root. Typically
44/// `vendor/tree-sitter-<language>`.
45/// - `2`: Path to the crate with the typed node wrappers. Typically `super::nodes` (and then put an
46/// invocation of [`generate_nodes!`] at top-level in the sister crate `nodes.rs`).
47///
48/// # Example
49///
50/// ```ignore
51/// # Doc tests give hygiene errors, so instead we use crate `type-sitter` to test these
52/// use type_sitter_proc::generate_queries;
53///
54/// generate_queries!("vendor/tree-sitter-typescript/queries/tags.scm", "vendor/tree-sitter-typescript", super::typescript_nodes);
55/// generate_queries!("vendor/tree-sitter-rust/queries", "vendor/tree-sitter-rust", super::rust_nodes);
56/// ```
57#[proc_macro]
58pub fn generate_queries(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
59 let args = parse_macro_input!(item as GenerateQueriesArgs);
60 type_sitter_gen::generate_queries(
61 &args.path,
62 &args.language_path,
63 &args.nodes,
64 use_yak_sitter(),
65 )
66 .map(|g| g.collapse(&args.nodes))
67 .unwrap_or_else(|err| err.to_compile_error())
68 .into()
69}
70
71#[cfg(feature = "yak-sitter")]
72fn use_yak_sitter() -> bool {
73 true
74}
75
76#[cfg(not(feature = "yak-sitter"))]
77fn use_yak_sitter() -> bool {
78 false
79}