diff --git a/fmt/src/lib.rs b/fmt/src/lib.rs index 4aff3313..84c5a1a1 100644 --- a/fmt/src/lib.rs +++ b/fmt/src/lib.rs @@ -766,6 +766,15 @@ impl Formatter { }, processor::actions::newline, ) + // Add newline before each identifier in a `with` statement. + .add_rule( + |ctx| { + ctx.in_rule(SyntaxKind::WITH_DECL, false) + && ctx.token(1).is(*IDENTIFIER) + && ctx.token(-1).is_not(*NEWLINE) + }, + processor::actions::newline, + ) // Add newline before the closing brace at the end of rule. .add_rule( |ctx| { @@ -784,14 +793,17 @@ impl Formatter { } else { Box::new(tokens) }; + let tokens: Box>> = if self.indent_section_contents { Box::new(Self::indent_sections(tokens)) } else { Box::new(tokens) }; + let tokens = Self::indent_hex_patterns(tokens); let tokens = Self::indent_parenthesized_exprs(tokens); + let tokens = Self::indent_with_expr(tokens); // indent_body and indent_sections will insert Indentation tokens, but // won't take into account that those tokens must appear before the @@ -834,14 +846,6 @@ impl Formatter { Box::new(tokens) }; - /*let tokens = processor::Processor::new(tokens).add_rule( - |ctx| { - println!("{:?}", ctx.token(1)); - true - }, - processor::actions::copy, - );*/ - let tokens = AddIndentationSpaces::new(tokens, self.indent_spaces); let tokens = RemoveTrailingSpaces::new(tokens); @@ -1024,6 +1028,52 @@ impl Formatter { ) } + /// Indent `with` expressions. For this input... + /// + /// ```text + /// rule foo { + /// condition: + /// with + /// foo = "foo" + /// bar = "bar": (...) + /// } + /// ``` + /// + /// ... the result is ... + /// + /// ```text + /// rule foo { + /// condition: + /// with + /// foo = "foo" + /// bar = "bar": (...) + /// } + /// ``` + fn indent_with_expr<'a, I>(input: I) -> impl TokenStream<'a> + 'a + where + I: TokenStream<'a> + 'a, + { + processor::Processor::new(input) + // Ignore all comments. + .set_passthrough(*COMMENT) + // Increase indentation after the `with` keyword. + .add_rule( + |ctx| { + ctx.in_rule(SyntaxKind::WITH_EXPR, false) + && ctx.token(-1).eq(&Keyword(b"with")) + }, + processor::actions::insert(Indentation(1)), + ) + // Decrease indentation after the `with` expression. + .add_rule( + |ctx| { + ctx.token(1).eq(&End(SyntaxKind::WITH_EXPR)) + && ctx.token(-1).neq(&Indentation(-1)) + }, + processor::actions::insert(Indentation(-1)), + ) + } + /// Indent hex patterns. For this input... /// /// ```text @@ -1257,6 +1307,7 @@ impl Formatter { // - No space after "(" and "[" // - No space before ")" and "]" // - No space before ":" + // - No space before "," // - No space before or after ".." (e.g: (0..10)) // - No space before or after "." (e.g: foo.bar) // - No space in-between identifiers and "(" or "[" (e.g: array[0], @@ -1276,6 +1327,7 @@ impl Formatter { let drop_space = // Don't insert space if next token is ":" next_token.eq(&COLON) + || next_token.eq(&COMMA) // Don't insert space after "-" || prev_token.eq(&HYPHEN) // Don't insert spaces around "." diff --git a/fmt/src/testdata/test33.formatted b/fmt/src/testdata/test33.formatted new file mode 100644 index 00000000..899fdeb8 --- /dev/null +++ b/fmt/src/testdata/test33.formatted @@ -0,0 +1,6 @@ +import "math" + +rule test { + condition: + math.min(0, 1) == 0 +} diff --git a/fmt/src/testdata/test33.unformatted b/fmt/src/testdata/test33.unformatted new file mode 100644 index 00000000..04cbff93 --- /dev/null +++ b/fmt/src/testdata/test33.unformatted @@ -0,0 +1,6 @@ +import "math" + +rule test { + condition: + math.min( 0 , 1) == 0 +} \ No newline at end of file diff --git a/fmt/src/testdata/test34.formatted b/fmt/src/testdata/test34.formatted new file mode 100644 index 00000000..fbfd9ef4 --- /dev/null +++ b/fmt/src/testdata/test34.formatted @@ -0,0 +1,16 @@ +rule test_1 { + condition: + with + foo = "foo", + bar = "baz": (true) +} + +rule test_2 { + condition: + with + // This is a comment + foo = "foo", + bar = "baz": ( + true + ) +} diff --git a/fmt/src/testdata/test34.unformatted b/fmt/src/testdata/test34.unformatted new file mode 100644 index 00000000..cc3a5db0 --- /dev/null +++ b/fmt/src/testdata/test34.unformatted @@ -0,0 +1,13 @@ +rule test_1 { + condition: + with foo = "foo", bar = "baz": (true) +} + +rule test_2 { + condition: + with + // This is a comment + foo = "foo", bar = "baz": ( + true + ) +} \ No newline at end of file diff --git a/fmt/src/tokens/mod.rs b/fmt/src/tokens/mod.rs index a30fbd17..020e507d 100644 --- a/fmt/src/tokens/mod.rs +++ b/fmt/src/tokens/mod.rs @@ -131,6 +131,7 @@ pub(crate) mod categories { lazy_static! { pub(crate) static ref ASTERISK: Token<'static> = Token::Punctuation(b"*"); pub(crate) static ref COLON: Token<'static> = Token::Punctuation(b":"); + pub(crate) static ref COMMA: Token<'static> = Token::Punctuation(b","); pub(crate) static ref DOT: Token<'static> = Token::Punctuation(b"."); pub(crate) static ref EQUAL: Token<'static> = Token::Punctuation(b"="); pub(crate) static ref HYPHEN: Token<'static> = Token::Punctuation(b"-"); @@ -371,6 +372,7 @@ impl<'a> Token<'a> { | SyntaxKind::THEM_KW | SyntaxKind::TRUE_KW | SyntaxKind::WIDE_KW + | SyntaxKind::WITH_KW | SyntaxKind::XOR_KW => Token::Keyword(src), // Punctuation. SyntaxKind::ASTERISK