diff --git a/Cargo.toml b/Cargo.toml index 4c30246..8a5991a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "darklua" -version = "0.2.1" +version = "0.2.2" authors = ["jeparlefrancais "] edition = "2018" readme = "README.md" diff --git a/RULES.md b/RULES.md index 6283a1b..9d383f6 100644 --- a/RULES.md +++ b/RULES.md @@ -3,6 +3,7 @@ You can find the available rules and their properties here. The default rule stack is: - [Remove empty do statements](#remove-empty-do-statements) + - [Remove method definitions](#remove-method-definitions) - [Rename variables](#rename-variables) --- @@ -21,6 +22,38 @@ This rule does not have any properties. --- +## Remove method definitions +```remove_method_definition``` + +Functions defined using the method syntax (with a `:`) will be replaced with their field like syntax. So the following Lua code: + +```lua +local Car = {} + +function Car:move(distance) + self.position = self.position + distance +end +``` + +Will produce the following code: + +```lua +local Car = {} + +function Car.move(self, distance) + self.position = self.position + distance +end +``` + +### Examples +```json5 +{ + rule: 'remove_method_definition', +} +``` + +--- + ## Rename variables ```rename_variables``` diff --git a/src/nodes/statements/function.rs b/src/nodes/statements/function.rs index bc37096..5365fc7 100644 --- a/src/nodes/statements/function.rs +++ b/src/nodes/statements/function.rs @@ -30,8 +30,8 @@ impl FunctionName { self } - pub fn with_method(mut self, method: String) -> Self { - self.method.replace(method); + pub fn with_method>(mut self, method: S) -> Self { + self.method.replace(method.into()); self } @@ -168,10 +168,29 @@ mod test { use super::*; #[test] - fn generate_() { + fn generate_empty_function() { let output = FunctionStatement::from_name("foo", Block::default()) .to_lua_string(); assert_eq!(output, "function foo()end"); } + + #[test] + fn generate_empty_function_with_field() { + let function_name = FunctionName::from_name("foo") + .with_fields(vec!["bar".to_owned()]); + let output = FunctionStatement::new(function_name, Block::default(), Vec::new(), false) + .to_lua_string(); + + assert_eq!(output, "function foo.bar()end"); + } + + #[test] + fn generate_empty_function_with_method() { + let function_name = FunctionName::from_name("foo").with_method("bar"); + let output = FunctionStatement::new(function_name, Block::default(), Vec::new(), false) + .to_lua_string(); + + assert_eq!(output, "function foo:bar()end"); + } } diff --git a/src/rules/method_def.rs b/src/rules/method_def.rs new file mode 100644 index 0000000..12ef625 --- /dev/null +++ b/src/rules/method_def.rs @@ -0,0 +1,61 @@ +use crate::nodes::{Block, FunctionStatement}; +use crate::process::{DefaultVisitor, NodeProcessor, NodeVisitor}; +use crate::rules::{Rule, RuleConfigurationError, RuleProperties}; + +#[derive(Default)] +struct FunctionMutator; + +impl NodeProcessor for FunctionMutator { + fn process_function_statement(&mut self, function: &mut FunctionStatement) { + function.remove_method(); + } +} + +pub const REMOVE_METHOD_DEFINITION_RULE_NAME: &'static str = "remove_method_definition"; + +/// Change method functions into regular functions. +#[derive(Debug, Default, PartialEq, Eq)] +pub struct RemoveMethodDefinition {} + +impl Rule for RemoveMethodDefinition { + fn process(&self, block: &mut Block) { + let mut processor = FunctionMutator::default(); + DefaultVisitor::visit_block(block, &mut processor); + } + + fn configure(&mut self, properties: RuleProperties) -> Result<(), RuleConfigurationError> { + for (key, _value) in properties { + return Err(RuleConfigurationError::UnexpectedProperty(key)) + } + + Ok(()) + } + + fn get_name(&self) -> &'static str { + REMOVE_METHOD_DEFINITION_RULE_NAME + } + + fn serialize_to_properties(&self) -> RuleProperties { + RuleProperties::new() + } +} + +#[cfg(test)] +mod test { + use super::*; + + use insta::assert_json_snapshot; + + fn new_rule() -> RemoveMethodDefinition { + RemoveMethodDefinition::default() + } + + fn wrap(rule: RemoveMethodDefinition) -> Box { + Box::new(rule) + } + + #[test] + fn serialize_default_rule() { + assert_json_snapshot!("default_remove_method_definition", wrap(new_rule())); + } +} diff --git a/src/rules/mod.rs b/src/rules/mod.rs index a07d1bc..4773842 100644 --- a/src/rules/mod.rs +++ b/src/rules/mod.rs @@ -1,9 +1,11 @@ //! A module that contains the different rules that mutates a Lua block. mod empty_do; +mod method_def; mod rename_variables; pub use empty_do::*; +pub use method_def::*; pub use rename_variables::*; use crate::nodes::Block; @@ -75,6 +77,7 @@ pub trait Rule { pub fn get_default_rules() -> Vec> { vec![ Box::new(RemoveEmptyDo::default()), + Box::new(RemoveMethodDefinition::default()), Box::new(RenameVariables::default()), ] } @@ -85,6 +88,7 @@ impl FromStr for Box { fn from_str(string: &str) -> Result { let rule: Box = match string { REMOVE_EMPTY_DO_RULE_NAME => Box::new(RemoveEmptyDo::default()), + REMOVE_METHOD_DEFINITION_RULE_NAME => Box::new(RemoveMethodDefinition::default()), RENAME_VARIABLES_RULE_NAME => Box::new(RenameVariables::default()), _ => return Err(format!("invalid rule name: {}", string)), }; diff --git a/src/rules/snapshots/test__default_remove_method_definition.snap b/src/rules/snapshots/test__default_remove_method_definition.snap new file mode 100644 index 0000000..2aa8872 --- /dev/null +++ b/src/rules/snapshots/test__default_remove_method_definition.snap @@ -0,0 +1,5 @@ +--- +source: src/rules/method_def.rs +expression: new_rule() +--- +"remove_method_definition" diff --git a/src/rules/snapshots/test__default_rules.snap b/src/rules/snapshots/test__default_rules.snap index 590d433..67ca888 100644 --- a/src/rules/snapshots/test__default_rules.snap +++ b/src/rules/snapshots/test__default_rules.snap @@ -4,5 +4,6 @@ expression: rules --- [ "remove_empty_do", + "remove_method_definition", "rename_variables" ] diff --git a/tests/rule_tests/mod.rs b/tests/rule_tests/mod.rs index b854e90..14bfbb2 100644 --- a/tests/rule_tests/mod.rs +++ b/tests/rule_tests/mod.rs @@ -17,4 +17,5 @@ macro_rules! test_rule { } mod remove_empty_do; +mod remove_method_definition; mod rename_variables; diff --git a/tests/rule_tests/remove_method_definition.rs b/tests/rule_tests/remove_method_definition.rs new file mode 100644 index 0000000..e2dd542 --- /dev/null +++ b/tests/rule_tests/remove_method_definition.rs @@ -0,0 +1,11 @@ +use darklua_core::rules::RemoveMethodDefinition; + +test_rule!( + RemoveMethodDefinition::default(), + name_without_method("function foo() end") => "function foo() end", + name_with_method("function foo:bar() end") => "function foo.bar(self) end", + name_with_field_and_method("function foo.bar:baz() end") => "function foo.bar.baz(self) end", + with_arguments("function foo:bar(a, b, c) end") => "function foo.bar(self, a, b, c) end", + variadic_function("function foo:bar(...) end") => "function foo.bar(self, ...) end", + variadic_with_arguments("function foo:bar(a, b, c, ...) end") => "function foo.bar(self, a, b, c, ...) end" +);