diff --git a/formatter/src/code_builder.rs b/formatter/src/code_builder.rs index 0e8b61cc8c8..1f5b5963eac 100644 --- a/formatter/src/code_builder.rs +++ b/formatter/src/code_builder.rs @@ -45,7 +45,8 @@ impl CodeBuilder { pub fn format_and_add(&mut self, line: &str) { let mut code_line = self.get_unfinished_code_line_or_new(); - let is_string_or_multiline_comment = code_line.is_string || code_line.is_multiline_comment; + let is_string_or_multiline_comment = + code_line.is_string() || code_line.is_multiline_comment(); let line = if !is_string_or_multiline_comment { line.trim() @@ -64,15 +65,21 @@ impl CodeBuilder { code_line.push_char('\n'); } + if code_line.is_multiline_comment() && line.trim() == "*/" { + code_line.push_str(&self.get_indentation()); + code_line.push_str("*/"); + return self.complete_and_add_line(code_line); + } + let mut iter = line.chars().enumerate().peekable(); loop { if let Some((current_index, current_char)) = iter.next() { - if code_line.is_string { + if code_line.is_string() { handle_string_case(&mut code_line, current_char); - } else if code_line.is_multiline_comment { + } else if code_line.is_multiline_comment() { handle_multiline_comment_case(&mut code_line, current_char, &mut iter); - if !code_line.is_multiline_comment { + if !code_line.is_multiline_comment() { self.complete_and_add_line(code_line); return self.move_rest_to_new_line(line, iter); } @@ -111,8 +118,8 @@ impl CodeBuilder { // handle beginning of the string '"' => { - if !code_line.is_string { - code_line.push_char(current_char); + if !code_line.is_string() { + code_line.append_with_whitespace("\""); code_line.become_string(); } } @@ -132,7 +139,19 @@ impl CodeBuilder { '}' => return self.handle_close_brace(line, code_line, iter), // add the rest - _ => code_line.push_char(current_char), + _ => { + // handle case when keywords are on different lines + if current_index == 0 { + // if there are 2 keywords on different lines - add whitespace between them + if let Some(last_char) = code_line.text.chars().last() { + if last_char.is_alphabetic() && current_char.is_alphabetic() { + code_line.append_whitespace() + } + } + } + + code_line.push_char(current_char) + } } } } else { diff --git a/formatter/src/code_line.rs b/formatter/src/code_line.rs index e0ea76eabe6..97052af4bdb 100644 --- a/formatter/src/code_line.rs +++ b/formatter/src/code_line.rs @@ -1,43 +1,59 @@ #[derive(Debug)] pub struct CodeLine { pub text: String, - pub is_string: bool, pub is_completed: bool, - pub is_multiline_comment: bool, pub was_previously_stored: bool, + code_type: CodeType, } impl CodeLine { pub fn new(text: String) -> Self { Self { text, - is_string: false, is_completed: false, - is_multiline_comment: false, was_previously_stored: false, + code_type: CodeType::Default, } } pub fn default() -> Self { Self { text: "".into(), - is_string: false, is_completed: false, - is_multiline_comment: false, was_previously_stored: false, + code_type: CodeType::Default, } } pub fn empty_line() -> Self { Self { text: "".into(), - is_string: false, is_completed: true, - is_multiline_comment: false, was_previously_stored: false, + code_type: CodeType::Default, } } + pub fn is_string(&self) -> bool { + self.code_type == CodeType::String + } + + pub fn is_multiline_comment(&self) -> bool { + self.code_type == CodeType::MultilineComment + } + + pub fn become_multiline_comment(&mut self) { + self.code_type = CodeType::MultilineComment; + } + + pub fn end_multiline_comment(&mut self) { + self.code_type = CodeType::Default; + } + + pub fn end_string(&mut self) { + self.code_type = CodeType::Default; + } + pub fn push_str(&mut self, line: &str) { self.text.push_str(line); } @@ -51,19 +67,7 @@ impl CodeLine { } pub fn become_string(&mut self) { - self.is_string = true; - } - - pub fn become_multiline_comment(&mut self) { - self.is_multiline_comment = true; - } - - pub fn end_multiline_comment(&mut self) { - self.is_multiline_comment = false; - } - - pub fn end_string(&mut self) { - self.is_string = false; + self.code_type = CodeType::String } pub fn update_for_storage(&mut self, indentation: String) { @@ -75,7 +79,7 @@ impl CodeLine { let last = self.text.chars().last(); let is_previous_whitespace = Some(' ') == last; - if !is_previous_whitespace { + if !is_previous_whitespace && last != None { self.push_char(' '); } @@ -105,3 +109,10 @@ impl CodeLine { self.text.is_empty() } } + +#[derive(Debug, PartialEq)] +enum CodeType { + Default, + String, + MultilineComment, +} diff --git a/formatter/src/formatter.rs b/formatter/src/formatter.rs index 5ec3456cb29..d415bbf5778 100644 --- a/formatter/src/formatter.rs +++ b/formatter/src/formatter.rs @@ -12,3 +12,216 @@ pub fn get_formatted_data(file: &str, tab_size: u32) -> (usize, String) { code_builder.get_final_edits() } + +#[cfg(test)] +mod tests { + use super::get_formatted_data; + + #[test] + fn test_indentation() { + let correct_sway_code = r#"script; + +fn main() { + // this is a comment + let o = 123; + + let p = { + /* this is some + multi line stuff t + + */ + 123; + + }; + + add(1, 2); +} + +pub fn add(a: u32, b: u32) -> u32 { + a + b +} +"#; + let (_, result) = get_formatted_data(correct_sway_code, 4); + assert_eq!(correct_sway_code, result); + + let sway_code = r#"script; + +fn main() { + // this is a comment + let o = 123; + + let +p + + + = + + + { + /* this is some + multi line stuff t + + */ + 123 + + + ; + + + }; + + add( 1, + + 2 + + + ) ; +} + +pub +fn +add + ( + a:u32 , + b: u32) ->u32{ + a +b} + +"#; + + let (_, result) = get_formatted_data(sway_code, 4); + assert_eq!(correct_sway_code, result); + } + + #[test] + fn test_multiline_string() { + let correct_sway_code = r#"script; + +fn main() { + let multiline_string = " sadsa + sadsad + sadasd sadsdsa + sadasd + sadasd sadasd + "; +} +"#; + + let (_, result) = get_formatted_data(correct_sway_code, 4); + assert_eq!(correct_sway_code, result); + + let sway_code = r#"script; + +fn main(){ + let multiline_string=" sadsa + sadsad + sadasd sadsdsa + sadasd + sadasd sadasd + " + ; +} +"#; + + let (_, result) = get_formatted_data(sway_code, 4); + assert_eq!(correct_sway_code, result); + } + + #[test] + fn test_whitespace_handling() { + let correct_sway_code = r#"script; + +fn main() { + let word = "word"; + let num = 12; + + let multi = { + let k = 12; + k + }; +} +"#; + + let (_, result) = get_formatted_data(correct_sway_code, 4); + assert_eq!(correct_sway_code, result); + + let sway_code = r#"script; + +fn main() { + let word="word"; + let num= 12 ; + + let multi = { + let k = 12; + k + } + + + ; +} +"#; + + let (_, result) = get_formatted_data(sway_code, 4); + assert_eq!(correct_sway_code, result); + } + + #[test] + fn test_comments() { + let correct_sway_code = r#"script; + +fn main() { + // this is a comment + let o = 123; // this is an inline comment + /* + asdasd + asdasdsad asdasdasd */ + + /* multiline closed on the same line */ + let p = { + /* this is some + multi line stuff t + + */ + 123; + }; // comment here as well +} // comment here too + +// example struct with comments +struct Example { // first comment + prop: bool, // second comment + age: u32 // another comment +} // comment as well +"#; + + let (_, result) = get_formatted_data(correct_sway_code, 4); + assert_eq!(correct_sway_code, result); + + let sway_code = r#"script; + +fn main() { + // this is a comment + let o = 123; // this is an inline comment + /* + asdasd + asdasdsad asdasdasd */ + + /* multiline closed on the same line */ + let p = { + /* this is some + multi line stuff t + + */ + 123; + }; // comment here as well +} // comment here too + + // example struct with comments +struct Example { // first comment + prop: bool,// second comment + age: u32// another comment +} // comment as well +"#; + + let (_, result) = get_formatted_data(sway_code, 4); + assert_eq!(correct_sway_code, result); + } +} diff --git a/formatter/src/parse_helpers.rs b/formatter/src/parse_helpers.rs index 3db065ab4bc..ba1c8067f11 100644 --- a/formatter/src/parse_helpers.rs +++ b/formatter/src/parse_helpers.rs @@ -45,7 +45,7 @@ pub fn handle_whitespace_case(code_line: &mut CodeLine, iter: &mut Peekable {} // do nothing, handle it in next turn + '(' | ';' | ':' | ')' | ',' => {} // do nothing, handle it in next turn _ => { // add whitespace if it is not already there code_line.append_whitespace();