ast_grep_core/
language.rs

1use crate::matcher::PatternBuilder;
2use crate::meta_var::{extract_meta_var, MetaVariable};
3use crate::{Pattern, PatternError};
4use std::borrow::Cow;
5use std::path::Path;
6
7/// Trait to abstract ts-language usage in ast-grep, which includes:
8/// * which character is used for meta variable.
9/// * if we need to use other char in meta var for parser at runtime
10/// * pre process the Pattern code.
11pub trait Language: Clone + 'static {
12  /// normalize pattern code before matching
13  /// e.g. remove expression_statement, or prefer parsing {} to object over block
14  fn pre_process_pattern<'q>(&self, query: &'q str) -> Cow<'q, str> {
15    Cow::Borrowed(query)
16  }
17
18  /// Configure meta variable special character
19  /// By default $ is the metavar char, but in PHP it can be #
20  #[inline]
21  fn meta_var_char(&self) -> char {
22    '$'
23  }
24
25  /// Some language does not accept $ as the leading char for identifiers.
26  /// We need to change $ to other char at run-time to make parser happy, thus the name expando.
27  /// By default this is the same as meta_var char so replacement is done at runtime.
28  #[inline]
29  fn expando_char(&self) -> char {
30    self.meta_var_char()
31  }
32
33  /// extract MetaVariable from a given source string
34  /// At runtime we need to use expand_char
35  fn extract_meta_var(&self, source: &str) -> Option<MetaVariable> {
36    extract_meta_var(source, self.expando_char())
37  }
38  /// Return the file language from path. Return None if the file type is not supported.
39  fn from_path<P: AsRef<Path>>(_path: P) -> Option<Self> {
40    // TODO: throw panic here if not implemented properly?
41    None
42  }
43
44  fn kind_to_id(&self, kind: &str) -> u16;
45  fn field_to_id(&self, field: &str) -> Option<u16>;
46  fn build_pattern(&self, builder: &PatternBuilder) -> Result<Pattern, PatternError>;
47}
48
49#[cfg(test)]
50pub use test::*;
51
52#[cfg(test)]
53mod test {
54  use super::*;
55  use crate::tree_sitter::{LanguageExt, StrDoc, TSLanguage};
56
57  #[derive(Clone)]
58  pub struct Tsx;
59  impl Language for Tsx {
60    fn kind_to_id(&self, kind: &str) -> u16 {
61      let ts_lang: TSLanguage = tree_sitter_typescript::LANGUAGE_TSX.into();
62      ts_lang.id_for_node_kind(kind, /* named */ true)
63    }
64    fn field_to_id(&self, field: &str) -> Option<u16> {
65      self
66        .get_ts_language()
67        .field_id_for_name(field)
68        .map(|f| f.get())
69    }
70    fn build_pattern(&self, builder: &PatternBuilder) -> Result<Pattern, PatternError> {
71      builder.build(|src| StrDoc::try_new(src, self.clone()))
72    }
73  }
74  impl LanguageExt for Tsx {
75    fn get_ts_language(&self) -> TSLanguage {
76      tree_sitter_typescript::LANGUAGE_TSX.into()
77    }
78  }
79}