ast_grep_py/
lib.rs

1#![cfg(not(test))]
2#![cfg(feature = "python")]
3mod py_lang;
4mod py_node;
5mod range;
6mod unicode_position;
7use py_lang::register_dynamic_language;
8use py_node::{Edit, SgNode};
9use range::{Pos, Range};
10
11use ast_grep_core::{AstGrep, Language, NodeMatch, StrDoc};
12use py_lang::PyLang;
13use pyo3::prelude::*;
14
15use unicode_position::UnicodePosition;
16
17/// A Python module implemented in Rust.
18#[pymodule]
19fn ast_grep_py(_py: Python, m: &Bound<PyModule>) -> PyResult<()> {
20  m.add_class::<SgRoot>()?;
21  m.add_class::<SgNode>()?;
22  m.add_class::<Range>()?;
23  m.add_class::<Pos>()?;
24  m.add_class::<Edit>()?;
25  m.add_function(wrap_pyfunction!(register_dynamic_language, m)?)?;
26  Ok(())
27}
28
29#[pyclass]
30struct SgRoot {
31  inner: AstGrep<StrDoc<PyLang>>,
32  filename: String,
33  pub(crate) position: UnicodePosition,
34}
35
36#[pymethods]
37impl SgRoot {
38  #[new]
39  fn new(src: &str, lang: &str) -> Self {
40    let position = UnicodePosition::new(src);
41    let lang: PyLang = lang.parse().unwrap();
42    let inner = lang.ast_grep(src);
43    Self {
44      inner,
45      filename: "anonymous".into(),
46      position,
47    }
48  }
49
50  fn root(slf: PyRef<Self>) -> SgNode {
51    let tree = unsafe { &*(&slf.inner as *const AstGrep<_>) } as &'static AstGrep<_>;
52    let inner = NodeMatch::from(tree.root());
53    SgNode {
54      inner,
55      root: slf.into(),
56    }
57  }
58
59  fn filename(&self) -> &str {
60    &self.filename
61  }
62}