Skip to content

Commit

Permalink
Merge branch 'master' into introduce-replace_index
Browse files Browse the repository at this point in the history
  • Loading branch information
ketkarameya committed Jun 16, 2023
2 parents 7ef6de5 + 245dab6 commit f5760c0
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/polyglot_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ jobs:
run: |
rustup target add aarch64-apple-darwin
pip install --upgrade maturin
maturin build --release -o dist --universal2
maturin build --release -o dist --target universal2-apple-darwin
- name: Pypi Release for macos-latest
run: |
pip install twine
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ tree-sitter-typescript = "0.20.1"
# TODO: Update after https://github.com/tree-sitter/tree-sitter-go/pull/103 lands
tree-sitter-go = { git = "https://github.com/uber/tree-sitter-go.git", rev = "8f807196afab4a1a1256dbf62a011020c6fe7745" }
tree-sitter-thrift = "0.5.0"
tree-sitter-strings = { git = "https://github.com/ketkarameya/tree-sitter-strings.git" }
tree-sitter-strings = { git = "https://github.com/uber/tree-sitter-strings.git" }
tree-sitter-query = "0.1.0"
derive_builder = "0.12.0"
getset = "0.1.2"
Expand Down
7 changes: 5 additions & 2 deletions polyglot_piranha.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,10 @@ class Filter:
"The minimum number of times the contains query should match in the enclosing node"
at_most: int
"The maximum number of times the contains query should match in the enclosing node"
number_of_children: int
child_count: int
"Number of named children under the primary matched node"
sibling_count: int
"Number of named siblings of the primary matched node"
def __init__(
self,
enclosing_node: Optional[str] = None,
Expand All @@ -182,7 +184,8 @@ class Filter:
contains: Optional[str] = None,
at_least: int = 1,
at_most: int = 4294967295, # u32::MAX
number_of_children: int = 4294967295 # u32::MAX
child_count: int = 4294967295, # u32::MAX
sibling_count: int = 4294967295 # u32::MAX
):
"""
Constructs `Filter`
Expand Down
4 changes: 4 additions & 0 deletions src/models/default_configs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ pub(crate) fn default_child_count() -> u32 {
u32::MAX
}

pub(crate) fn default_sibling_count() -> u32 {
u32::MAX
}

pub(crate) fn default_enclosing_node() -> TSQuery {
TSQuery::new(String::new())
}
Expand Down
31 changes: 23 additions & 8 deletions src/models/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ use crate::utilities::{
};

use super::{
default_configs::default_child_count, rule::InstantiatedRule, rule_store::RuleStore,
source_code_unit::SourceCodeUnit, Validator,
default_configs::default_child_count, default_configs::default_sibling_count,
rule::InstantiatedRule, rule_store::RuleStore, source_code_unit::SourceCodeUnit, Validator,
};

use crate::utilities::{tree_sitter_utilities::TSQuery, Instantiate};
Expand Down Expand Up @@ -80,11 +80,18 @@ pub struct Filter {
at_most: u32,

// number of named children under the primary matched node
#[builder(default = "default_contains_at_most()")]
#[builder(default = "default_child_count()")]
#[get = "pub"]
#[serde(default = "default_contains_at_most")]
#[serde(default = "default_child_count")]
#[pyo3(get)]
child_count: u32,

// number of named siblings of the primary matched node (inclusive)
#[builder(default = "default_sibling_count()")]
#[get = "pub"]
#[serde(default = "default_sibling_count")]
#[pyo3(get)]
sibling_count: u32,
}

#[pymethods]
Expand All @@ -93,7 +100,7 @@ impl Filter {
fn py_new(
enclosing_node: Option<String>, not_enclosing_node: Option<String>,
not_contains: Option<Vec<String>>, contains: Option<String>, at_least: Option<u32>,
at_most: Option<u32>, child_count: Option<u32>,
at_most: Option<u32>, child_count: Option<u32>, sibling_count: Option<u32>,
) -> Self {
FilterBuilder::default()
.enclosing_node(TSQuery::new(enclosing_node.unwrap_or_default()))
Expand All @@ -109,6 +116,7 @@ impl Filter {
.at_least(at_least.unwrap_or(default_contains_at_least()))
.at_most(at_most.unwrap_or(default_contains_at_most()))
.child_count(child_count.unwrap_or(default_child_count()))
.sibling_count(sibling_count.unwrap_or(default_sibling_count()))
.build()
}
gen_py_str_methods!();
Expand Down Expand Up @@ -159,13 +167,14 @@ impl Validator for Filter {
self.not_contains().iter().try_for_each(|x| x.validate())?
}

if *self.child_count() != default_child_count()
if (*self.child_count() != default_child_count()
|| *self.sibling_count() != default_sibling_count())
&& (*self.enclosing_node() != default_enclosing_node()
|| *self.not_enclosing_node() != default_not_enclosing_node()
|| *self.contains() != default_contains_query()
|| *self.not_contains() != default_not_contains_queries())
{
return Err("The child count operator is not compatible with (not) enclosing node and (not) contains operator".to_string());
return Err("The child/sibling count operator is not compatible with (not) enclosing node and (not) contains operator".to_string());
}

Ok(())
Expand Down Expand Up @@ -230,7 +239,7 @@ impl FilterBuilder {
/// ```
///
macro_rules! filter {
($(enclosing_node = $enclosing_node:expr)? $(, not_enclosing_node=$not_enclosing_node:expr)? $(, not_contains= [$($q:expr,)*])? $(, contains= $p:expr)? $(, at_least=$min:expr)? $(, at_most=$max:expr)? $(, child_count=$nChildren:expr)?) => {
($(enclosing_node = $enclosing_node:expr)? $(, not_enclosing_node=$not_enclosing_node:expr)? $(, not_contains= [$($q:expr,)*])? $(, contains= $p:expr)? $(, at_least=$min:expr)? $(, at_most=$max:expr)? $(, child_count=$nChildren:expr)? $(, sibling_count=$nSibling:expr)?) => {
$crate::models::filter::FilterBuilder::default()
$(.enclosing_node($crate::utilities::tree_sitter_utilities::TSQuery::new($enclosing_node.to_string())))?
$(.not_enclosing_node($crate::utilities::tree_sitter_utilities::TSQuery::new($not_enclosing_node.to_string())))?
Expand All @@ -239,6 +248,7 @@ macro_rules! filter {
$(.at_least($min))?
$(.at_most($max))?
$(.child_count($nChildren))?
$(.sibling_count($nSibling))?
.build()
};
}
Expand All @@ -262,6 +272,7 @@ impl Instantiate for Filter {
at_least: self.at_least,
at_most: self.at_most,
child_count: self.child_count,
sibling_count: self.sibling_count,
}
}
}
Expand Down Expand Up @@ -304,6 +315,10 @@ impl SourceCodeUnit {
return node.named_child_count() == (*filter.child_count() as usize);
}

if *filter.sibling_count() != default_sibling_count() {
return node.parent().unwrap().named_child_count() == (*filter.sibling_count() as usize);
}

// Check if no ancestor matches the query for not_enclosing_node
if !self._check_not_enclosing_node(rule_store, node_to_check, &instantiated_filter) {
return false;
Expand Down
13 changes: 12 additions & 1 deletion src/models/unit_tests/rule_graph_validation_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,22 @@ fn test_rule_graph_incorrect_query() {

#[test]
#[should_panic(
expected = "The child count operator is not compatible with (not) enclosing node and (not) contains operator"
expected = "The child/sibling count operator is not compatible with (not) enclosing node and (not) contains operator"
)]
fn test_filter_bad_arg_contains_n_children() {
FilterBuilder::default()
.enclosing_node(TSQuery::new("(method_declaration) @i".to_string()))
.child_count(2)
.build();
}

#[test]
#[should_panic(
expected = "The child/sibling count operator is not compatible with (not) enclosing node and (not) contains operator"
)]
fn test_filter_bad_arg_contains_n_sibling() {
FilterBuilder::default()
.enclosing_node(TSQuery::new("(method_declaration) @i".to_string()))
.sibling_count(2)
.build();
}
71 changes: 71 additions & 0 deletions src/models/unit_tests/source_code_unit_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,77 @@ fn test_satisfies_filters_child_count() {
assert!(!source_code_unit.is_satisfied(*node, &rule_neg, &HashMap::new(), &mut rule_store,));
}

#[test]
fn test_satisfies_filters_sibling_count() {
let rule_positive = piranha_rule! {
name= "test",
query= "(
(method_invocation
name: (_) @name
arguments: (argument_list (_)@arg)) @mi
(#eq? @name \"someOtherFunction\")
(#eq? @arg \"1\")
)",
replace_node= "arg",
replace= "()",
filters= [filter!{
, sibling_count = 3
}]
};
let rule_positive = InstantiatedRule::new(&rule_positive, &HashMap::new());

let rule_neg = piranha_rule! {
name= "test",
query= "(
(method_invocation
name: (_) @name
arguments: (argument_list (_) @arg )) @mi
(#eq? @name \"someOtherFunction\")
(#eq? @arg \"1\")
)",
replace_node= "arg",
replace= "()",
filters= [filter!{
, sibling_count = 2
}]
};
let rule_neg = InstantiatedRule::new(&rule_neg, &HashMap::new());

let source_code = "class Test {
public void foobar(){
boolean isFlagTreated = true;
isFlagTreated = false;
if (isFlagTreated) {
someOtherFunction(1, 2, 3);
}
}
}";

let mut rule_store = RuleStore::default();
let java = get_java_tree_sitter_language();
let mut parser = java.parser();
let piranha_arguments = &PiranhaArgumentsBuilder::default()
.path_to_codebase(UNUSED_CODE_PATH.to_string())
.language(java)
.build();
let source_code_unit = SourceCodeUnit::new(
&mut parser,
source_code.to_string(),
&HashMap::new(),
PathBuf::new().as_path(),
piranha_arguments,
);

let node = &source_code_unit
.root_node()
.descendant_for_byte_range(167, 168)
.unwrap();

assert!(source_code_unit.is_satisfied(*node, &rule_positive, &HashMap::new(), &mut rule_store,));

assert!(!source_code_unit.is_satisfied(*node, &rule_neg, &HashMap::new(), &mut rule_store,));
}

// Tests for contains without providing an enclosing node
fn run_test_satisfies_filters_without_enclosing(
filter: Filter, // Replace with the filter to test
Expand Down

0 comments on commit f5760c0

Please sign in to comment.