-
Notifications
You must be signed in to change notification settings - Fork 931
Format tuple like structs #93
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
Conversation
(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment | ||
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, | ||
G, | ||
W); |
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.
I think I would format like this:
struct Qux<'a,
N: Clone + 'a,
E: Clone + 'a,
G: Labeller<'a, N, E> + GraphWalk<'a, N, E>,
W: Write + Copy>(
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,
G,
W,
);
Note the trailing comma - we probably want three options for trailing commas in tuples - always, never, and vertical only (maybe we have these options already, actually).
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.
That looks good, but isn't it inconsistent with the rest of the formatting rules? We usually don't have a 'dangling' closing paren for tuple-like structures.
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.
I don't think we can be consistent with both the expression form and regular structs. I think being closer to other items is more important here (and gives less weird indenting). Struct literals also vary a bit from struct definitions, so I think its OK.
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.
Alright, will implement.
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.
Thanks!
Also, if you take this approach I wonder if you can format each field independently so we can cope with a mix of struct-like and tuple-like fields. Obvs whether you use |
That was my initial approach, but it didn't work out very well for me. Especially switching between horizontal mode and vertical mode is unique to the tuple variant. It also requires distinct formatting code, and then we'd probably just reimplement |
I might be missing the subtleties having not written the code. But it seems like the vertical vs horizontal is just a parameter to write_list and can be deduced at the same time as whether to use {} or (). Formatting each field into a string should be independent of any formatting of the whole struct. |
Right, I think I understand now. So we'd make |
Yeah, I think that should work. I might be wrong because of attributes on fields, but hopefully not. |
I'll look into it! |
Should be functionally correct now, but still needs a refactor. WIP. |
I am a bit stuck here. What gives me the most troubles is that in a struct like |
@marcusklaas definitely a libsyntax bug, lets fix it there. |
I don't know what changed, but that bug that I mentioned earlier no longer seems to be present! Still, I have troubles finishing this PR. Quick recap: I'm trying to format all structs using the struct Problematic {
// Our first and
pub x: String, // only field
} This is very difficult, I think. I do have some workarounds in mind, but I thought I'd run them by you first. We could pass two associated comments for every item we give to struct Tuple(
// Some int
i32
); That would ideally be formatted as struct Tuple(i32 /* Some int */); That can't be done (easily) if we can't distinguish between the comment and the item itself. On a related note, I believe the comments we pass to This may all be going a bit far, so maybe it's best to just do something that works now (merge preceding comment and item texts) and leave improvements for later. What do you think, @nrc? |
Hmm, it is a tricky issue. I think there are a few questions here. The first one is, do we want to move comments around? I had been ducking this issue previously. We could imagine having a style guideline that says "all comments on fields should happen on the previous line" or something. My intuition is that, in general, the programmer probably knows best with comments and we should do the minimum of reorganisation. We can certainly re-visit this later though. I do think we can and should change the kind of comment - i.e., The next question is how much we want to get right. There are already some cases we don't even try to handle, e.g., Given that there is so much variety in how we could place comments, I believe we have to let write_list do it, rather than trying to do some merging before passing to write_list. So, all of this suggests that having pre- and post-comments passed to write_list is a good idea. Probably we should pass one list of structs, rather than three lists. Probably need to start using Options rather than empty strings too. I think passing the comments without the // or /* */ is a good idea. (The complicated aspect here is that where to put the comments and what tokens to use depends on how write_list lays them out). I think this shouldn't be too hard. I think the quick and dirty approach will actually cause problems in the short run too, so isn't worth it. I'd be fine with not covering all the possible situations in write_list for now. I.e., panicking in some situations and fixing them later. Only implement what you need here and to not cause regressions. The other option if you think that is too slow would be to not handle side comments for now (i.e., only handle comments on the preceding line). |
Thank you for your wisdom Nicholas. I fully agree and will try to implement what was suggested. |
I've given this an update. It should close https://github.com/nrc/rustfmt/issues/86 and https://github.com/nrc/rustfmt/issues/76, since struct-like enum variants are formatted now as well. Some progress on https://github.com/nrc/rustfmt/issues/27 has been made as well. Formatting the comments correctly was the biggest challenge, after all. A brief description of the approach: let struct AmbiguousIsMe {
pub x: 32, // this is clearly belongs to x
// but what about this?
// this clearly belongs to y
y: PrivateType
} Most expressions and items that use There's a million edge cases, which tend to make things messy. For example, a long post-comment will be converted into a block-style comment. The last post-comment in expression-like lists will also be in block-style, to prevent the comments from commenting out actual code: fn test(
arg_one: i32, // looooooooooong comment
arg_two: &str // comment
) { may become fn test(arg_one: i32, // looooooooooong comment
arg_two: &str /* comment */) { There's many changes here and I am confident about only few of those, so I would be very grateful for any feedback! |
.trim_left_matches("* ") | ||
.trim_left_matches('*') | ||
.trim_right_matches("*/") | ||
.trim_right_matches(' ') |
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.
I think there is a problem with comments like
// // /* <- yes, I want to talk about comments in my comment
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.
Good catch!
Except theses details, seems very nice. |
Thank you very much for your excellent commentary, @cassiersg. I'll get to work! |
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
// Format comments and string literals |
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.
I would break this into separate modules for stings and comments, unless there is a lot of overlap I'm not noticing
offset); | ||
|
||
result.push(' '); | ||
result.push_str(&formatted_comment); | ||
} |
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.
The handling of comments in Mixed
mode seems to be incorrect : line_len
should be updated with the comments len.
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.
Excellent observation, thanks!
Should also fix https://github.com/nrc/rustfmt/issues/87 now. |
@@ -41,11 +47,38 @@ pub struct ListFormatting<'a> { | |||
pub h_width: usize, | |||
// Available width if we layout vertically | |||
pub v_width: usize, | |||
// Non-expressions, e.g. items, will have a new line at the end of the list. | |||
// Important for comment styles. | |||
pub is_expression: bool |
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.
Could this be named to be more about what you're doing rather than why? ends_with_newline or ends_block or something? (also needs a trailing comma)
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.
The more I think about this, the less I like it. Could we append a newline and block_indent instead of using a block comment in the expression case? It feels a bit irregular atm.
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.
I agree it's not pretty, but I am afraid it will be a bit irregular in any case. If I understand correctly, we have to decide between
(item1, // Comment 1
item2, // Comment 2
item3, /* Comment 3 */)
and
(item1, // Comment 1
item2, // Comment 2
item3, // Comment 3
)
Personally, I don't believe the latter is always better than the first, but I can get behind it if that's what is decided on.
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.
I don't want to worry too much about this - it should be a total edge case exactly because there is no way to format it nicely. Another alternative might be to change all post-comments to /* */. Or to only do that if there is a final comment? Any way we do this is kind of inconsistent. I guess I prefer a little inconsistency in the punctuation rather than in the comment style (and the code should be simpler), but I don't think it is too important.
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.
Alright. I've left it as it is for now, if you do not mind. We can improve this later.
result.push_str(&rewrite_comment(comment, | ||
// Block style in non-vertical mode | ||
tactic != ListTactic::Vertical, | ||
1000, |
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.
I'm not a fan of these magic 1000s - could you use an Option rather than a usize?
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.
This was actually a bug! 😨
Nice! 🎊 Thank you for your guidance and patience in this, @nrc! I learned a lot doing it! |
A pleasure; thanks for the PR! |
This adds formatting for tuple like structs, and should address https://github.com/nrc/rustfmt/issues/86.