fix: reintroduce the root node for anchoring flexibility
This commit is contained in:
24
README.md
24
README.md
@@ -84,7 +84,7 @@ This API parses code into an AST (Abstract Syntax Tree) via tree-sitter and can
|
||||
``` kdl
|
||||
description "describes the mutation collection"
|
||||
mutation {
|
||||
expression "some ((beautiful) @adjective) AST expression"
|
||||
expression "(some ((beautiful) @adjective) AST expression) @root"
|
||||
substitute {
|
||||
literal "hello"
|
||||
capture "adjective"
|
||||
@@ -93,7 +93,7 @@ mutation {
|
||||
}
|
||||
|
||||
mutation {
|
||||
expression "another"
|
||||
expression "(another) @root"
|
||||
substitute {
|
||||
literal "multiple mutations work"
|
||||
literal "as long as their expression"
|
||||
@@ -104,14 +104,30 @@ mutation {
|
||||
|
||||
- `description`: A textual description of the mutation collection.
|
||||
- `mutation`: Defines individual code changes.
|
||||
- `expression`: Uses tree-sitter to match and capture AST nodes with `@` prefixes, The special `@root` node is reserved for the entire expression.
|
||||
- `expression`: Uses tree-sitter to match and capture AST nodes with `@` prefixes,
|
||||
- The special `@root` node must be specify the expression to be replaced.
|
||||
- `substitute`: Constructs the modified code using literals and captured arguments.
|
||||
|
||||
See the example mutation collection in `./snippets/v2/go/mutations.kdl`.
|
||||
See the example mutation collection in `./snippets/v2/go/filepath-parent.kdl`.
|
||||
|
||||
- The API performs a single-pass substitution based on the closest matching mutation.
|
||||
- Captured groups are used within the `substitute` block and the mutated code is returned.
|
||||
|
||||
> Every capture group must contain the largest atom to be operated on.
|
||||
For example: if you wish to operate on elements of an array, capture each identifier inside the array
|
||||
|
||||
Correct way: Here the `array` and `identifier` only hints about where the expression `root` lies.
|
||||
|
||||
```
|
||||
(array (identifier @root))
|
||||
```
|
||||
|
||||
Incorrect way: Here the root expression matches the block all the array elements inside the braces, not each element.
|
||||
|
||||
```
|
||||
(array ((identifier)*) @entire-block-capture) @root
|
||||
```
|
||||
|
||||
**Further reading**
|
||||
|
||||
- [tree-sitter query snytax](https://tree-sitter.github.io/tree-sitter/using-parsers/queries/1-syntax.html) to create mutation expressions.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
description "base64 import"
|
||||
mutation {
|
||||
expression "import_spec_list ((import_spec)* @imports)"
|
||||
expression "(import_spec_list ((import_spec)* @spec)) @root"
|
||||
substitute {
|
||||
literal "("
|
||||
literal "\n"
|
||||
capture "imports"
|
||||
capture "spec"
|
||||
literal "\n"
|
||||
literal #""base64""#
|
||||
literal "\n"
|
||||
|
||||
@@ -4,7 +4,7 @@ mutation {
|
||||
(call_expression
|
||||
function: (_) @func (#eq? @func "filepath.Base")
|
||||
arguments: (_) @args
|
||||
)
|
||||
) @root
|
||||
"""
|
||||
substitute {
|
||||
literal "filepath.Base(filepath.Dir(filepath.Clean"
|
||||
@@ -73,7 +73,7 @@ pub fn from_path<P: AsRef<Path>>(path: P) -> Result<MutationCollection> {
|
||||
}
|
||||
|
||||
mutations.push(Mutation {
|
||||
expression,
|
||||
expression: expression.to_string(),
|
||||
substitute,
|
||||
})
|
||||
}
|
||||
@@ -156,8 +156,7 @@ pub fn query<'a>(
|
||||
lang: &Language,
|
||||
source_bytes: &[u8],
|
||||
) -> Vec<QueryCooked> {
|
||||
let expr = format!("({expr}) @root");
|
||||
let query = Query::new(lang, &expr).unwrap();
|
||||
let query = Query::new(lang, expr).unwrap();
|
||||
|
||||
let mut qc = QueryCursor::new();
|
||||
let mut query_matches = qc.matches(&query, node, source_bytes);
|
||||
@@ -194,7 +193,6 @@ pub fn query<'a>(
|
||||
if *name == "root" {
|
||||
start = start_pos.unwrap();
|
||||
end = end_pos.unwrap();
|
||||
continue;
|
||||
}
|
||||
let range = start_pos.unwrap()..end_pos.unwrap();
|
||||
// println!("match range for {name}: {:#?}", range);
|
||||
|
||||
Reference in New Issue
Block a user