Merge pull request #96 from marcusklaas/find-uncommented

Deal with problematic characters in comments
This commit is contained in:
Nick Cameron 2015-06-16 09:45:01 +12:00
commit 129e2f12e4
3 changed files with 76 additions and 12 deletions

View File

@ -11,7 +11,7 @@
// Formatting top-level items - functions, structs, enums, traits, impls.
use {ReturnIndent, BraceStyle};
use utils::{format_visibility, make_indent};
use utils::{format_visibility, make_indent, FindUncommented};
use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic};
use visitor::FmtVisitor;
use syntax::{ast, abi};
@ -336,12 +336,11 @@ impl<'a> FmtVisitor<'a> {
// FIXME If you thought the crap with the commas was ugly, just wait.
// This is awful. We're going to look from the last item span to the
// start of the return type span, then we drop everything after the
// first closing paren. Obviously, this will break if there is a
// closing paren in the comment.
// first closing paren.
// The fix is comments in the AST or a span for the closing paren.
let snippet = self.snippet(codemap::mk_sp(prev_end, next_span_start));
let snippet = snippet.trim();
let snippet = &snippet[..snippet.find(terminator).unwrap_or(snippet.len())];
let snippet = &snippet[..snippet.find_uncommented(terminator).unwrap_or(snippet.len())];
let snippet = snippet.trim();
result.push(snippet.to_owned());
@ -417,8 +416,7 @@ impl<'a> FmtVisitor<'a> {
self.changes.push_str_span(span, &header_str);
let enum_snippet = self.snippet(span);
// FIXME this will give incorrect results if there is a { in a comment.
let body_start = span.lo + BytePos(enum_snippet.find('{').unwrap() as u32 + 1);
let body_start = span.lo + BytePos(enum_snippet.find_uncommented("{").unwrap() as u32 + 1);
let generics_str = self.format_generics(generics, body_start);
self.changes.push_str_span(span, &generics_str);
@ -542,8 +540,8 @@ impl<'a> FmtVisitor<'a> {
self.changes.push_str_span(span, &generics_str);
let struct_snippet = self.snippet(span);
// FIXME this will give incorrect results if there is a { in a comment.
self.last_pos = span.lo + BytePos(struct_snippet.find('{').unwrap() as u32 + 1);
// This will drop the comment in between the header and body.
self.last_pos = span.lo + BytePos(struct_snippet.find_uncommented("{").unwrap() as u32 + 1);
self.block_indent += config!(tab_spaces);
for (i, f) in struct_def.fields.iter().enumerate() {
@ -632,8 +630,7 @@ impl<'a> FmtVisitor<'a> {
// This hack makes sure we only add comments etc. after the comma, and
// makes sure we don't repeat any commas.
let hi = field.span.hi;
// FIXME a comma in a comment will break this hack.
let comma_pos = match struct_snippet[(hi.0 - struct_start.0) as usize..].find(',') {
let comma_pos = match struct_snippet[(hi.0 - struct_start.0) as usize..].find_uncommented(",") {
Some(i) => i,
None => 0,
};

View File

@ -10,6 +10,72 @@
use syntax::ast::Visibility;
pub trait FindUncommented {
fn find_uncommented(&self, pat: &str) -> Option<usize>;
}
impl FindUncommented for str {
fn find_uncommented(&self, pat: &str) -> Option<usize> {
let mut needle_iter = pat.chars();
let mut possible_comment = false;
for (i, b) in self.char_indices() {
match needle_iter.next() {
Some(c) => {
if b != c {
needle_iter = pat.chars();
}
},
None => return Some(i - pat.len())
}
if possible_comment {
if b == '/' {
return self[(i+1)..].find('\n')
.and_then(|end| {
self[(end + i + 2)..].find_uncommented(pat)
.map(|idx| idx + end + i + 2)
});
} else if b == '*' {
return self[(i+1)..].find("*/")
.and_then(|end| {
self[(end + i + 3)..].find_uncommented(pat)
.map(|idx| idx + end + i + 3)
});
} else {
possible_comment = false;
}
} else {
possible_comment = b == '/';
}
}
// Handle case where the pattern is a suffix of the search string
match needle_iter.next() {
Some(_) => None,
None => Some(self.len() - pat.len())
}
}
}
#[test]
fn test_find_uncommented() {
fn check(haystack: &str, needle: &str, expected: Option<usize>) {
assert_eq!(expected, haystack.find_uncommented(needle));
}
check("/*//*/test", "test", Some(6));
check("//test\ntest", "test", Some(7));
check("/* comment only */", "whatever", None);
check("/* comment */ some text /* more commentary */ result", "result", Some(46));
check("sup // sup", "p", Some(2));
check("sup", "x", None);
check("π? /**/ π is nice!", "π is nice", Some(9));
check("/*sup yo? \n sup*/ sup", "p", Some(20));
check("hel/*lohello*/lo", "hello", None);
check("acb", "ab", None);
}
#[inline]
pub fn prev_char(s: &str, mut i: usize) -> usize {
if i == 0 { return 0; }
@ -63,6 +129,7 @@ pub fn round_up_to_power_of_two(mut x: usize) -> usize {
x + 1
}
#[inline]
#[cfg(target_pointer_width="32")]
pub fn round_up_to_power_of_two(mut x: usize) -> usize {
x -= 1;

View File

@ -4,13 +4,13 @@ fn foo(a: AAAA, b: BBB, c: CCC) -> RetType {
}
fn foo(a: AAAA, b: BBB, c: CCC) -> RetType
fn foo(a: AAAA, b: BBB /* some, weird, inline comment */, c: CCC) -> RetType
where T: Blah
{
}
fn foo(a: AAA)
fn foo(a: AAA /* (comment) */)
where T: Blah
{