Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiline comments #90

Merged
merged 13 commits into from
Jun 22, 2021
Merged
59 changes: 46 additions & 13 deletions formatter/src/code_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ use std::{
str::Chars,
};

use super::parse_helpers::{clean_all_incoming_whitespace, is_comment};
use super::{
code_line::CodeLine,
parse_helpers::{
handle_ampersand_case, handle_assignment_case, handle_colon_case, handle_dash_case,
handle_pipe_case, handle_string_case, handle_whitespace_case,
clean_all_incoming_whitespace, handle_ampersand_case, handle_assignment_case,
handle_colon_case, handle_dash_case, handle_multiline_comment_case, handle_pipe_case,
handle_string_case, handle_whitespace_case, is_comment,
},
};

Expand Down Expand Up @@ -45,7 +45,9 @@ impl CodeBuilder {
pub fn format_and_add(&mut self, line: &str) {
let mut code_line = self.get_unfinished_code_line_or_new();

let line = if !code_line.is_string {
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()
} else {
line
Expand All @@ -57,17 +59,23 @@ impl CodeBuilder {
return self.complete_and_add_line(code_line);
}

// handle multiline string
if code_line.is_string {
// add newline if it's multiline string or comment
if is_string_or_multiline_comment {
code_line.push_char('\n');
}

let mut iter = line.chars().enumerate().peekable();

loop {
if let Some((_, current_char)) = iter.next() {
if let Some((current_index, current_char)) = iter.next() {
if code_line.is_string {
handle_string_case(&mut code_line, current_char);
} else if code_line.is_multiline_comment {
handle_multiline_comment_case(&mut code_line, current_char, &mut iter);
if !code_line.is_multiline_comment {
self.complete_and_add_line(code_line);
return self.move_rest_to_new_line(line, iter);
}
} else {
match current_char {
' ' => handle_whitespace_case(&mut code_line, &mut iter),
Expand All @@ -80,7 +88,23 @@ impl CodeBuilder {
',' => code_line.push_str(", "),
'+' => code_line.append_with_whitespace("+ "),
'*' => code_line.append_with_whitespace("* "),
'/' => code_line.append_with_whitespace("- "),
'/' => {
match iter.peek() {
Some((_, '*')) => {
// it's a multiline comment
code_line.become_multiline_comment();
iter.next();
code_line.push_str("/*");
}
Some((_, '/')) => {
// it's a comment
let comment = &line[current_index..];
code_line.push_str(&comment);
return self.complete_and_add_line(code_line);
}
_ => code_line.append_with_whitespace("/ "),
}
}
'%' => code_line.append_with_whitespace("% "),
'^' => code_line.append_with_whitespace("^ "),
'!' => code_line.append_with_whitespace("!"),
Expand Down Expand Up @@ -155,7 +179,7 @@ impl CodeBuilder {
// case when '}' was separated from ';' by one or more new lines
if previous_code_line.is_completed {
// remove empty line first
if !(previous_code_line.text.chars().last().unwrap_or(' ') == '}') {
if !(previous_code_line.text.chars().last() == Some('}')) {
self.edits.pop();
}

Expand Down Expand Up @@ -196,6 +220,7 @@ impl CodeBuilder {
}
// if there is more - move to new line!
Some(_) => {
self.complete_and_add_line(CodeLine::new("}".into()));
self.move_rest_to_new_line(line, iter);
}
None => {
Expand All @@ -207,11 +232,19 @@ impl CodeBuilder {
fn move_rest_to_new_line(&mut self, line: &str, iter: Peekable<Enumerate<Chars>>) {
let mut iter = iter;

if iter.peek().is_some() {
let (next_index, _) = iter.peek().unwrap();
if let Some((next_index, _)) = iter.peek() {
let next_line = &line[*next_index..].trim();

let next_line = &line[*next_index..];
self.format_and_add(next_line);
// if rest is comment append it to the last existing line
if is_comment(&next_line) {
if let Some(mut code_line) = self.edits.pop() {
code_line.push_char(' ');
code_line.push_str(next_line);
self.add_line(code_line);
}
} else {
self.format_and_add(next_line);
}
}
}

Expand Down
37 changes: 32 additions & 5 deletions formatter/src/code_line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub struct CodeLine {
pub text: String,
pub is_string: bool,
pub is_completed: bool,
pub is_multiline_comment: bool,
pub was_previously_stored: bool,
}

Expand All @@ -12,6 +13,7 @@ impl CodeLine {
text,
is_string: false,
is_completed: false,
is_multiline_comment: false,
was_previously_stored: false,
}
}
Expand All @@ -21,6 +23,7 @@ impl CodeLine {
text: "".into(),
is_string: false,
is_completed: false,
is_multiline_comment: false,
was_previously_stored: false,
}
}
Expand All @@ -30,6 +33,7 @@ impl CodeLine {
text: "".into(),
is_string: false,
is_completed: true,
is_multiline_comment: false,
was_previously_stored: false,
}
}
Expand All @@ -50,6 +54,14 @@ impl CodeLine {
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;
}
Expand All @@ -61,11 +73,7 @@ impl CodeLine {

pub fn append_with_whitespace(&mut self, value: &str) {
let last = self.text.chars().last();
let is_previous_whitespace = if last.is_none() {
true
} else {
last.unwrap() == ' '
};
let is_previous_whitespace = Some(' ') == last;

if !is_previous_whitespace {
self.push_char(' ');
Expand All @@ -74,6 +82,25 @@ impl CodeLine {
self.push_str(value);
}

pub fn append_equal_sign(&mut self) {
let last = self.text.chars().last();

if Some('!') == last {
self.push_char('=');
} else {
self.append_with_whitespace("=");
}
}

pub fn append_whitespace(&mut self) {
let last = self.text.chars().last();

match last {
Some('(') => {} // do not add whitespace,
_ => self.append_with_whitespace(""),
}
}

pub fn is_empty(&self) -> bool {
self.text.is_empty()
}
Expand Down
27 changes: 21 additions & 6 deletions formatter/src/parse_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,29 @@ pub fn is_comment(line: &str) -> bool {
chars.next() == Some('/') && chars.next() == Some('/')
}

pub fn handle_multiline_comment_case(
code_line: &mut CodeLine,
current_char: char,
iter: &mut Peekable<Enumerate<Chars>>,
) {
code_line.push_char(current_char);

if current_char == '*' {
// end multiline
if let Some((_, '/')) = iter.peek() {
code_line.push_char('/');
iter.next();
code_line.end_multiline_comment();
}
}
}
// if it's a string just keep pushing the characters
pub fn handle_string_case(code_line: &mut CodeLine, current_char: char) {
code_line.push_char(current_char);
if current_char == '"' {
let previous_char = code_line.text.chars().last().unwrap_or(' ');
let previous_char = code_line.text.chars().last();
// end of the string
if previous_char != '\\' {
if previous_char != Some('\\') {
code_line.end_string();
}
}
Expand All @@ -29,10 +45,10 @@ pub fn handle_whitespace_case(code_line: &mut CodeLine, iter: &mut Peekable<Enum
let next_char = *next_char;

match next_char {
'(' | ';' | ':' => {} // 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_with_whitespace("");
code_line.append_whitespace();
}
}
}
Expand All @@ -50,8 +66,7 @@ pub fn handle_assignment_case(code_line: &mut CodeLine, iter: &mut Peekable<Enum
code_line.append_with_whitespace("=> ");
iter.next();
} else {
// it's assignment
code_line.append_with_whitespace("= ");
code_line.append_equal_sign();
}
} else {
code_line.append_with_whitespace("= ");
Expand Down