| Summary: | [formatter] Follow-up bug for comments | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Manoj N Palat <manoj.palat> | ||||||||||||||
| Component: | Core | Assignee: | Mateusz Matela <mateusz.matela> | ||||||||||||||
| Status: | VERIFIED FIXED | QA Contact: | |||||||||||||||
| Severity: | normal | ||||||||||||||||
| Priority: | P3 | CC: | daniel_megert, jarthana, manoj.palat, markus.kell.r, mateusz.matela, noopur_gupta | ||||||||||||||
| Version: | 4.5 | Flags: | manoj.palat:
review+
|
||||||||||||||
| Target Milestone: | 4.5 M7 | ||||||||||||||||
| Hardware: | PC | ||||||||||||||||
| OS: | Windows 7 | ||||||||||||||||
| See Also: |
https://git.eclipse.org/r/46737 https://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=871cac4ba4cecfc6322ce0af5777177652a514a9 |
||||||||||||||||
| Whiteboard: | |||||||||||||||||
| Bug Depends on: | 303519, 462945, 463590 | ||||||||||||||||
| Bug Blocks: | 431523 | ||||||||||||||||
| Attachments: |
|
||||||||||||||||
|
Description
Manoj N Palat
When I said "the new formatter doesn't align asterisks at comment line beginnings when comment formatting is disabled", I meant it as a feature - don't format comments should mean leave them alone, so aligning asterisks is not desired. A lot of modifications for tests in bug 303519 was related to this. It's a non-breaking change (it will not cause sources formatted with the old formatter to be changed by the new formatter) so I didn't mention it. So I think we should change the scenarios you used Manoj, if they are somewhere in the repos, otherwise there's nothing to do :) In the org.eclipse.jdt.ui.tests.refactoring.all.AllAllRefactoringTests, there's one failure in InlineTempTests18#test1().
Reduced test case (inline variable "fi"):
-------
package p;
import java.util.function.IntUnaryOperator;
class TestInlineLambda1 {
{
IntUnaryOperator fi = x -> x;
int hi = fi.hashCode();
}
}
-------
Result with a space too much after "x -> x":
int hi = ((IntUnaryOperator) x -> x ).hashCode();
The underlying reason is this behavior in the new formatter, where the space is inserted after the "x -> {}":
-------
package p;
import java.util.function.IntConsumer;
class TestInlineLambda1 {
{
IntConsumer op = (x -> {
});
}
}
-------
The space is inserted in SpacePreparator#visit(Block). A fix is to make that method end like this, i.e. extends the special case to TokenNameRPAREN as well:
if (this.options.insert_space_after_closing_brace_in_block) {
int closeBraceIndex = this.tm.lastIndexIn(node, TokenNameRBRACE);
if (closeBraceIndex + 1 < this.tm.size()) {
int nextToken = this.tm.get(closeBraceIndex + 1).tokenType;
if (nextToken != TokenNameSEMICOLON && nextToken != TokenNameRPAREN) {
this.tm.get(closeBraceIndex).spaceAfter();
}
}
}
return true;
For this source, the line break after the last ',' is removed, even if the option "Never join already wrapped lines" is checked:
String[] strings = {
"Hello World",
"How are you",
"anything and yet nothing in particular",
};
The line break is also removed if there's no trailing comma.
For this source, all line breaks are removed (despite the never-join setting):
private static final String CU_POSTFIX= " {\n" +
" \n" +
"}\n" +
"}\n";
(In reply to Markus Keller from comment #3) > For this source, the line break after the last ',' is removed, even if the > option "Never join already wrapped lines" is checked: > > String[] strings = { > "Hello World", > "How are you", > "anything and yet nothing in particular", > }; The thing is the old formatter never wrapped on the closing brace in an array initializer - it either wrapped on the last element or not at all. In the new formatter the "Never join already wrapped lines" option only works in places where formatter itself is allowed to wrap (more about this in bug 372801), so a line break before a closing brace is removed. I think it's a good idea to allow wrapping on the closing brace in this case, but with lower priority to avoid effects like this: String[] strings = { "Hello World", "How are you", }; I'll implement it this way. > The line break is also removed if there's no trailing comma. > > For this source, all line breaks are removed (despite the never-join > setting): > > private static final String CU_POSTFIX= " {\n" + > " \n" + > "}\n" + > "}\n"; The formatter settings probably say wrapping should take place before a binary operator, so line breaks after an operator are not considered a valid wrap to preserve (as mentioned above). I this behavior acceptable? See bug 303519 comment #145 as well. The "Never join already wrapped lines" should continue to do exactly what it says. When enabled, the formatter should just never remove a line delimiter, independent of any other settings. (In reply to Markus Keller from comment #6) > The "Never join already wrapped lines" should continue to do exactly what it > says. When enabled, the formatter should just never remove a line delimiter, > independent of any other settings. Well, it still does what it says, it's just that the definition of "already wrapped lines" has changed a bit. Delimiters that break formatting are not line wrapping. Even the old formatter did remove some line delimiters, though inconsistently. We can add a few exceptions and leave some additional line breaks if really necessary, but IMO leaving all the delimiters in would not make much sense. I present my arguments in bug 372801, we can continue the discussion there. (In reply to Mateusz Matela from comment #4) > > For this source, all line breaks are removed (despite the never-join > > setting): > > > > private static final String CU_POSTFIX= " {\n" + > > " \n" + > > "}\n" + > > "}\n"; > The formatter settings probably say wrapping should take place before a > binary operator, so line breaks after an operator are not considered a valid > wrap to preserve (as mentioned above). I this behavior acceptable? When I uncheck "Wrap before operator" (and have "Never join..." checked) then the line breaks indeed stay as expected. Nevertheless, the "Never join..." option used to keep such line breaks regardless of the "Wrap before operator" setting and the position of the operator in pre-wrapped code. This behavior needs to be preserved in the new formatter. String concatenation is the prime example where the "Never join..." option is used all the time, and changing this now would cause too many surprises. Created attachment 250909 [details]
Example project
Found 2 differences in the formatter wrt line wrapping, which may be the same as discussed in above comments.
In the attached example, press Ctrl+Shift+F on the file.
The two formatting changes were not happening with the earlier formatter.
(In reply to Noopur Gupta from comment #9) > Found 2 differences in the formatter wrt line wrapping, which may be the > same as discussed in above comments. The first change (array initializer closing brace) was duscussed earlier and I had an idea in comment 4 but I still think about a better solution. The method invocation chain is joined because wrapping policy for "Function Calls -> Qualified invocations" is "Do not wrap". If you change it to "Wrap where necessary", formatting should work as expected. Is this OK? Correct me if I'm wrong, but I can't imagine it would be very important to someone to always preserve existing wrapping, but othwersie allow exceeding the line limit. Even then, maybe a good solution would be to increase maximum line width (unless this strange requirement is only for qualified invocations, which makes this scenario even stranger). (In reply to Markus Keller from comment #8) > Nevertheless, the "Never join..." option used to keep such line breaks > regardless of the "Wrap before operator" setting and the position of the > operator in pre-wrapped code. This behavior needs to be preserved in the new > formatter. String concatenation is the prime example where the "Never > join..." option is used all the time, and changing this now would cause too > many surprises. What do you think about adding a setting for this? Next to the "Wrap before operator" checkbox, there would be something like "Never join if opposite" checkbox, checked by default, enabled only when "Never join already wrapped lines" is true. I think it's important, because if we revert to the old behavior without an option, it would render the "Wrap before operator" setting pretty much meaningless when the "Never join..." setting is on. One could accidentally type some code that breaks the rule agreed upon by their team and the formatter would just ignore it. Created attachment 250953 [details] patch - version 1 - fix for extra space after a lambda proposed in comment 2 + a test -> InlineTempTests18#test1() can be enabled again - "Never join lines" preserves a line break before array initializer closing brace as per comment 4 + changed affected tests - removed unnecessary file as per comment 5 - added FormatterOldBugsGistTests to RunFormatterTests (I missed that in the original patch) Mrkus, Manoj, In addition to comment 11, I have a few other ideas for changes in formatter settings. I'd like to know if you'll have the time to discuss, review and commit these in the 3 weeks before API freeze. 0. see comment 11 1. New options to allow wrapping before/after comparison operators. Current formatter will do something like this: if (aaaaaaaaa .bbbbbb() == ccccc .ddddddd() { And I think this would be nicer: if (aaaaaaaaa.bbbbbb() == ccccc.ddddddd() { 2. New option to prefer lines of similar length, to avoid code like this: int a = some.example(1, 2, 3, 4, 5, 6, 7); in favor of this: int a = some.example(1, 2, 3, 4, 5, 6, 7); This rule would have the lowest priority and it would try to minimize the variation for number of tokens in each line. 3. In the "Braces" settings card, add a new option for each combo box: "Keep existing position". This would be a partial remedy for people who won't like the new interpretation of the "Never join lines" rule. 4. In the "Braces" settings card, add the position configuration for array initializer closing brace. This would mostly solve bug 176820. It would probably make the "Keep empty array..." option unnecessary. It may be a good idea to add this for lambda closing brace too. (In reply to Mateusz Matela from comment #10) > (In reply to Noopur Gupta from comment #9) > > Found 2 differences in the formatter wrt line wrapping, which may be the > > same as discussed in above comments. > The first change (array initializer closing brace) was duscussed earlier and > I had an idea in comment 4 but I still think about a better solution. The > method invocation chain is joined because wrapping policy for "Function > Calls -> Qualified invocations" is "Do not wrap". If you change it to "Wrap > where necessary", formatting should work as expected. Is this OK? Correct me > if I'm wrong, but I can't imagine it would be very important to someone to > always preserve existing wrapping, but othwersie allow exceeding the line > limit. Even then, maybe a good solution would be to increase maximum line > width (unless this strange requirement is only for qualified invocations, > which makes this scenario even stranger). I received these examples through bug 459341. Can't say how important it is to preserve the existing wrapping here. Created attachment 251319 [details] Example Project 2 Attached another example that shows change in formatter behavior. Formatting the code in example adds additional indentation to enum constants now. This results in toggle on save (similar to other cases mentioned in bug 439582). Let me know if the new formatter behavior is as expected. In that case, 'correct indentation' will have to be adapted accordingly. (In reply to Noopur Gupta from comment #15) > Attached another example that shows change in formatter behavior. Formatting > the code in example adds additional indentation to enum constants now. This > results in toggle on save (similar to other cases mentioned in bug 439582). > Let me know if the new formatter behavior is as expected. In that case, > 'correct indentation' will have to be adapted accordingly. I confirm this change is intentional. The old formatter treated the "Indent on column" policy for enum constants the same as "Default indentation", which didn't make sense. The new formatter actually indents on column, the same way as other elements. Moving to M7 Created attachment 251749 [details] File - for Example Project 2 (In reply to Mateusz Matela from comment #16) > (In reply to Noopur Gupta from comment #15) > > Attached another example that shows change in formatter behavior. Formatting > > the code in example adds additional indentation to enum constants now. This > > results in toggle on save (similar to other cases mentioned in bug 439582). > > Let me know if the new formatter behavior is as expected. In that case, > > 'correct indentation' will have to be adapted accordingly. > I confirm this change is intentional. The old formatter treated the "Indent > on column" policy for enum constants the same as "Default indentation", > which didn't make sense. The new formatter actually indents on column, the > same way as other elements. Add the attached file to example project given in comment #15 and press Ctrl+Shift+F on the file to format. In "TestEnum", only the first enum constant is indented on column and other enum constants are not. (In reply to Noopur Gupta from comment #18) > Add the attached file to example project given in comment #15 and press > Ctrl+Shift+F on the file to format. In "TestEnum", only the first enum > constant is indented on column and other enum constants are not. This is the result of copying the old formatter's behavior for wrapped elements separated by empty lines. Usually, when wrap policy is 'wrap where necessary', having an empty line before a wrappable element results in this element not being indented, for example: public void test(int a, int b) { } I just didn't notice that this behavior was different if the wrap policy is 'wrap all elements + force split'. This is easy to change in WrapExecutor#getWrapIndent(). I'm only wondering if we should keep the old behavior for 'wrap where necessary' policy or just add the indentation in every case. Manoj, Markus, do you have an opinion on this? There are currently 3 tests that relay on this behavior, all use the same sample code - see .howMany() method call at the end of /org.eclipse.jdt.core.tests.model/workspace/FormatterJSR335/testLambda/A_out.java (In reply to Mateusz Matela from comment #16) > (In reply to Noopur Gupta from comment #15) > > Attached another example that shows change in formatter behavior. Formatting > > the code in example adds additional indentation to enum constants now. This > > results in toggle on save (similar to other cases mentioned in bug 439582). > > Let me know if the new formatter behavior is as expected. In that case, > > 'correct indentation' will have to be adapted accordingly. > I confirm this change is intentional. The old formatter treated the "Indent > on column" policy for enum constants the same as "Default indentation", > which didn't make sense. The new formatter actually indents on column, the > same way as other elements. Looks good. However, when I change the Indentation policy for enum constants to "Indent by one", I see 8 spaces before the constants and changing it to "Default indentation" adds only 4 spaces. In my view, this should be reversed. Please correct me if I am wrong. Created attachment 251859 [details]
File - for built-in formatter profile - indents comments in switch-case
In the attached file, apply formatter with built-in formatter profile. The comments in switch-case are unnecessarily indented.
(In reply to Noopur Gupta from comment #20) > > Looks good. However, when I change the Indentation policy for enum constants > to "Indent by one", I see 8 spaces before the constants and changing it to > "Default indentation" adds only 4 spaces. In my view, this should be > reversed. Please correct me if I am wrong. Yes, this is counterintuitive, but the old formater behaved this way. I've decided that this issue is not important enough to change it now and risk potential problems related to the need to change the workspace/project settings on switching to new Eclipse. (In reply to Noopur Gupta from comment #21) > Created attachment 251859 [details] > File - for built-in formatter profile - indents comments in switch-case > > In the attached file, apply formatter with built-in formatter profile. The > comments in switch-case are unnecessarily indented. Reported bug 463590 for this. Based on discussion with Dani, reported bug 463596 to discuss the enum related issues reported in this bug. Mateusz: Any further action expected in this for M7? As I mentioned in bug 463590 comment 1 and bug 463372 comment 1, I thought you would quickly push the fix for bug 462945 and then I'd upload the second version of the patch here with additional fixes for issues mentioned by Noopur. In the meantime a few separate bugs were added with problems addressed here so I'm not sure if you prefer one patch in this bug or separate patches in the new bugs (I prefer the former). Created attachment 252854 [details] patch - version2 Rebased everything on current trunk, and in addition to things listed in comment 12: - Better indentation of comments in switch statements as per comment 21 and bug 463590 - "Never join lines" preserves line breaks on the wrong side of operators + changed affected tests, as per comment 8 and bug 463372 - Elements wrapped with a "Wrap all" policy are properly indented even if separated by empty lines, as per comment 19 - "Use spaces to indent wrapped lines" does not affect enum constants, as per comment 24 and bug 463596 (In reply to Mateusz Matela from comment #27) > Created attachment 252854 [details] > patch - version2 I find a .txt file part of the patch, which probably shouldn't be there? a/org.eclipse.jdt.core/eclipse.jdt.ui.patch.txt (In reply to Jay Arthanareeswaran from comment #28) > > I find a .txt file part of the patch, which probably shouldn't be there? > > a/org.eclipse.jdt.core/eclipse.jdt.ui.patch.txt The .txt shouldn't be there, so this patch removes it. As per your comment 5 :) (In reply to Mateusz Matela from comment #29) > The .txt shouldn't be there, so this patch removes it. As per your comment 5 > :) I see, thanks! (In reply to Mateusz Matela from comment #27) > Created attachment 252854 [details] > patch - version2 > > - "Use spaces to indent wrapped lines" does not affect enum constants, as > per comment 24 and bug 463596 In this bug 463596, in the "E2.java" of project "Modified Profile 1" in the attachment, after the application of this patch the 2nd and 3rd enums are formatted differently. This can be taken up when bug 463596 is addressed and this patch can be committed. +1. New Gerrit change created: https://git.eclipse.org/r/46737 Gerrit change https://git.eclipse.org/r/46737 was merged to [master]. Commit: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=871cac4ba4cecfc6322ce0af5777177652a514a9 (In reply to Manoj Palat Away Until May 11 2015 from comment #31) > In this bug 463596, in the "E2.java" of project "Modified Profile 1" in the > attachment, after the application of this patch the 2nd and 3rd enums are > formatted differently. This can be taken up when bug 463596 is addressed and > this patch can be committed. +1. It turns out this problem is not speciffic to enum constants, so I'll keep the discussion in this bug. This is actually a follow-up to comment 19: (In reply to Mateusz Matela from comment #19) > (In reply to Noopur Gupta from comment #18) > > Add the attached file to example project given in comment #15 and press > > Ctrl+Shift+F on the file to format. In "TestEnum", only the first enum > > constant is indented on column and other enum constants are not. > > This is the result of copying the old formatter's behavior for wrapped > elements separated by empty lines. Usually, when wrap policy is 'wrap where > necessary', having an empty line before a wrappable element results in this > element not being indented, for example: > public void test(int a, > > int b) { > } > I just didn't notice that this behavior was different if the wrap policy is > 'wrap all elements + force split'. > > This is easy to change in WrapExecutor#getWrapIndent(). I'm only wondering > if we should keep the old behavior for 'wrap where necessary' policy or just > add the indentation in every case. Manoj, Markus, do you have an opinion on > this? > There are currently 3 tests that relay on this behavior, all use the same > sample code - see .howMany() method call at the end of > /org.eclipse.jdt.core.tests.model/workspace/FormatterJSR335/testLambda/A_out. > java There was a decision to be made and I went with an option that seemed to be safer: keep the old formatter's behavior for elements wrapped with the "wrap where necessary" policy and fix indentation only for "wrap all elements.." policies. But this doesn't work for the first element with the "wrap all elements except first..." policy. I don't see a simple way to change the behavior for this particular case, so now I'm leaning towards indenting all elements regardless of wrapping policy. This "feature" of skipping indentation after an empty line didn't seem to make much sense anyway... If you don't object, I'll upload a second patch here with this change. The patch has already been released. We have two options: Either to keep this open and address during RC1 or close this and take it up on another bug for RC1. . *** Bug 463590 has been marked as a duplicate of this bug. *** Verified for 4.5 RC3 with build I20150524-2000. |