Skip to content

Commit

Permalink
Fix display for nodes (#1312)
Browse files Browse the repository at this point in the history
* Fixed top level indents

* Fixed function definitions

* For loops display correctly now

* Await expressions display correctly

* Await calls no longer have a custom display() function

* Fixed async function declaration

* Added spacing to do-while loop

* Fixed for of loop

* Fixed object declaration formatter

* Fixed switch statements formatting

* Added operator fmt test

* Added array display test

* Added tests for await expressions. Unclear if let a = await blah() has been implemented yet, but I got parse errors when testing that

* Added block display test

* Added break formatting test

* Added a potential test for when block labels are added

* Added call formatting tests

* Added a testing utility function for formatting tests

* Using custom testing function instead of a bunch of asserts in formatting tests

* Improved formatting of failed parsing formatting tests

* Added conditional formatting tests

* Wrote function tests, and found out that functions are still horribly broken

* Fixed arrow function declaration

* Fixed the formatting for the rest of the functions. Async function expressions don't seem to be parsed correctly

* Re-ordered functions to match the output of StatementList

* Fixed async function expressions

* Added field formatting tests

* Added formatting test for 'for' loops

* For in loops now display their label if they have one

* Added test for the rest of the loops

* Added fmt for labels for all the types of loops

* Added test for new keyword formatting

* Added object formatting

* Partially fixed object display function

* Split Node::display into two functions, allowing objects to be displayed correctly

* Added a first implementation of a MethodDefinition formatter

* Added tests for the rest of object function fields (every branch of MethodDefinitionField)

* Operator test uses propper formatting test

* Added return statment formatter test

* Added spread argument formatting test

* Added switch statement formatting test

* Added a formatting test for templates

* Added a throw statement formatter test

* Added try catch test

* Removed unused import

* Formatting test now uses eprintln! instead of println!
  • Loading branch information
macmv authored Jun 18, 2021
1 parent 75a361b commit 057cbb1
Show file tree
Hide file tree
Showing 42 changed files with 581 additions and 80 deletions.
3 changes: 3 additions & 0 deletions boa/src/syntax/ast/node/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ use std::fmt;
#[cfg(feature = "deser")]
use serde::{Deserialize, Serialize};

#[cfg(test)]
mod tests;

/// An array is an ordered collection of data (either primitive or object depending upon the
/// language).
///
Expand Down
9 changes: 9 additions & 0 deletions boa/src/syntax/ast/node/array/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#[test]
fn fmt() {
super::super::test_formatting(
r#"
let a = [1, 2, 3, "words", "more words"];
let b = [];
"#,
);
}
14 changes: 5 additions & 9 deletions boa/src/syntax/ast/node/await_expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ use std::fmt;
#[cfg(feature = "deser")]
use serde::{Deserialize, Serialize};

#[cfg(test)]
mod tests;

/// An await expression is used within an async function to pause execution and wait for a
/// promise to resolve.
///
Expand All @@ -31,14 +34,6 @@ impl Executable for AwaitExpr {
}
}

impl AwaitExpr {
/// Implements the display formatting with indentation.
pub(super) fn display(&self, f: &mut fmt::Formatter<'_>, indentation: usize) -> fmt::Result {
writeln!(f, "await ")?;
self.expr.display(f, indentation)
}
}

impl<T> From<T> for AwaitExpr
where
T: Into<Box<Node>>,
Expand All @@ -50,7 +45,8 @@ where

impl fmt::Display for AwaitExpr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.display(f, 0)
write!(f, "await ")?;
self.expr.display(f, 0)
}
}

Expand Down
9 changes: 9 additions & 0 deletions boa/src/syntax/ast/node/await_expr/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#[test]
fn fmt() {
// TODO: `let a = await fn()` is invalid syntax as of writing. It should be tested here once implemented.
super::super::test_formatting(
r#"
await function_call();
"#,
);
}
3 changes: 3 additions & 0 deletions boa/src/syntax/ast/node/block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ use std::fmt;
#[cfg(feature = "deser")]
use serde::{Deserialize, Serialize};

#[cfg(test)]
mod tests;

/// A `block` statement (or compound statement in other languages) is used to group zero or
/// more statements.
///
Expand Down
22 changes: 22 additions & 0 deletions boa/src/syntax/ast/node/block/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#[test]
fn fmt() {
super::super::test_formatting(
r#"
{
let a = function_call();
console.log("hello");
}
another_statement();
"#,
);
// TODO: Once block labels are implemtned, this should be tested:
// super::super::test_formatting(
// r#"
// block_name: {
// let a = function_call();
// console.log("hello");
// }
// another_statement();
// "#,
// );
}
31 changes: 31 additions & 0 deletions boa/src/syntax/ast/node/break_node/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,34 @@ fn check_post_state() {
&InterpreterState::Break(Some("label".into()))
);
}

#[test]
fn fmt() {
// Blocks do not store their label, so we cannot test with
// the outer block having a label.
//
// TODO: Once block labels are implemented, this test should
// include them:
//
// ```
// outer: {
// while (true) {
// break outer;
// }
// skipped_call();
// }
// ```
super::super::test_formatting(
r#"
{
while (true) {
break outer;
}
skipped_call();
}
while (true) {
break;
}
"#,
);
}
3 changes: 3 additions & 0 deletions boa/src/syntax/ast/node/call/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ use std::fmt;
#[cfg(feature = "deser")]
use serde::{Deserialize, Serialize};

#[cfg(test)]
mod tests;

/// Calling the function actually performs the specified actions with the indicated parameters.
///
/// Defining a function does not execute it. Defining it simply names the function and
Expand Down
10 changes: 10 additions & 0 deletions boa/src/syntax/ast/node/call/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#[test]
fn fmt() {
super::super::test_formatting(
r#"
call_1(1, 2, 3);
call_2("argument here");
call_3();
"#,
);
}
3 changes: 3 additions & 0 deletions boa/src/syntax/ast/node/conditional/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ pub mod conditional_op;
pub mod if_node;

pub use self::{conditional_op::ConditionalOp, if_node::If};

#[cfg(test)]
mod tests;
13 changes: 13 additions & 0 deletions boa/src/syntax/ast/node/conditional/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#[test]
fn fmt() {
super::super::test_formatting(
r#"
let a = true ? 5 : 6;
if (false) {
a = 10;
} else {
a = 20;
}
"#,
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,13 @@ impl ArrowFunctionDecl {
) -> fmt::Result {
write!(f, "(")?;
join_nodes(f, &self.params)?;
f.write_str(") => ")?;
self.body.display(f, indentation)
if self.body().is_empty() {
f.write_str(") => {}")
} else {
f.write_str(") => {\n")?;
self.body.display(f, indentation + 1)?;
write!(f, "{}}}", " ".repeat(indentation))
}
}
}

Expand Down
20 changes: 9 additions & 11 deletions boa/src/syntax/ast/node/declaration/async_function_decl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,17 @@ impl AsyncFunctionDecl {
indentation: usize,
) -> fmt::Result {
match &self.name {
Some(name) => {
write!(f, "async function {}(", name)?;
}
None => {
write!(f, "async function (")?;
}
Some(name) => write!(f, "async function {}(", name)?,
None => write!(f, "async function (")?,
}
join_nodes(f, &self.parameters)?;
f.write_str(") {{")?;

self.body.display(f, indentation + 1)?;

writeln!(f, "}}")
if self.body().is_empty() {
f.write_str(") {}")
} else {
f.write_str(") {\n")?;
self.body.display(f, indentation + 1)?;
write!(f, "{}}}", " ".repeat(indentation))
}
}
}

Expand Down
14 changes: 8 additions & 6 deletions boa/src/syntax/ast/node/declaration/async_function_expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,19 @@ impl AsyncFunctionExpr {
f: &mut fmt::Formatter<'_>,
indentation: usize,
) -> fmt::Result {
f.write_str("function")?;
f.write_str("async function")?;
if let Some(ref name) = self.name {
write!(f, " {}", name)?;
}
f.write_str("(")?;
join_nodes(f, &self.parameters)?;
f.write_str(") {{")?;

self.body.display(f, indentation + 1)?;

writeln!(f, "}}")
if self.body().is_empty() {
f.write_str(") {}")
} else {
f.write_str(") {\n")?;
self.body.display(f, indentation + 1)?;
write!(f, "{}}}", " ".repeat(indentation))
}
}
}

Expand Down
12 changes: 7 additions & 5 deletions boa/src/syntax/ast/node/declaration/function_decl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,13 @@ impl FunctionDecl {
) -> fmt::Result {
write!(f, "function {}(", self.name)?;
join_nodes(f, &self.parameters)?;
f.write_str(") {{")?;

self.body.display(f, indentation + 1)?;

writeln!(f, "}}")
if self.body().is_empty() {
f.write_str(") {}")
} else {
f.write_str(") {\n")?;
self.body.display(f, indentation + 1)?;
write!(f, "{}}}", " ".repeat(indentation))
}
}
}

Expand Down
21 changes: 17 additions & 4 deletions boa/src/syntax/ast/node/declaration/function_expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,24 @@ impl FunctionExpr {
}
f.write_str("(")?;
join_nodes(f, &self.parameters)?;
f.write_str(") {{")?;

self.body.display(f, indentation + 1)?;
f.write_str(") ")?;
self.display_block(f, indentation)
}

writeln!(f, "}}")
/// Displays the function's body. This includes the curly braces at the start and end.
/// This will not indent the first brace, but will indent the last brace.
pub(in crate::syntax::ast::node) fn display_block(
&self,
f: &mut fmt::Formatter<'_>,
indentation: usize,
) -> fmt::Result {
if self.body().is_empty() {
f.write_str("{}")
} else {
f.write_str("{\n")?;
self.body.display(f, indentation + 1)?;
write!(f, "{}}}", " ".repeat(indentation))
}
}
}

Expand Down
29 changes: 29 additions & 0 deletions boa/src/syntax/ast/node/declaration/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,32 @@ fn duplicate_function_name() {

assert_eq!(&exec(scenario), "12");
}

#[test]
fn fmt() {
super::super::test_formatting(
r#"
function func(a, b) {
console.log(a);
};
function func_2(a, b) {};
let arrow_func = (a, b) => {
console.log("in multi statement arrow");
console.log(b);
};
async function async_func(a, b) {
console.log(a);
};
pass_async_func(async function(a, b) {
console.log("in async callback", a);
});
pass_func(function(a, b) {
console.log("in callback", a);
});
let arrow_func_2 = (a, b) => {};
async function async_func_2(a, b) {};
pass_async_func(async function(a, b) {});
pass_func(function(a, b) {});
"#,
);
}
3 changes: 3 additions & 0 deletions boa/src/syntax/ast/node/field/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ pub mod get_const_field;
pub mod get_field;

pub use self::{get_const_field::GetConstField, get_field::GetField};

#[cfg(test)]
mod tests;
10 changes: 10 additions & 0 deletions boa/src/syntax/ast/node/field/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#[test]
fn fmt() {
super::super::test_formatting(
r#"
a.field_name;
a[5];
a["other_field_name"];
"#,
);
}
14 changes: 5 additions & 9 deletions boa/src/syntax/ast/node/iteration/continue_node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,11 @@ impl Executable for Continue {

impl fmt::Display for Continue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"continue{}",
if let Some(label) = self.label() {
format!(" {}", label)
} else {
String::new()
}
)
write!(f, "continue")?;
if let Some(label) = self.label() {
write!(f, " {}", label)?;
}
Ok(())
}
}

Expand Down
7 changes: 5 additions & 2 deletions boa/src/syntax/ast/node/iteration/do_while_loop/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,12 @@ impl DoWhileLoop {
f: &mut fmt::Formatter<'_>,
indentation: usize,
) -> fmt::Result {
write!(f, "do")?;
if let Some(ref label) = self.label {
write!(f, "{}: ", label)?;
}
write!(f, "do ")?;
self.body().display(f, indentation)?;
write!(f, "while ({})", self.cond())
write!(f, " while ({})", self.cond())
}
}

Expand Down
8 changes: 5 additions & 3 deletions boa/src/syntax/ast/node/iteration/for_in_loop/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ impl ForInLoop {
}

pub fn display(&self, f: &mut fmt::Formatter<'_>, indentation: usize) -> fmt::Result {
write!(f, "for ({} in {}) {{", self.variable, self.expr,)?;
self.body().display(f, indentation + 1)?;
f.write_str("}")
if let Some(ref label) = self.label {
write!(f, "{}: ", label)?;
}
write!(f, "for ({} in {}) ", self.variable, self.expr)?;
self.body().display(f, indentation)
}
}

Expand Down
Loading

0 comments on commit 057cbb1

Please sign in to comment.