Skip to content

Commit

Permalink
Remove artifact
Browse files Browse the repository at this point in the history
  • Loading branch information
danieltrt committed Jun 20, 2023
2 parents f3d76cf + 5f3d820 commit 77846af
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 9 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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
Version 0.3.9
-------------
* Rule graph validation #493
* Bug fix #497 #499
* Kotlin dependency update

Version 0.3.8
-------------
* Bug Fix related to code snippet mode #489
Expand Down
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ authors = [
]
name = "piranha"
description = "Polyglot Piranha is a library for performing structural find and replace with deep cleanup."
version = "0.3.8"
version = "0.3.9"
edition = "2021"
include = ["pyproject.toml", "src/"]
exclude = ["legacy"]
Expand Down Expand Up @@ -49,8 +49,8 @@ log = "0.4.16"
env_logger = "0.10.0"
tempdir = "0.3"
serde_json = "1.0.82"
# TODO: Update after https://github.com/fwcd/tree-sitter-kotlin/pull/71 lands
tree-sitter-kotlin = { git = "https://github.com/ketkarameya/tree-sitter-kotlin.git", rev = "a87ddd003368e068563f1cc478a1b2a3f9d73b60" }

tree-sitter-kotlin = { git = "https://github.com/fwcd/tree-sitter-kotlin.git" }
# TODO: Update after next version is released (https://github.com/tree-sitter/tree-sitter-java/issues/146)
tree-sitter-java = { git = "https://github.com/tree-sitter/tree-sitter-java.git", rev = "c194ee5e6ede5f26cf4799feead4a8f165dcf14d" }
# TODO: Update after: https://github.com/alex-pinkus/tree-sitter-swift/issues/278 resolves
Expand All @@ -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
8 changes: 7 additions & 1 deletion polyglot_piranha.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -172,14 +172,20 @@ 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"
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,
not_enclosing_node: Optional[str] = None,
not_contains: list[str] = [],
contains: Optional[str] = None,
at_least: int = 1,
at_most: int = 4294967295 # u32::MAX
at_most: int = 4294967295, # u32::MAX
child_count: int = 4294967295, # u32::MAX
sibling_count: int = 4294967295 # u32::MAX
):
"""
Constructs `Filter`
Expand Down
8 changes: 8 additions & 0 deletions src/models/default_configs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,14 @@ pub(crate) fn default_contains_at_most() -> u32 {
u32::MAX
}

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
44 changes: 42 additions & 2 deletions src/models/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use crate::utilities::{
};

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

Expand Down Expand Up @@ -77,6 +78,20 @@ pub struct Filter {
#[serde(default = "default_contains_at_most")]
#[pyo3(get)]
at_most: u32,

// number of named children under the primary matched node
#[builder(default = "default_child_count()")]
#[get = "pub"]
#[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 @@ -85,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>,
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 @@ -100,6 +115,8 @@ impl Filter {
.contains(TSQuery::new(contains.unwrap_or_default()))
.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 @@ -149,6 +166,17 @@ impl Validator for Filter {
if *self.not_contains() != default_not_contains_queries() {
self.not_contains().iter().try_for_each(|x| x.validate())?
}

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/sibling count operator is not compatible with (not) enclosing node and (not) contains operator".to_string());
}

Ok(())
}
}
Expand Down Expand Up @@ -211,14 +239,16 @@ 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)?) => {
($(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())))?
$(.not_contains(vec![$($crate::utilities::tree_sitter_utilities::TSQuery::new($q.to_string()),)*]))?
$(.contains($crate::utilities::tree_sitter_utilities::TSQuery::new($p.to_string())))?
$(.at_least($min))?
$(.at_most($max))?
$(.child_count($nChildren))?
$(.sibling_count($nSibling))?
.build()
};
}
Expand All @@ -241,6 +271,8 @@ impl Instantiate for Filter {
contains: self.contains().instantiate(substitutions_for_holes),
at_least: self.at_least,
at_most: self.at_most,
child_count: self.child_count,
sibling_count: self.sibling_count,
}
}
}
Expand Down Expand Up @@ -279,6 +311,14 @@ impl SourceCodeUnit {
let mut node_to_check = node;
let instantiated_filter = filter.instantiate(substitutions);

if *filter.child_count() != default_child_count() {
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
2 changes: 1 addition & 1 deletion src/models/language.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ impl std::str::FromStr for PiranhaLanguage {
scopes: parse_toml::<ScopeConfig>(include_str!("../cleanup_rules/kt/scope_config.toml"))
.scopes()
.to_vec(),
comment_nodes: vec!["comment".to_string()],
comment_nodes: vec!["comment".to_string(), "line_comment".to_string()],
})
}
PYTHON => Ok(PiranhaLanguage {
Expand Down
22 changes: 22 additions & 0 deletions src/models/unit_tests/rule_graph_validation_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,25 @@ fn test_rule_graph_incorrect_query() {
])
.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_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();
}
140 changes: 140 additions & 0 deletions src/models/unit_tests/source_code_unit_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,146 @@ fn test_satisfies_filters_not_contains_negative() {
));
}

#[test]
fn test_satisfies_filters_child_count() {
let rule_positive = piranha_rule! {
name= "test",
query= "(
(method_invocation
name: (_) @name
arguments: (argument_list)@args) @mi
(#eq? @name \"someOtherFunction\")
)",
replace_node= "args",
replace= "()",
filters= [filter!{
, child_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)@args) @mi
(#eq? @name \"someOtherFunction\")
)",
replace_node= "args",
replace= "()",
filters= [filter!{
, child_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, 175)
.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,));
}

#[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 77846af

Please sign in to comment.