Skip to content

Commit 031e029

Browse files
authored
fix to extract comments to stop internal error (#3857)
2 parents 801cb98 + b57ded9 commit 031e029

File tree

5 files changed

+154
-11
lines changed

5 files changed

+154
-11
lines changed

src/comment.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,7 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle<'_>) -> (&'a s
976976

977977
pub(crate) trait FindUncommented {
978978
fn find_uncommented(&self, pat: &str) -> Option<usize>;
979+
fn find_last_uncommented(&self, pat: &str) -> Option<usize>;
979980
}
980981

981982
impl FindUncommented for str {
@@ -1001,6 +1002,19 @@ impl FindUncommented for str {
10011002
None => Some(self.len() - pat.len()),
10021003
}
10031004
}
1005+
1006+
fn find_last_uncommented(&self, pat: &str) -> Option<usize> {
1007+
if let Some(left) = self.find_uncommented(pat) {
1008+
let mut result = left;
1009+
// add 1 to use find_last_uncommented for &str after pat
1010+
while let Some(next) = self[(result + 1)..].find_last_uncommented(pat) {
1011+
result += next + 1;
1012+
}
1013+
Some(result)
1014+
} else {
1015+
None
1016+
}
1017+
}
10041018
}
10051019

10061020
// Returns the first byte position after the first comment. The given string
@@ -1882,6 +1896,16 @@ mod test {
18821896
check("\"/* abc", "abc", Some(4));
18831897
}
18841898

1899+
#[test]
1900+
fn test_find_last_uncommented() {
1901+
fn check(haystack: &str, needle: &str, expected: Option<usize>) {
1902+
assert_eq!(expected, haystack.find_last_uncommented(needle));
1903+
}
1904+
check("foo test bar test", "test", Some(13));
1905+
check("test,", "test", Some(0));
1906+
check("nothing", "test", None);
1907+
}
1908+
18851909
#[test]
18861910
fn test_filter_normal_code() {
18871911
let s = r#"

src/expr.rs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1881,14 +1881,13 @@ pub(crate) fn rewrite_assign_rhs<S: Into<String>, R: Rewrite>(
18811881
rewrite_assign_rhs_with(context, lhs, ex, shape, RhsTactics::Default)
18821882
}
18831883

1884-
pub(crate) fn rewrite_assign_rhs_with<S: Into<String>, R: Rewrite>(
1884+
pub(crate) fn rewrite_assign_rhs_expr<R: Rewrite>(
18851885
context: &RewriteContext<'_>,
1886-
lhs: S,
1886+
lhs: &str,
18871887
ex: &R,
18881888
shape: Shape,
18891889
rhs_tactics: RhsTactics,
18901890
) -> Option<String> {
1891-
let lhs = lhs.into();
18921891
let last_line_width = last_line_width(&lhs).saturating_sub(if lhs.contains('\n') {
18931892
shape.indent.width()
18941893
} else {
@@ -1900,13 +1899,31 @@ pub(crate) fn rewrite_assign_rhs_with<S: Into<String>, R: Rewrite>(
19001899
offset: shape.offset + last_line_width + 1,
19011900
..shape
19021901
});
1903-
let rhs = choose_rhs(
1902+
let has_rhs_comment = if let Some(offset) = lhs.find_last_uncommented("=") {
1903+
lhs.trim_end().len() > offset + 1
1904+
} else {
1905+
false
1906+
};
1907+
1908+
choose_rhs(
19041909
context,
19051910
ex,
19061911
orig_shape,
19071912
ex.rewrite(context, orig_shape),
19081913
rhs_tactics,
1909-
)?;
1914+
has_rhs_comment,
1915+
)
1916+
}
1917+
1918+
pub(crate) fn rewrite_assign_rhs_with<S: Into<String>, R: Rewrite>(
1919+
context: &RewriteContext<'_>,
1920+
lhs: S,
1921+
ex: &R,
1922+
shape: Shape,
1923+
rhs_tactics: RhsTactics,
1924+
) -> Option<String> {
1925+
let lhs = lhs.into();
1926+
let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_tactics)?;
19101927
Some(lhs + &rhs)
19111928
}
19121929

@@ -1916,6 +1933,7 @@ fn choose_rhs<R: Rewrite>(
19161933
shape: Shape,
19171934
orig_rhs: Option<String>,
19181935
rhs_tactics: RhsTactics,
1936+
has_rhs_comment: bool,
19191937
) -> Option<String> {
19201938
match orig_rhs {
19211939
Some(ref new_str)
@@ -1932,13 +1950,14 @@ fn choose_rhs<R: Rewrite>(
19321950
.indent
19331951
.block_indent(context.config)
19341952
.to_string_with_newline(context.config);
1953+
let before_space_str = if has_rhs_comment { "" } else { " " };
19351954

19361955
match (orig_rhs, new_rhs) {
19371956
(Some(ref orig_rhs), Some(ref new_rhs))
19381957
if wrap_str(new_rhs.clone(), context.config.max_width(), new_shape)
19391958
.is_none() =>
19401959
{
1941-
Some(format!(" {}", orig_rhs))
1960+
Some(format!("{}{}", before_space_str, orig_rhs))
19421961
}
19431962
(Some(ref orig_rhs), Some(ref new_rhs))
19441963
if prefer_next_line(orig_rhs, new_rhs, rhs_tactics) =>
@@ -1948,10 +1967,11 @@ fn choose_rhs<R: Rewrite>(
19481967
(None, Some(ref new_rhs)) => Some(format!("{}{}", new_indent_str, new_rhs)),
19491968
(None, None) if rhs_tactics == RhsTactics::AllowOverflow => {
19501969
let shape = shape.infinite_width();
1951-
expr.rewrite(context, shape).map(|s| format!(" {}", s))
1970+
expr.rewrite(context, shape)
1971+
.map(|s| format!("{}{}", before_space_str, s))
19521972
}
19531973
(None, None) => None,
1954-
(Some(orig_rhs), _) => Some(format!(" {}", orig_rhs)),
1974+
(Some(orig_rhs), _) => Some(format!("{}{}", before_space_str, orig_rhs)),
19551975
}
19561976
}
19571977
}

src/items.rs

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ use crate::comment::{
1818
use crate::config::lists::*;
1919
use crate::config::{BraceStyle, Config, IndentStyle, Version};
2020
use crate::expr::{
21-
is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, RhsTactics,
21+
is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_expr,
22+
rewrite_assign_rhs_with, RhsTactics,
2223
};
2324
use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
2425
use crate::macros::{rewrite_macro, MacroPosition};
@@ -111,10 +112,67 @@ impl Rewrite for ast::Local {
111112
result.push_str(&infix);
112113

113114
if let Some(ref ex) = self.init {
115+
let base_span = if let Some(ref ty) = self.ty {
116+
mk_sp(ty.span.hi(), self.span.hi())
117+
} else {
118+
mk_sp(self.pat.span.hi(), self.span.hi())
119+
};
120+
121+
if let Some(offset) = context.snippet(base_span).find_uncommented("=") {
122+
let base_span_lo = base_span.lo();
123+
124+
let assign_lo = base_span_lo + BytePos(offset as u32);
125+
let comment_start_pos = if let Some(ref ty) = self.ty {
126+
ty.span.hi()
127+
} else {
128+
self.pat.span.hi()
129+
};
130+
let comment_before_assign =
131+
context.snippet(mk_sp(comment_start_pos, assign_lo)).trim();
132+
133+
let assign_hi = base_span_lo + BytePos((offset + 1) as u32);
134+
let rhs_span_lo = ex.span.lo();
135+
let comment_end_pos = if ex.attrs.is_empty() {
136+
rhs_span_lo
137+
} else {
138+
let attr_span_lo = ex.attrs.first().unwrap().span.lo();
139+
// for the case using block
140+
// ex. let x = { #![my_attr]do_something(); }
141+
if rhs_span_lo < attr_span_lo {
142+
rhs_span_lo
143+
} else {
144+
attr_span_lo
145+
}
146+
};
147+
let comment_after_assign =
148+
context.snippet(mk_sp(assign_hi, comment_end_pos)).trim();
149+
150+
if !comment_before_assign.is_empty() {
151+
let new_indent_str = &pat_shape
152+
.block_indent(0)
153+
.to_string_with_newline(context.config);
154+
result = format!("{}{}{}", comment_before_assign, new_indent_str, result);
155+
}
156+
157+
if !comment_after_assign.is_empty() {
158+
let new_indent_str =
159+
&shape.block_indent(0).to_string_with_newline(context.config);
160+
result.push_str(new_indent_str);
161+
result.push_str(comment_after_assign);
162+
result.push_str(new_indent_str);
163+
}
164+
}
165+
114166
// 1 = trailing semicolon;
115167
let nested_shape = shape.sub_width(1)?;
116-
117-
result = rewrite_assign_rhs(context, result, &**ex, nested_shape)?;
168+
let rhs = rewrite_assign_rhs_expr(
169+
context,
170+
&result,
171+
&**ex,
172+
nested_shape,
173+
RhsTactics::Default,
174+
)?;
175+
result = result + &rhs;
118176
}
119177

120178
result.push(';');

tests/source/issue-3851.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
fn main() {
2+
let before
3+
// before_comment
4+
=
5+
if true {
6+
1.0
7+
};
8+
9+
let after =
10+
// after_comment
11+
if true {
12+
1.0
13+
};
14+
15+
let both
16+
// before_comment
17+
=
18+
// after_comment
19+
if true {
20+
1.0
21+
};
22+
}

tests/target/issue-3851.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
fn main() {
2+
// before_comment
3+
let before = if true {
4+
1.0
5+
};
6+
7+
let after =
8+
// after_comment
9+
if true {
10+
1.0
11+
};
12+
13+
// before_comment
14+
let both =
15+
// after_comment
16+
if true {
17+
1.0
18+
};
19+
}

0 commit comments

Comments
 (0)