Skip to content

Commit a67208f

Browse files
authored
Merge pull request #2986 from topecongiro/issue-2907
Handle chain w/ try operators with spaces
2 parents 5fb9418 + ba9e159 commit a67208f

File tree

3 files changed

+98
-26
lines changed

3 files changed

+98
-26
lines changed

src/chains.rs

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@
6565
//! .qux
6666
//! ```
6767
68-
use comment::rewrite_comment;
68+
use comment::{rewrite_comment, CharClasses, FullCodeCharKind, RichChar};
6969
use config::IndentStyle;
7070
use expr::rewrite_call;
71-
use lists::{extract_post_comment, extract_pre_comment, get_comment_end};
71+
use lists::extract_pre_comment;
7272
use macros::convert_try_mac;
7373
use rewrite::{Rewrite, RewriteContext};
7474
use shape::Shape;
@@ -275,6 +275,20 @@ impl Chain {
275275
s.chars().all(|c| c == '?')
276276
}
277277

278+
fn is_post_comment(s: &str) -> bool {
279+
let comment_start_index = s.chars().position(|c| c == '/');
280+
if comment_start_index.is_none() {
281+
return false;
282+
}
283+
284+
let newline_index = s.chars().position(|c| c == '\n');
285+
if newline_index.is_none() {
286+
return true;
287+
}
288+
289+
comment_start_index.unwrap() < newline_index.unwrap()
290+
}
291+
278292
fn handle_post_comment(
279293
post_comment_span: Span,
280294
post_comment_snippet: &str,
@@ -289,25 +303,14 @@ impl Chain {
289303
// No post comment.
290304
return;
291305
}
292-
// HACK: Treat `?`s as separators.
293-
let trimmed_snippet = post_comment_snippet.trim_matches('?');
294-
let comment_end = get_comment_end(trimmed_snippet, "?", "", false);
295-
let maybe_post_comment = extract_post_comment(trimmed_snippet, comment_end, "?")
296-
.and_then(|comment| {
297-
if comment.is_empty() {
298-
None
299-
} else {
300-
Some((comment, comment_end))
301-
}
302-
});
303-
304-
if let Some((post_comment, comment_end)) = maybe_post_comment {
306+
let trimmed_snippet = trim_tries(post_comment_snippet);
307+
if is_post_comment(&trimmed_snippet) {
305308
children.push(ChainItem::comment(
306309
post_comment_span,
307-
post_comment,
310+
trimmed_snippet.trim().to_owned(),
308311
CommentPosition::Back,
309312
));
310-
*prev_span_end = *prev_span_end + BytePos(comment_end as u32);
313+
*prev_span_end = post_comment_span.hi();
311314
}
312315
}
313316

@@ -336,9 +339,8 @@ impl Chain {
336339
// Pre-comment
337340
if handle_comment {
338341
let pre_comment_span = mk_sp(prev_span_end, chain_item.span.lo());
339-
let pre_comment_snippet = context.snippet(pre_comment_span);
340-
let pre_comment_snippet = pre_comment_snippet.trim().trim_matches('?');
341-
let (pre_comment, _) = extract_pre_comment(pre_comment_snippet);
342+
let pre_comment_snippet = trim_tries(context.snippet(pre_comment_span));
343+
let (pre_comment, _) = extract_pre_comment(&pre_comment_snippet);
342344
match pre_comment {
343345
Some(ref comment) if !comment.is_empty() => {
344346
children.push(ChainItem::comment(
@@ -872,3 +874,28 @@ fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool
872874
_ => false,
873875
}
874876
}
877+
878+
/// Remove try operators (`?`s) that appear in the given string. If removing
879+
/// them leaves an empty line, remove that line as well unless it is the first
880+
/// line (we need the first newline for detecting pre/post comment).
881+
fn trim_tries(s: &str) -> String {
882+
let mut result = String::with_capacity(s.len());
883+
let mut line_buffer = String::with_capacity(s.len());
884+
for (kind, rich_char) in CharClasses::new(s.chars()) {
885+
match rich_char.get_char() {
886+
'\n' => {
887+
if result.is_empty() || !line_buffer.trim().is_empty() {
888+
result.push_str(&line_buffer);
889+
result.push('\n')
890+
}
891+
line_buffer.clear();
892+
}
893+
'?' if kind == FullCodeCharKind::Normal => continue,
894+
c => line_buffer.push(c),
895+
}
896+
}
897+
if !line_buffer.trim().is_empty() {
898+
result.push_str(&line_buffer);
899+
}
900+
result
901+
}

tests/source/chains_with_comment.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,29 @@ impl Foo {
9393
.map(|(k, deps)| (k.clone(), deps.iter().cloned().filter(|d| dirties.contains(&d)).collect()))
9494
}
9595
}
96+
97+
// #2907
98+
fn foo() {
99+
let x = foo
100+
.bar?? ? // comment
101+
.baz;
102+
let x = foo
103+
.bar? ??
104+
// comment
105+
.baz;
106+
let x = foo
107+
.bar? ? ? // comment
108+
// comment
109+
.baz;
110+
let x = foo
111+
.bar? ?? // comment
112+
// comment
113+
? ??
114+
// comment
115+
? ??
116+
// comment
117+
???
118+
// comment
119+
? ? ?
120+
.baz;
121+
}

tests/target/chains_with_comment.rs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ fn main() {
3131
)
3232
});
3333

34-
let y = expr
35-
/* comment */
34+
let y = expr /* comment */
3635
.kaas()?
3736
// comment
3837
.test();
@@ -50,11 +49,9 @@ fn main() {
5049

5150
let y = a
5251
.very
53-
.loooooooooooooooooooooooooooooooooooooong()
54-
/* comment */
52+
.loooooooooooooooooooooooooooooooooooooong() /* comment */
5553
.chain()
56-
.inside()
57-
/* comment */
54+
.inside() /* comment */
5855
.weeeeeeeeeeeeeee()?
5956
.test()
6057
.0
@@ -116,3 +113,25 @@ impl Foo {
116113
})
117114
}
118115
}
116+
117+
// #2907
118+
fn foo() {
119+
let x = foo
120+
.bar??? // comment
121+
.baz;
122+
let x = foo
123+
.bar???
124+
// comment
125+
.baz;
126+
let x = foo
127+
.bar??? // comment
128+
// comment
129+
.baz;
130+
let x = foo
131+
.bar??????????????? // comment
132+
// comment
133+
// comment
134+
// comment
135+
// comment
136+
.baz;
137+
}

0 commit comments

Comments
 (0)