1#![cfg(not(feature = "napi-noop-in-unit-test"))]
2
3mod doc;
4mod find_files;
5mod napi_lang;
6mod sg_node;
7
8use ast_grep_core::{AstGrep, Language};
9use ast_grep_language::SupportLang;
10use napi::bindgen_prelude::*;
11use napi_derive::napi;
12use napi_lang::register_dynamic_language as register_dynamic_language_impl;
13
14use doc::{JsDoc, NapiConfig};
15use find_files::{find_in_files_impl, FindConfig, FindInFiles, ParseAsync};
16use napi_lang::NapiLang;
17use sg_node::SgRoot;
18
19pub use find_files::parse_files;
20
21macro_rules! impl_lang_mod {
22 ($name: ident, $lang: ident) => {
23 #[napi]
24 pub mod $name {
25 use super::*;
26
27 #[napi]
28 pub fn parse(src: String) -> SgRoot {
29 parse_with_lang(SupportLang::$lang.to_string(), src).expect("parse failed")
30 }
31
32 #[napi]
33 pub fn parse_async(src: String) -> Result<AsyncTask<ParseAsync>> {
34 parse_async_with_lang(SupportLang::$lang.to_string(), src)
35 }
36 #[napi]
37 pub fn kind(kind_name: String) -> Result<u16> {
38 kind_with_lang(SupportLang::$lang.to_string(), kind_name)
39 }
40 #[napi]
41 pub fn pattern(pattern: String) -> NapiConfig {
42 pattern_with_lang(SupportLang::$lang.to_string(), pattern)
43 }
44 #[napi]
45 pub fn find_in_files(
46 config: FindConfig,
47 callback: JsFunction,
48 ) -> Result<AsyncTask<FindInFiles>> {
49 find_in_files_impl(SupportLang::$lang.into(), config, callback)
50 }
51 }
52 };
53}
54
55use kind as kind_with_lang;
57use parse as parse_with_lang;
58use parse_async as parse_async_with_lang;
59use pattern as pattern_with_lang;
60impl_lang_mod!(html, Html);
61impl_lang_mod!(js, JavaScript);
62impl_lang_mod!(jsx, JavaScript);
63impl_lang_mod!(ts, TypeScript);
64impl_lang_mod!(tsx, Tsx);
65impl_lang_mod!(css, Css);
66
67#[napi]
69pub fn parse(lang: String, src: String) -> Result<SgRoot> {
70 let doc = JsDoc::new(src, lang.parse()?);
71 Ok(SgRoot(AstGrep::doc(doc), "anonymous".into()))
72}
73
74#[napi]
80pub fn parse_async(lang: String, src: String) -> Result<AsyncTask<ParseAsync>> {
81 let lang = lang.parse()?;
82 Ok(AsyncTask::new(ParseAsync { src, lang }))
83}
84
85#[napi]
87pub fn kind(lang: String, kind_name: String) -> Result<u16> {
88 let lang: NapiLang = lang.parse()?;
89 let kind = lang
90 .get_ts_language()
91 .id_for_node_kind(&kind_name, true);
92 Ok(kind)
93}
94
95#[napi]
97pub fn pattern(lang: String, pattern: String) -> NapiConfig {
98 NapiConfig {
99 rule: serde_json::json!({
100 "pattern": pattern,
101 }),
102 constraints: None,
103 language: Some(lang),
104 utils: None,
105 transform: None,
106 }
107}
108
109#[napi]
114pub fn find_in_files(
115 lang: String,
116 config: FindConfig,
117 callback: JsFunction,
118) -> Result<AsyncTask<FindInFiles>> {
119 let lang: NapiLang = lang.parse()?;
120 find_in_files_impl(lang, config, callback)
121}
122
123#[napi]
126pub fn register_dynamic_language(langs: serde_json::Value) -> Result<()> {
127 let langs = serde_json::from_value(langs)?;
128 register_dynamic_language_impl(langs)
129}