ast_grep_core/
lib.rs

1/*!
2This module contains the core library for ast-grep.
3
4It provides APIs for parsing, traversing, searching and replacing tree-sitter nodes.
5Usually you will only need ast-grep CLI instead of this crate.
6But if you want to use ast-grep as a library, this is the right place.
7*/
8
9pub mod language;
10pub mod matcher;
11pub mod meta_var;
12pub mod ops;
13pub mod replacer;
14pub mod source;
15#[cfg(feature = "tree-sitter")]
16pub mod tree_sitter;
17
18#[doc(hidden)]
19pub mod pinned;
20
21mod match_tree;
22mod node;
23
24pub use language::Language;
25pub use match_tree::MatchStrictness;
26pub use matcher::{Matcher, NodeMatch, Pattern, PatternError};
27pub use node::{Node, Position};
28pub use source::Doc;
29
30use node::Root;
31
32pub type AstGrep<D> = Root<D>;
33
34#[cfg(test)]
35mod test {
36  use super::*;
37  use crate::tree_sitter::LanguageExt;
38  use language::Tsx;
39  use ops::Op;
40
41  pub type Result = std::result::Result<(), String>;
42
43  #[test]
44  fn test_replace() -> Result {
45    let mut ast_grep = Tsx.ast_grep("var a = 1; let b = 2;");
46    ast_grep.replace("var $A = $B", "let $A = $B")?;
47    let source = ast_grep.generate();
48    assert_eq!(source, "let a = 1; let b = 2;"); // note the semicolon
49    Ok(())
50  }
51
52  #[test]
53  fn test_replace_by_rule() -> Result {
54    let rule = Op::either("let a = 123").or("let b = 456");
55    let mut ast_grep = Tsx.ast_grep("let a = 123");
56    let replaced = ast_grep.replace(rule, "console.log('it works!')")?;
57    assert!(replaced);
58    let source = ast_grep.generate();
59    assert_eq!(source, "console.log('it works!')");
60    Ok(())
61  }
62
63  #[test]
64  fn test_replace_unnamed_node() -> Result {
65    // ++ and -- is unnamed node in tree-sitter javascript
66    let mut ast_grep = Tsx.ast_grep("c++");
67    ast_grep.replace("$A++", "$A--")?;
68    let source = ast_grep.generate();
69    assert_eq!(source, "c--");
70    Ok(())
71  }
72
73  #[test]
74  fn test_replace_trivia() -> Result {
75    let mut ast_grep = Tsx.ast_grep("var a = 1 /*haha*/;");
76    ast_grep.replace("var $A = $B", "let $A = $B")?;
77    let source = ast_grep.generate();
78    assert_eq!(source, "let a = 1 /*haha*/;"); // semicolon
79
80    let mut ast_grep = Tsx.ast_grep("var a = 1; /*haha*/");
81    ast_grep.replace("var $A = $B", "let $A = $B")?;
82    let source = ast_grep.generate();
83    assert_eq!(source, "let a = 1; /*haha*/");
84    Ok(())
85  }
86
87  #[test]
88  fn test_replace_trivia_with_skipped() -> Result {
89    let mut ast_grep = Tsx.ast_grep("return foo(1, 2,) /*haha*/;");
90    ast_grep.replace("return foo($A, $B)", "return bar($A, $B)")?;
91    let source = ast_grep.generate();
92    assert_eq!(source, "return bar(1, 2) /*haha*/;"); // semicolon
93    Ok(())
94  }
95}