diff --git a/polyglot/piranha/src/lib.rs b/polyglot/piranha/src/lib.rs index 22601f488..95aa35ecb 100644 --- a/polyglot/piranha/src/lib.rs +++ b/polyglot/piranha/src/lib.rs @@ -13,8 +13,8 @@ Copyright (c) 2022 Uber Technologies, Inc. use config::CommandLineArguments; use models::{ - piranha_arguments::PiranhaArguments, - piranha_output::PiranhaOutputSummary, source_code_unit::SourceCodeUnit, + piranha_arguments::PiranhaArguments, piranha_output::PiranhaOutputSummary, + source_code_unit::SourceCodeUnit, }; mod config; @@ -47,22 +47,23 @@ use crate::{ utilities::tree_sitter_utilities::get_node_for_range, }; -use pyo3::prelude::{PyModule, PyResult, Python, pyfunction, pymodule, wrap_pyfunction}; +use pyo3::prelude::{pyfunction, pymodule, wrap_pyfunction, PyModule, PyResult, Python}; use std::collections::VecDeque; use tree_sitter::Node; -/// Executes piranha for the provided configuration at {path_to_configurations} upon the given {path_to_codebase}. -/// +/// Executes piranha for the provided configuration at {path_to_configurations} upon the given {path_to_codebase}. +/// /// # Arguments: /// * path_to_codebase: Path to the root of the code base that Piranha will update /// * path_to_configuration: PAth to the directory that contains - `piranha_arguments.toml`, `rules.toml` and optionally `edges.toml` /// * should_rewrite: determines if Piranha should actually update the code. -/// +/// /// Returns Piranha Output Summary for each file touched or analyzed by Piranha. -/// For each file, it reports its content after the rewrite, the list of matches and the list of rewrites. +/// For each file, it reports its content after the rewrite, the list of matches and the list of rewrites. #[pyfunction] pub fn run_piranha_cli( - path_to_codebase: String, path_to_configurations: String, should_rewrite_files: bool) -> Vec { + path_to_codebase: String, path_to_configurations: String, should_rewrite_files: bool, +) -> Vec { let configuration = PiranhaArguments::new(CommandLineArguments { path_to_codebase, path_to_configurations, @@ -388,7 +389,6 @@ impl FlagCleaner { .iter() .any(|x| x.holes().is_empty()); let pattern = self.get_grep_heuristics(); - info!("{}", format!("Searching pattern {}", pattern).green()); let files: HashMap = WalkDir::new(&self.path_to_codebase) // Walk over the entire code base .into_iter() @@ -410,7 +410,7 @@ impl FlagCleaner { .filter(|x| no_global_rules_with_holes || pattern.is_match(x.1.as_str())) .collect(); #[rustfmt::skip] - println!("{}", format!("Will parse and analyze {} files.", files.len()).green()); + info!("{}", format!("Will parse and analyze {} files.", files.len()).green()); files } diff --git a/polyglot/piranha/src/main.rs b/polyglot/piranha/src/main.rs index b3ed2f903..cc4ee0658 100644 --- a/polyglot/piranha/src/main.rs +++ b/polyglot/piranha/src/main.rs @@ -17,22 +17,19 @@ use std::{fs, time::Instant}; use log::info; use polyglot_piranha::{ execute_piranha, models::piranha_arguments::PiranhaArguments, - models::piranha_output::PiranhaOutputSummary, utilities::initialize_logger, + models::piranha_output::PiranhaOutputSummary, }; fn main() { let now = Instant::now(); - initialize_logger(false); + env_logger::init(); let args = PiranhaArguments::from_command_line(); let piranha_output_summaries = execute_piranha(&args, true); if let Some(path) = args.path_to_output_summaries() { - write_output_summary( - piranha_output_summaries, - path, - ); + write_output_summary(piranha_output_summaries, path); } info!("Time elapsed - {:?}", now.elapsed().as_secs()); diff --git a/polyglot/piranha/src/models/matches.rs b/polyglot/piranha/src/models/matches.rs index c68518fc5..2b45af6a0 100644 --- a/polyglot/piranha/src/models/matches.rs +++ b/polyglot/piranha/src/models/matches.rs @@ -13,8 +13,8 @@ Copyright (c) 2022 Uber Technologies, Inc. use std::collections::HashMap; -use serde_derive::Serialize; use pyo3::prelude::pyclass; +use serde_derive::Serialize; #[derive(Serialize, Debug, Clone)] #[pyclass] diff --git a/polyglot/piranha/src/models/piranha_arguments.rs b/polyglot/piranha/src/models/piranha_arguments.rs index 4c46c8370..400fce482 100644 --- a/polyglot/piranha/src/models/piranha_arguments.rs +++ b/polyglot/piranha/src/models/piranha_arguments.rs @@ -11,12 +11,12 @@ Copyright (c) 2022 Uber Technologies, Inc. limitations under the License. */ -use std::{collections::HashMap, path::PathBuf}; -use getset::{Getters, CopyGetters}; use clap::Parser; use colored::Colorize; use derive_builder::Builder; +use getset::{CopyGetters, Getters}; use log::info; +use std::{collections::HashMap, path::PathBuf}; use tree_sitter::Language; use crate::{ @@ -61,10 +61,10 @@ pub struct PiranhaArguments { /// All source code units from this point will have access to this global tag. #[getset(get = "pub")] global_tag_prefix: String, - /// Add a user option to configure the number of ancestors considered when applying - /// parent scoped rules + /// Add a user option to configure the number of ancestors considered when applying + /// parent scoped rules #[getset(get = "pub")] - number_of_ancestors_in_parent_scope: u8 + number_of_ancestors_in_parent_scope: u8, } impl PiranhaArguments { @@ -82,11 +82,12 @@ impl PiranhaArguments { let input_substitutions = piranha_args_from_config.substitutions(); #[rustfmt::skip] - info!("{}", format!("Piranha arguments are :\n {:?}", input_substitutions).purple()); + info!("{}", format!("Piranha arguments are :\n {:?}", input_substitutions).purple()); let mut args_builder = PiranhaArgumentsBuilder::default(); - args_builder.path_to_code_base(args.path_to_codebase.to_string()) + args_builder + .path_to_code_base(args.path_to_codebase.to_string()) .input_substitutions(input_substitutions) .path_to_configurations(args.path_to_configurations) .path_to_output_summaries(args.path_to_output_summary) @@ -102,7 +103,7 @@ impl PiranhaArguments { if let Some(v) = piranha_args_from_config.global_tag_prefix() { args_builder.global_tag_prefix(v); } - return args_builder.build().unwrap(); + args_builder.build().unwrap() } } @@ -122,7 +123,7 @@ impl Default for PiranhaArguments { /// i.e. it expects global tag names to look like /// @GLOBAL_TAG.class_name global_tag_prefix: "GLOBAL_TAG.".to_string(), - number_of_ancestors_in_parent_scope: 4 + number_of_ancestors_in_parent_scope: 4, } } } diff --git a/polyglot/piranha/src/models/piranha_config.rs b/polyglot/piranha/src/models/piranha_config.rs index cfe3f6475..49e267c12 100644 --- a/polyglot/piranha/src/models/piranha_config.rs +++ b/polyglot/piranha/src/models/piranha_config.rs @@ -42,11 +42,11 @@ impl PiranhaConfiguration { self.delete_file_if_empty } - pub(crate) fn delete_consecutive_new_lines(&self) -> Option { - self.delete_consecutive_new_lines - } + pub(crate) fn delete_consecutive_new_lines(&self) -> Option { + self.delete_consecutive_new_lines + } pub(crate) fn global_tag_prefix(&self) -> Option { - self.global_tag_prefix.clone() + self.global_tag_prefix.clone() } } diff --git a/polyglot/piranha/src/models/piranha_output.rs b/polyglot/piranha/src/models/piranha_output.rs index 5e79e2d73..09f9dda7c 100644 --- a/polyglot/piranha/src/models/piranha_output.rs +++ b/polyglot/piranha/src/models/piranha_output.rs @@ -6,7 +6,6 @@ use serde_derive::Serialize; use super::{edit::Edit, matches::Match, source_code_unit::SourceCodeUnit}; use pyo3::prelude::pyclass; #[derive(Serialize, Debug, Clone, Default)] - #[pyclass] pub struct PiranhaOutputSummary { #[pyo3(get)] diff --git a/polyglot/piranha/src/models/rule.rs b/polyglot/piranha/src/models/rule.rs index 17e2c0fa3..2eb59fc2e 100644 --- a/polyglot/piranha/src/models/rule.rs +++ b/polyglot/piranha/src/models/rule.rs @@ -149,7 +149,7 @@ impl Rule { match self.groups.as_mut() { None => self.groups = Some(HashSet::from([SEED.to_string()])), Some(_groups) => { - _groups.insert(SEED.to_string()); + _groups.insert(SEED.to_string()); } } } @@ -221,7 +221,8 @@ impl Rule { source_code_unit: &SourceCodeUnit, previous_edit_start: usize, previous_edit_end: usize, rules_store: &mut RuleStore, rules: &Vec, ) -> Option { - let number_of_ancestors_in_parent_scope = rules_store.get_number_of_ancestors_in_parent_scope().clone(); + let number_of_ancestors_in_parent_scope = *rules_store + .get_number_of_ancestors_in_parent_scope(); let changed_node = get_node_for_range( source_code_unit.root_node(), previous_edit_start, @@ -233,7 +234,7 @@ impl Rule { source_code_unit.root_node(), changed_node, source_code_unit.code(), - number_of_ancestors_in_parent_scope + number_of_ancestors_in_parent_scope, ) }; for rule in rules { @@ -323,8 +324,12 @@ impl Rule { replace_node: Some(replace_node.to_string()), replace: Some(replace.to_string()), groups: None, - holes: if holes.is_empty() { None} else {Some(holes)}, - constraints: if constraints.is_empty() { None} else {Some(constraints)}, + holes: if holes.is_empty() { None } else { Some(holes) }, + constraints: if constraints.is_empty() { + None + } else { + Some(constraints) + }, grep_heuristics: None, } } diff --git a/polyglot/piranha/src/models/rule_store.rs b/polyglot/piranha/src/models/rule_store.rs index 74422e537..81cb3a291 100644 --- a/polyglot/piranha/src/models/rule_store.rs +++ b/polyglot/piranha/src/models/rule_store.rs @@ -199,7 +199,7 @@ impl RuleStore { global_rules: vec![], piranha_args: PiranhaArguments::default(), scopes, - global_tags : HashMap::new() + global_tags: HashMap::new(), } } } diff --git a/polyglot/piranha/src/models/source_code_unit.rs b/polyglot/piranha/src/models/source_code_unit.rs index 000bd7e0f..36af19760 100644 --- a/polyglot/piranha/src/models/source_code_unit.rs +++ b/polyglot/piranha/src/models/source_code_unit.rs @@ -10,9 +10,9 @@ use tree_sitter_traversal::{traverse, Order}; use crate::utilities::{eq_without_whitespace, tree_sitter_utilities::get_tree_sitter_edit}; - -use super::{edit::Edit, piranha_arguments::PiranhaArguments, matches::Match, rule_store::RuleStore}; - +use super::{ + edit::Edit, matches::Match, piranha_arguments::PiranhaArguments, rule_store::RuleStore, +}; // Maintains the updated source code content and AST of the file #[derive(Clone)] @@ -120,7 +120,6 @@ impl SourceCodeUnit { } else { None }; - println!("Replacing file contents"); // Create a new updated tree from the previous tree let new_tree = parser .parse(&replacement_content, prev_tree) @@ -202,7 +201,9 @@ impl SourceCodeUnit { &self.substitutions } - pub(crate) fn add_to_substitutions(&mut self, new_entries: &HashMap, rule_store: &mut RuleStore) { + pub(crate) fn add_to_substitutions( + &mut self, new_entries: &HashMap, rule_store: &mut RuleStore, + ) { let _ = &self.substitutions.extend(new_entries.clone()); rule_store.add_global_tags(new_entries); } diff --git a/polyglot/piranha/src/models/unit_tests/source_code_unit_test.rs b/polyglot/piranha/src/models/unit_tests/source_code_unit_test.rs index 2a78fabc4..1c2b45c9f 100644 --- a/polyglot/piranha/src/models/unit_tests/source_code_unit_test.rs +++ b/polyglot/piranha/src/models/unit_tests/source_code_unit_test.rs @@ -117,7 +117,6 @@ fn test_apply_edit_comma_handling_via_grammar() { &Edit::dummy_edit(range(37, 47, 2, 26, 2, 36), String::new()), &mut parser, ); - println!("{}", &source_code_unit.code()); assert!(eq_without_whitespace( &source_code.replace("\"NullAway\",", ""), &source_code_unit.code() @@ -144,7 +143,6 @@ fn test_apply_edit_comma_handling_via_regex() { &Edit::dummy_edit(range(59, 75, 3, 23, 3, 41), String::new()), &mut parser, ); - println!("{}", &source_code_unit.code()); assert!(eq_without_whitespace( &source_code.replace("name: \"BMX Bike\",", ""), &source_code_unit.code() @@ -171,9 +169,10 @@ fn execute_persist_in_temp_folder( #[test] fn test_persist_delete_file_when_empty() -> Result<(), io::Error> { let args = PiranhaArgumentsBuilder::default() - .delete_consecutive_new_lines(true) - .delete_file_if_empty(true) - .build().unwrap(); + .delete_consecutive_new_lines(true) + .delete_file_if_empty(true) + .build() + .unwrap(); let source_code = ""; fn check(temp_dir: &TempDir) -> Result { let paths = fs::read_dir(temp_dir)?; @@ -186,9 +185,10 @@ fn test_persist_delete_file_when_empty() -> Result<(), io::Error> { #[test] fn test_persist_do_not_delete_file_when_empty() -> Result<(), io::Error> { let args = PiranhaArgumentsBuilder::default() - .delete_consecutive_new_lines(true) - .delete_file_if_empty(false) - .build().unwrap(); + .delete_consecutive_new_lines(true) + .delete_file_if_empty(false) + .build() + .unwrap(); let source_code = ""; fn check(temp_dir: &TempDir) -> Result { let paths = fs::read_dir(temp_dir)?; @@ -202,9 +202,10 @@ fn test_persist_do_not_delete_file_when_empty() -> Result<(), io::Error> { #[test] fn test_persist_delete_consecutive_lines() -> Result<(), io::Error> { let args = PiranhaArgumentsBuilder::default() - .delete_consecutive_new_lines(true) - .delete_file_if_empty(true) - .build().unwrap(); + .delete_consecutive_new_lines(true) + .delete_file_if_empty(true) + .build() + .unwrap(); let source_code_test_1 = "class Test { public void foobar() { @@ -255,9 +256,10 @@ fn test_persist_delete_consecutive_lines() -> Result<(), io::Error> { #[test] fn test_persist_do_not_delete_consecutive_lines() -> Result<(), io::Error> { let args = PiranhaArgumentsBuilder::default() - .delete_consecutive_new_lines(false) - .delete_file_if_empty(true) - .build().unwrap(); + .delete_consecutive_new_lines(false) + .delete_file_if_empty(true) + .build() + .unwrap(); let source_code = "class Test { public void foobar() { diff --git a/polyglot/piranha/src/tests/mod.rs b/polyglot/piranha/src/tests/mod.rs index 90952a202..2e1780b0e 100644 --- a/polyglot/piranha/src/tests/mod.rs +++ b/polyglot/piranha/src/tests/mod.rs @@ -13,11 +13,13 @@ Copyright (c) 2022 Uber Technologies, Inc. use std::path::{Path, PathBuf}; +use log::error; + use crate::config::CommandLineArguments; use crate::execute_piranha; use crate::models::piranha_arguments::PiranhaArguments; use crate::models::piranha_output::PiranhaOutputSummary; -use crate::utilities::{eq_without_whitespace, find_file, initialize_logger, read_file}; +use crate::utilities::{eq_without_whitespace, find_file, read_file}; mod test_piranha_java; mod test_piranha_kt; @@ -32,7 +34,7 @@ static INIT: Once = Once::new(); fn initialize() { INIT.call_once(|| { - initialize_logger(true); + env_logger::init(); }); } @@ -99,7 +101,7 @@ fn check_result(updated_files: Vec, path_to_expected: Path if !eq_without_whitespace(source_code_unit.content(), &expected_content) { all_files_match = false; - println!("{}", &source_code_unit.content()); + error!("{}", &source_code_unit.content()); } } assert!(all_files_match); diff --git a/polyglot/piranha/src/tests/test_piranha_java.rs b/polyglot/piranha/src/tests/test_piranha_java.rs index 71e48142f..b3485803f 100644 --- a/polyglot/piranha/src/tests/test_piranha_java.rs +++ b/polyglot/piranha/src/tests/test_piranha_java.rs @@ -57,7 +57,6 @@ fn test_java_scenarios_find_and_propagate() { run_rewrite_test(&format!("{}/{}", LANGUAGE, "find_and_propagate"), 2); } - #[test] fn test_java_scenarios_user_defined_non_seed_rules() { initialize(); @@ -67,19 +66,31 @@ fn test_java_scenarios_user_defined_non_seed_rules() { #[test] fn test_java_scenarios_insert_field_and_initializer() { initialize(); - run_rewrite_test(&format!("{}/{}", LANGUAGE, "insert_field_and_initializer"), 1); + run_rewrite_test( + &format!("{}/{}", LANGUAGE, "insert_field_and_initializer"), + 1, + ); } #[test] fn test_java_scenarios_new_line_character_used_in_string_literal() { initialize(); - run_rewrite_test(&format!("{}/{}", LANGUAGE, "new_line_character_used_in_string_literal"), 1); + run_rewrite_test( + &format!( + "{}/{}", + LANGUAGE, "new_line_character_used_in_string_literal" + ), + 1, + ); } #[test] fn test_java_scenarios_consecutive_scope_level_rules() { initialize(); - run_rewrite_test(&format!("{}/{}", LANGUAGE, "consecutive_scope_level_rules"), 1); + run_rewrite_test( + &format!("{}/{}", LANGUAGE, "consecutive_scope_level_rules"), + 1, + ); } // run_match_test diff --git a/polyglot/piranha/src/tests/test_piranha_swift.rs b/polyglot/piranha/src/tests/test_piranha_swift.rs index d546c37f8..5c6c10b19 100644 --- a/polyglot/piranha/src/tests/test_piranha_swift.rs +++ b/polyglot/piranha/src/tests/test_piranha_swift.rs @@ -15,21 +15,23 @@ use super::{initialize, run_rewrite_test}; static LANGUAGE: &str = "swift"; -// Tests cascading file delete based on enum and type alias. +// Tests cascading file delete based on enum and type alias. // This scenario is "derived" from plugin cleanup. // This cleanup requires the concept of global tags #[test] fn test_cascading_delete_file() { initialize(); - run_rewrite_test(&format!("{}/{}",LANGUAGE, "cascade_file_delete"), 3); + run_rewrite_test(&format!("{}/{}", LANGUAGE, "cascade_file_delete"), 3); } - -// Tests cascading file delete based on enum and type alias. +// Tests cascading file delete based on enum and type alias. // This scenario is "derived" from plugin cleanup. // Checks custom global_tags #[test] fn test_cascading_delete_file_custom_global_tag() { initialize(); - run_rewrite_test(&format!("{}/{}",LANGUAGE, "cascade_file_delete_custom_global_tag"), 3); + run_rewrite_test( + &format!("{}/{}", LANGUAGE, "cascade_file_delete_custom_global_tag"), + 3, + ); } diff --git a/polyglot/piranha/src/utilities/mod.rs b/polyglot/piranha/src/utilities/mod.rs index d3287c184..a9c87af4f 100644 --- a/polyglot/piranha/src/utilities/mod.rs +++ b/polyglot/piranha/src/utilities/mod.rs @@ -12,11 +12,10 @@ Copyright (c) 2022 Uber Technologies, Inc. */ pub(crate) mod tree_sitter_utilities; - use std::collections::HashMap; +use std::fs::File; #[cfg(test)] use std::fs::{self, DirEntry}; -use std::fs::{File, OpenOptions}; use std::hash::Hash; use std::io::{BufReader, Read}; use std::path::PathBuf; @@ -65,21 +64,6 @@ impl MapOfVec for HashMap> { } } -/// Initialize logger. -pub fn initialize_logger(is_test: bool) { - let log_file = OpenOptions::new() - .write(true) - .create(true) // Create a log file if it doesn't exists - .append(true) // Append to the log file if it exists - .open("piranha.log") - .unwrap(); - let _ = env_logger::builder() - .format_timestamp(None) - .target(env_logger::Target::Pipe(Box::new(log_file))) - .is_test(is_test) - .try_init(); -} - /// Compares two strings, ignoring whitespace pub(crate) fn eq_without_whitespace(s1: &str, s2: &str) -> bool { s1.split_whitespace() diff --git a/polyglot/piranha/src/utilities/tree_sitter_utilities.rs b/polyglot/piranha/src/utilities/tree_sitter_utilities.rs index 041d24fca..ea1eb74f3 100644 --- a/polyglot/piranha/src/utilities/tree_sitter_utilities.rs +++ b/polyglot/piranha/src/utilities/tree_sitter_utilities.rs @@ -268,17 +268,22 @@ pub(crate) fn get_tree_sitter_edit( #[rustfmt::skip] info!("\n {} at ({:?}) -\n {}", edit_kind , &replace_range, replacement_snippet_fmt); // Create the new source code content by appropriately - // replacing the range with the replacement string. - let new_source_code = [ - &code[..replace_range.start_byte], - replacement, - &code[replace_range.end_byte..], - ] - .concat(); + // replacing the range with the replacement string. + let new_source_code = [ + &code[..replace_range.start_byte], + replacement, + &code[replace_range.end_byte..], + ] + .concat(); ( new_source_code.to_string(), // Tree-sitter edit - _get_tree_sitter_edit(replace_range, replacement.as_bytes().len(), code.as_bytes(), &new_source_code.as_bytes()), + _get_tree_sitter_edit( + replace_range, + replacement.as_bytes().len(), + code.as_bytes(), + new_source_code.as_bytes(), + ), ) } @@ -314,17 +319,17 @@ fn _get_tree_sitter_edit( } } -/// Replaces the all the occurrences of a specific tag with the corresponding string values -/// specified in `substitutions`, and returns this new string. -/// -/// # Arguments -/// -/// * `input_string` : the string to be transformed -/// * `substitutions` : a map between tree-sitter tag and the replacement string -/// * `is_tree_sitter_query` : true if the `input_string` is a tree-sitter query, false if it is a +/// Replaces the all the occurrences of a specific tag with the corresponding string values +/// specified in `substitutions`, and returns this new string. +/// +/// # Arguments +/// +/// * `input_string` : the string to be transformed +/// * `substitutions` : a map between tree-sitter tag and the replacement string +/// * `is_tree_sitter_query` : true if the `input_string` is a tree-sitter query, false if it is a /// replacement pattern. -/// -/// Note that, it escapes newline characters for tree-sitter-queries. +/// +/// Note that, it escapes newline characters for tree-sitter-queries. pub(crate) fn substitute_tags( input_string: String, substitutions: &HashMap, is_tree_sitter_query: bool, ) -> String { diff --git a/polyglot/piranha/src/utilities/unit_tests/tree_sitter_utilities_test.rs b/polyglot/piranha/src/utilities/unit_tests/tree_sitter_utilities_test.rs index fb13df276..54b8050ea 100644 --- a/polyglot/piranha/src/utilities/unit_tests/tree_sitter_utilities_test.rs +++ b/polyglot/piranha/src/utilities/unit_tests/tree_sitter_utilities_test.rs @@ -1,4 +1,7 @@ -use std::{collections::{HashMap, HashSet}, path::PathBuf}; +use std::{ + collections::{HashMap, HashSet}, + path::PathBuf, +}; use tree_sitter::Query; @@ -244,7 +247,11 @@ fn test_substitute_tags() { ("init".to_string(), "true".to_string()), ]); assert_eq!( - substitute_tags("@variable_name foo bar @init".to_string(), &substitutions, false), + substitute_tags( + "@variable_name foo bar @init".to_string(), + &substitutions, + false + ), "isFlagTreated foo bar true" ) }