-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Format: keep trailing spaces in macros #7099
Format: keep trailing spaces in macros #7099
Conversation
Could you give an example where removing a trailing whitespace changes semantics? |
@straight-shoota Just Rewriting string literal value by formatter is totally evil and unintentionally. When the following code is given: (NOTE: Please drag this code. Heredoc left_aligned_string = <<-LEFT_ALINGED
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
LEFT_ALINGED
puts left_aligned_string.lines.map { |line| line + line }.join "\n" Var $ crystal run left_aligned.cr
1 1
2 2
Fizz Fizz
4 4
Buzz Buzz
Fizz Fizz
7 7
8 8
Fizz Fizz
Buzz Buzz
11 11
Fizz Fizz
13 13
14 14
FizzBuzz FizzBuzz Encloses this code by macro and adds this invocation, then formats the file by current macro main
left_aligned_string = <<-LEFT_ALINGED
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
LEFT_ALINGED
puts left_aligned_string.lines.map { |line| line + line }.join "\n"
end
main Trailing spaces inside heredocs are removed, so the output is broken. $ crystal tool format -< fizz.cr | crystal eval
11
22
FizzFizz
44
BuzzBuzz
FizzFizz
77
88
FizzFizz
BuzzBuzz
1111
FizzFizz
1313
1414
FizzBuzzFizzBuzz Yes, it is very conservative fix. I believe the formatter should not break the given source code of course. The output of |
Even though it's a conservative change, having invisible code is a really bad practice in my opinion. |
In your example the trailing whitespace is removed inside a string literal (heredoc). That's obviously incorrect, whether it's inside a macro method or not. But as far as I can tell, this PR is not limited to string literals. Can you show an example where in a macro trailing whitespace is relevant outside a string literal? |
@straight-shoota That's the only use case, string literals inside macros. If I remember correctly the macro processor doesn't know it's inside a string literal, everything is just "text". |
@asterite If I understand correctly, a part of the issue is that trailing whitespace in a string literal is handled differently inside a macro method. ( # formatter preserves trailing whitespace
<<-EOF
foo ¶
EOF
macro foo
# formatter removes trailing whitespace
<<-EOF
foo ¶
EOF
end The formatter should treat both cases the same, either remove or preserve trailing whitespace. |
@straight-shoota Backslash line continuation is another example. When it has trailing spaces, it cannot compile. Otherwise, it pass through the compiler if the formatter removes trailing spaces. macro foo
foo = 1
p foo \
+ 1
end
foo @asterite You are right and I think so too. However I also think it is linter field. I'm surveying other formatters and linters (with |
In any case I think this should be fixed. I think the formatter does a last pass that removes trailing whitespace so this migh be a bit hard to implement, but this PR seems to work, so 👍 from me (I didn't have time to see the diff yet). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unfortunate that the formatter cannot format macros, but the formatter should not ever break code. That's it's primary directive and breaking it makes developers loose confidence in autoformat.
@@ -1234,4 +1234,31 @@ describe Crystal::Formatter do | |||
# 3 + 4 | |||
# ``` | |||
CODE | |||
|
|||
# Keep trailing spaces in macros. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Editors are usually configured to trim white spaces at the end.
These specs should be written different in order to avoid loosing those spaces.
Perhaps CI will fail because I found a new formatter bug. I think it is irrelevant to this PR, so I will open a new PR when I fixed this. |
done |
I was expecting a single line string filled with " \n \n " to preserve trailing spaces 😄. The proposed way is far more clear. Feel free to change it to " \n \n " if you timeout with the formatter bug you reached. |
@bcardiff However the first spec of this is too long to write as single line, so I'd write to: assert_format(
"macro foo\n" +
" <<-FOO\n" +
" hello \n" +
" FOO\n" +
"end\n" +
"{% verbatim do %}\n" +
" <<-FOO\n" +
" hello \n" +
" FOO\n" +
"{% end %}\n" +
"{% if true %}\n" +
" <<-FOO\n" +
" hello \n" +
" FOO\n" +
"{% end %}\n" +
"{% for a in %w() %}\n" +
" <<-FOO\n" +
" hello \n" +
" FOO\n" +
"{% end %}"
) What do you think? |
@makenowjust You could put the individual samples each on a single line string. And maybe use line continuation ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @makenowjust 👍
needs rebase |
Currently the formatter removes trailing spaces in macros, however macro may contain meaningful trailing spaces (e.g. space inside string literals), so it is possible to change program meaning. The formatter should keep such spaces because formatter doesn't change input program meaning at any time.
But keep trailing spaces in macro body outside macro expressions
63f7a27
to
f52b90b
Compare
rebased |
Currently the formatter removes trailing spaces in macros, however macro may contain meaningful trailing spaces (e.g. space inside string literals), so it is possible to change program meaning.
The formatter should keep such spaces because formatter doesn't change input program meaning at any time.