2013-05-30 03:16:33 -07:00
|
|
|
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 16:48:01 -08:00
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2012-07-04 22:53:12 +01:00
|
|
|
/*!
|
2012-09-20 16:09:46 -07:00
|
|
|
Removes the common level of indention from description strings. For
|
|
|
|
instance, if an entire doc comment is indented 8 spaces we want to
|
|
|
|
remove those 8 spaces from every line.
|
|
|
|
|
|
|
|
The first line of a string is allowed to be intend less than
|
|
|
|
subsequent lines in the same paragraph in order to account for
|
|
|
|
instances where the string containing the doc comment is opened in the
|
|
|
|
middle of a line, and each of the following lines is indented.
|
|
|
|
*/
|
2012-01-24 22:02:36 -08:00
|
|
|
|
2013-05-17 15:28:44 -07:00
|
|
|
use core::prelude::*;
|
|
|
|
|
2013-06-08 15:12:39 +10:00
|
|
|
use core::iterator::IteratorUtil;
|
2013-05-24 19:35:29 -07:00
|
|
|
use core::str;
|
|
|
|
use core::uint;
|
2013-01-08 19:37:25 -08:00
|
|
|
use pass::Pass;
|
2012-12-23 17:41:37 -05:00
|
|
|
use text_pass;
|
|
|
|
|
2012-11-19 18:00:12 -08:00
|
|
|
pub fn mk_pass() -> Pass {
|
2012-07-13 22:57:48 -07:00
|
|
|
text_pass::mk_pass(~"unindent", unindent)
|
2012-01-24 22:02:36 -08:00
|
|
|
}
|
|
|
|
|
2013-01-30 18:52:31 -08:00
|
|
|
fn unindent(s: &str) -> ~str {
|
2013-03-26 04:39:10 +01:00
|
|
|
let mut lines = ~[];
|
|
|
|
for str::each_line_any(s) |line| { lines.push(line.to_owned()); }
|
2012-03-22 08:39:41 -07:00
|
|
|
let mut saw_first_line = false;
|
|
|
|
let mut saw_second_line = false;
|
2013-06-08 15:12:39 +10:00
|
|
|
let min_indent = do lines.iter().fold(uint::max_value)
|
2012-06-30 16:19:07 -07:00
|
|
|
|min_indent, line| {
|
2012-01-24 22:02:36 -08:00
|
|
|
|
|
|
|
// After we see the first non-whitespace line, look at
|
|
|
|
// the line we have. If it is not whitespace, and therefore
|
|
|
|
// part of the first paragraph, then ignore the indentation
|
|
|
|
// level of the first line
|
|
|
|
let ignore_previous_indents =
|
|
|
|
saw_first_line &&
|
|
|
|
!saw_second_line &&
|
2012-09-27 22:20:47 -07:00
|
|
|
!str::is_whitespace(*line);
|
2012-01-24 22:02:36 -08:00
|
|
|
|
|
|
|
let min_indent = if ignore_previous_indents {
|
|
|
|
uint::max_value
|
|
|
|
} else {
|
|
|
|
min_indent
|
|
|
|
};
|
|
|
|
|
|
|
|
if saw_first_line {
|
|
|
|
saw_second_line = true;
|
|
|
|
}
|
|
|
|
|
2012-09-27 22:20:47 -07:00
|
|
|
if str::is_whitespace(*line) {
|
2012-01-24 22:02:36 -08:00
|
|
|
min_indent
|
|
|
|
} else {
|
|
|
|
saw_first_line = true;
|
2012-08-30 12:54:50 -07:00
|
|
|
let mut spaces = 0;
|
2013-06-10 00:34:23 +10:00
|
|
|
do line.iter().all |char| {
|
2012-01-24 22:02:36 -08:00
|
|
|
// Only comparing against space because I wouldn't
|
|
|
|
// know what to do with mixed whitespace chars
|
|
|
|
if char == ' ' {
|
2012-08-30 12:54:50 -07:00
|
|
|
spaces += 1;
|
2012-01-24 22:02:36 -08:00
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
};
|
2012-08-30 12:54:50 -07:00
|
|
|
uint::min(min_indent, spaces)
|
2012-01-24 22:02:36 -08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-01-24 23:24:57 -05:00
|
|
|
if !lines.is_empty() {
|
2013-03-21 23:02:27 +01:00
|
|
|
let unindented = ~[lines.head().trim().to_owned()]
|
2013-03-03 07:22:40 -08:00
|
|
|
+ do lines.tail().map |line| {
|
2012-09-28 17:17:20 -07:00
|
|
|
if str::is_whitespace(*line) {
|
2013-01-30 13:14:35 -08:00
|
|
|
copy *line
|
2012-01-24 22:02:36 -08:00
|
|
|
} else {
|
2013-06-10 00:44:58 +10:00
|
|
|
assert!(line.len() >= min_indent);
|
|
|
|
line.slice(min_indent, line.len()).to_owned()
|
2012-01-24 22:02:36 -08:00
|
|
|
}
|
|
|
|
};
|
2013-05-21 22:55:07 +09:00
|
|
|
str::connect(unindented, "\n")
|
2012-01-24 22:02:36 -08:00
|
|
|
} else {
|
2013-01-30 18:52:31 -08:00
|
|
|
s.to_str()
|
2012-01-24 22:02:36 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_unindent() {
|
2012-07-13 22:57:48 -07:00
|
|
|
let s = ~" line1\n line2";
|
2012-01-24 22:02:36 -08:00
|
|
|
let r = unindent(s);
|
2013-05-18 22:02:45 -04:00
|
|
|
assert_eq!(r, ~"line1\nline2");
|
2012-01-24 22:02:36 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_unindent_multiple_paragraphs() {
|
2012-07-13 22:57:48 -07:00
|
|
|
let s = ~" line1\n\n line2";
|
2012-01-24 22:02:36 -08:00
|
|
|
let r = unindent(s);
|
2013-05-18 22:02:45 -04:00
|
|
|
assert_eq!(r, ~"line1\n\nline2");
|
2012-01-24 22:02:36 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_leave_multiple_indent_levels() {
|
|
|
|
// Line 2 is indented another level beyond the
|
|
|
|
// base indentation and should be preserved
|
2012-07-13 22:57:48 -07:00
|
|
|
let s = ~" line1\n\n line2";
|
2012-01-24 22:02:36 -08:00
|
|
|
let r = unindent(s);
|
2013-05-18 22:02:45 -04:00
|
|
|
assert_eq!(r, ~"line1\n\n line2");
|
2012-01-24 22:02:36 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_ignore_first_line_indent() {
|
|
|
|
// Thi first line of the first paragraph may not be indented as
|
|
|
|
// far due to the way the doc string was written:
|
|
|
|
//
|
|
|
|
// #[doc = "Start way over here
|
|
|
|
// and continue here"]
|
2012-07-13 22:57:48 -07:00
|
|
|
let s = ~"line1\n line2";
|
2012-01-24 22:02:36 -08:00
|
|
|
let r = unindent(s);
|
2013-05-18 22:02:45 -04:00
|
|
|
assert_eq!(r, ~"line1\nline2");
|
2012-01-24 22:02:36 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_not_ignore_first_line_indent_in_a_single_line_para() {
|
2012-07-13 22:57:48 -07:00
|
|
|
let s = ~"line1\n\n line2";
|
2012-01-24 22:02:36 -08:00
|
|
|
let r = unindent(s);
|
2013-05-18 22:02:45 -04:00
|
|
|
assert_eq!(r, ~"line1\n\n line2");
|
2012-01-30 20:27:16 -08:00
|
|
|
}
|