Skip to content

Commit 129e2f1

Browse files
committed
Merge pull request #96 from marcusklaas/find-uncommented
Deal with problematic characters in comments
2 parents c7ecf74 + b17c920 commit 129e2f1

File tree

3 files changed

+76
-12
lines changed

3 files changed

+76
-12
lines changed

src/items.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// Formatting top-level items - functions, structs, enums, traits, impls.
1212

1313
use {ReturnIndent, BraceStyle};
14-
use utils::{format_visibility, make_indent};
14+
use utils::{format_visibility, make_indent, FindUncommented};
1515
use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic};
1616
use visitor::FmtVisitor;
1717
use syntax::{ast, abi};
@@ -336,12 +336,11 @@ impl<'a> FmtVisitor<'a> {
336336
// FIXME If you thought the crap with the commas was ugly, just wait.
337337
// This is awful. We're going to look from the last item span to the
338338
// start of the return type span, then we drop everything after the
339-
// first closing paren. Obviously, this will break if there is a
340-
// closing paren in the comment.
339+
// first closing paren.
341340
// The fix is comments in the AST or a span for the closing paren.
342341
let snippet = self.snippet(codemap::mk_sp(prev_end, next_span_start));
343342
let snippet = snippet.trim();
344-
let snippet = &snippet[..snippet.find(terminator).unwrap_or(snippet.len())];
343+
let snippet = &snippet[..snippet.find_uncommented(terminator).unwrap_or(snippet.len())];
345344
let snippet = snippet.trim();
346345
result.push(snippet.to_owned());
347346

@@ -417,8 +416,7 @@ impl<'a> FmtVisitor<'a> {
417416
self.changes.push_str_span(span, &header_str);
418417

419418
let enum_snippet = self.snippet(span);
420-
// FIXME this will give incorrect results if there is a { in a comment.
421-
let body_start = span.lo + BytePos(enum_snippet.find('{').unwrap() as u32 + 1);
419+
let body_start = span.lo + BytePos(enum_snippet.find_uncommented("{").unwrap() as u32 + 1);
422420
let generics_str = self.format_generics(generics, body_start);
423421
self.changes.push_str_span(span, &generics_str);
424422

@@ -542,8 +540,8 @@ impl<'a> FmtVisitor<'a> {
542540
self.changes.push_str_span(span, &generics_str);
543541

544542
let struct_snippet = self.snippet(span);
545-
// FIXME this will give incorrect results if there is a { in a comment.
546-
self.last_pos = span.lo + BytePos(struct_snippet.find('{').unwrap() as u32 + 1);
543+
// This will drop the comment in between the header and body.
544+
self.last_pos = span.lo + BytePos(struct_snippet.find_uncommented("{").unwrap() as u32 + 1);
547545

548546
self.block_indent += config!(tab_spaces);
549547
for (i, f) in struct_def.fields.iter().enumerate() {
@@ -632,8 +630,7 @@ impl<'a> FmtVisitor<'a> {
632630
// This hack makes sure we only add comments etc. after the comma, and
633631
// makes sure we don't repeat any commas.
634632
let hi = field.span.hi;
635-
// FIXME a comma in a comment will break this hack.
636-
let comma_pos = match struct_snippet[(hi.0 - struct_start.0) as usize..].find(',') {
633+
let comma_pos = match struct_snippet[(hi.0 - struct_start.0) as usize..].find_uncommented(",") {
637634
Some(i) => i,
638635
None => 0,
639636
};

src/utils.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,72 @@
1010

1111
use syntax::ast::Visibility;
1212

13+
pub trait FindUncommented {
14+
fn find_uncommented(&self, pat: &str) -> Option<usize>;
15+
}
16+
17+
impl FindUncommented for str {
18+
fn find_uncommented(&self, pat: &str) -> Option<usize> {
19+
let mut needle_iter = pat.chars();
20+
let mut possible_comment = false;
21+
22+
for (i, b) in self.char_indices() {
23+
match needle_iter.next() {
24+
Some(c) => {
25+
if b != c {
26+
needle_iter = pat.chars();
27+
}
28+
},
29+
None => return Some(i - pat.len())
30+
}
31+
32+
if possible_comment {
33+
if b == '/' {
34+
return self[(i+1)..].find('\n')
35+
.and_then(|end| {
36+
self[(end + i + 2)..].find_uncommented(pat)
37+
.map(|idx| idx + end + i + 2)
38+
});
39+
} else if b == '*' {
40+
return self[(i+1)..].find("*/")
41+
.and_then(|end| {
42+
self[(end + i + 3)..].find_uncommented(pat)
43+
.map(|idx| idx + end + i + 3)
44+
});
45+
} else {
46+
possible_comment = false;
47+
}
48+
} else {
49+
possible_comment = b == '/';
50+
}
51+
}
52+
53+
// Handle case where the pattern is a suffix of the search string
54+
match needle_iter.next() {
55+
Some(_) => None,
56+
None => Some(self.len() - pat.len())
57+
}
58+
}
59+
}
60+
61+
#[test]
62+
fn test_find_uncommented() {
63+
fn check(haystack: &str, needle: &str, expected: Option<usize>) {
64+
assert_eq!(expected, haystack.find_uncommented(needle));
65+
}
66+
67+
check("/*//*/test", "test", Some(6));
68+
check("//test\ntest", "test", Some(7));
69+
check("/* comment only */", "whatever", None);
70+
check("/* comment */ some text /* more commentary */ result", "result", Some(46));
71+
check("sup // sup", "p", Some(2));
72+
check("sup", "x", None);
73+
check("π? /**/ π is nice!", "π is nice", Some(9));
74+
check("/*sup yo? \n sup*/ sup", "p", Some(20));
75+
check("hel/*lohello*/lo", "hello", None);
76+
check("acb", "ab", None);
77+
}
78+
1379
#[inline]
1480
pub fn prev_char(s: &str, mut i: usize) -> usize {
1581
if i == 0 { return 0; }
@@ -63,6 +129,7 @@ pub fn round_up_to_power_of_two(mut x: usize) -> usize {
63129
x + 1
64130
}
65131

132+
#[inline]
66133
#[cfg(target_pointer_width="32")]
67134
pub fn round_up_to_power_of_two(mut x: usize) -> usize {
68135
x -= 1;

tests/target/fn.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ fn foo(a: AAAA, b: BBB, c: CCC) -> RetType {
44

55
}
66

7-
fn foo(a: AAAA, b: BBB, c: CCC) -> RetType
7+
fn foo(a: AAAA, b: BBB /* some, weird, inline comment */, c: CCC) -> RetType
88
where T: Blah
99
{
1010

1111
}
1212

13-
fn foo(a: AAA)
13+
fn foo(a: AAA /* (comment) */)
1414
where T: Blah
1515
{
1616

0 commit comments

Comments
 (0)