Skip to content

Commit

Permalink
feat: IGNORE parts of matches
Browse files Browse the repository at this point in the history
  • Loading branch information
alexpovel committed Mar 21, 2024
1 parent 6b67dfe commit 21b8dde
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 12 deletions.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,41 @@ which can be caught as:
cat sensitive.go | srgn --go-query '(field_declaration name: (field_identifier) @name tag: (raw_string_literal) @tag (#match? @name "[tT]oken") (#not-eq? @tag "`json:\"-\"`"))' --fail-any # will fail
```

###### Ignoring parts of matches

Occassionally, parts of a match need to be ignored, for example when no suitable
tree-sitter node type is available. For example, say we'd like to replace the `error`
with `wrong` inside the string of the macro body:

```rust wrong.rs
fn wrong() {
let wrong = "wrong";
error!("This went error");
}
```

Let's assume there's a node type for matching *entire* macros (`macro_invocation`) and
one to match macro *names* (`((macro_invocation macro: (identifier) @name))`), but
*none* to match macro *contents* (this is wrong, tree-sitter offers this in the form of
`token_tree`, but let's imagine...). To match just `"This went error"`, the entire macro
would need to be matched, with the name part ignored. Any capture name containing
`IGNORE` will provide just that:

```bash
cat wrong.rs | srgn --rust-query '((macro_invocation macro: (identifier) @IGNORE_name) @macro)' 'error' 'wrong'
```

```rust output-wrong.rs
fn wrong() {
let wrong = "wrong";
error!("This went wrong");
}
```

If it weren't ignored, the result would read `wrong!("This went wrong");`.

###### Further reading

These matching expressions are a mouthful. A couple resources exist for getting started
with your own queries:

Expand Down
26 changes: 14 additions & 12 deletions src/scoping/langs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,22 @@ pub trait LanguageScoper: Scoper {

let ranges = run(query);

let has_ignore = query.capture_names().iter().any(|name| name == IGNORE);
let is_ignored = |name: &str| name.contains(IGNORE);
let has_ignored_captures = query.capture_names().iter().any(|name| is_ignored(name));

if has_ignore {
if has_ignored_captures {
let ignored_ranges = {
disable_all_captures_except(IGNORE, query);
let acknowledged_captures = query
.capture_names()
.iter()
.filter(|name| !is_ignored(name))
.cloned()
.collect::<Vec<_>>();

for name in acknowledged_captures {
trace!("Disabling capture for: {:?}", name);
query.disable_capture(&name);
}

debug!("Query has captures to ignore: running additional query");
run(query)
Expand All @@ -150,12 +161,3 @@ pub trait LanguageScoper: Scoper {
}
}
}

fn disable_all_captures_except(capture_name: &str, query: &mut TSQuery) {
let capture_names = query.capture_names().to_owned();
for name in capture_names {
if name != capture_name {
query.disable_capture(&name);
}
}
}

0 comments on commit 21b8dde

Please sign in to comment.