2012-07-04 22:53:12 +01:00
|
|
|
/*!
|
|
|
|
* Pulls a brief description out of a long description.
|
|
|
|
*
|
|
|
|
* If the first paragraph of a long description is short enough then it
|
|
|
|
* is interpreted as the brief description.
|
|
|
|
*/
|
2012-01-24 17:19:27 -08:00
|
|
|
|
2012-09-18 16:48:40 -07:00
|
|
|
use doc::ItemUtils;
|
2012-07-11 15:00:40 -07:00
|
|
|
|
2012-01-24 17:19:27 -08:00
|
|
|
export mk_pass;
|
|
|
|
|
2012-09-18 16:48:40 -07:00
|
|
|
fn mk_pass() -> Pass {
|
2012-02-27 18:07:16 -08:00
|
|
|
{
|
2012-07-13 22:57:48 -07:00
|
|
|
name: ~"desc_to_brief",
|
2012-02-27 18:07:16 -08:00
|
|
|
f: run
|
|
|
|
}
|
2012-01-24 17:19:27 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn run(
|
2012-09-18 16:48:40 -07:00
|
|
|
_srv: astsrv::Srv,
|
|
|
|
doc: doc::Doc
|
|
|
|
) -> doc::Doc {
|
|
|
|
let fold = fold::Fold({
|
2012-02-17 15:55:30 -08:00
|
|
|
fold_item: fold_item,
|
2012-07-03 16:30:42 -07:00
|
|
|
fold_trait: fold_trait,
|
2012-09-04 13:29:32 -07:00
|
|
|
fold_impl: fold_impl,
|
|
|
|
.. *fold::default_any_fold(())
|
2012-01-24 17:19:27 -08:00
|
|
|
});
|
2012-03-02 18:33:25 -08:00
|
|
|
fold.fold_doc(fold, doc)
|
2012-01-24 17:19:27 -08:00
|
|
|
}
|
|
|
|
|
2012-09-18 16:48:40 -07:00
|
|
|
fn fold_item(fold: fold::Fold<()>, doc: doc::ItemDoc) -> doc::ItemDoc {
|
2012-02-17 15:55:30 -08:00
|
|
|
let doc = fold::default_seq_fold_item(fold, doc);
|
2012-01-24 17:19:27 -08:00
|
|
|
|
2012-01-30 13:05:25 -08:00
|
|
|
{
|
2012-09-04 13:29:32 -07:00
|
|
|
brief: extract(doc.desc),
|
|
|
|
.. doc
|
2012-01-26 22:19:47 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-18 16:48:40 -07:00
|
|
|
fn fold_trait(fold: fold::Fold<()>, doc: doc::TraitDoc) -> doc::TraitDoc {
|
2012-07-03 16:30:42 -07:00
|
|
|
let doc =fold::default_seq_fold_trait(fold, doc);
|
2012-01-30 19:24:06 -08:00
|
|
|
|
|
|
|
{
|
2012-07-14 03:36:35 +10:00
|
|
|
methods: par::map(doc.methods, |doc| {
|
2012-09-04 13:29:32 -07:00
|
|
|
brief: extract(doc.desc),
|
|
|
|
.. doc
|
|
|
|
}),
|
|
|
|
.. doc
|
2012-01-30 19:24:06 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-18 16:48:40 -07:00
|
|
|
fn fold_impl(fold: fold::Fold<()>, doc: doc::ImplDoc) -> doc::ImplDoc {
|
2012-01-31 20:31:52 -08:00
|
|
|
let doc =fold::default_seq_fold_impl(fold, doc);
|
|
|
|
|
|
|
|
{
|
2012-07-14 03:36:35 +10:00
|
|
|
methods: par::map(doc.methods, |doc| {
|
2012-09-04 13:29:32 -07:00
|
|
|
brief: extract(doc.desc),
|
|
|
|
.. doc
|
|
|
|
}),
|
|
|
|
.. doc
|
2012-01-31 20:31:52 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-24 17:19:27 -08:00
|
|
|
#[test]
|
2012-03-09 17:40:40 -08:00
|
|
|
fn should_promote_desc() {
|
2012-07-13 22:57:48 -07:00
|
|
|
let doc = test::mk_doc(~"#[doc = \"desc\"] mod m { }");
|
2012-08-20 12:23:37 -07:00
|
|
|
assert doc.cratemod().mods()[0].brief() == Some(~"desc");
|
2012-01-30 19:24:06 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2012-07-03 16:30:42 -07:00
|
|
|
fn should_promote_trait_method_desc() {
|
2012-07-31 10:27:51 -07:00
|
|
|
let doc = test::mk_doc(~"trait i { #[doc = \"desc\"] fn a(); }");
|
2012-08-20 12:23:37 -07:00
|
|
|
assert doc.cratemod().traits()[0].methods[0].brief == Some(~"desc");
|
2012-01-31 20:31:52 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_promote_impl_method_desc() {
|
|
|
|
let doc = test::mk_doc(
|
2012-08-08 17:19:06 -07:00
|
|
|
~"impl int { #[doc = \"desc\"] fn a() { } }");
|
2012-08-20 12:23:37 -07:00
|
|
|
assert doc.cratemod().impls()[0].methods[0].brief == Some(~"desc");
|
2012-02-01 22:41:41 -08:00
|
|
|
}
|
|
|
|
|
2012-01-31 18:32:37 -08:00
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
2012-09-18 16:48:40 -07:00
|
|
|
fn mk_doc(source: ~str) -> doc::Doc {
|
2012-06-30 16:19:07 -07:00
|
|
|
do astsrv::from_str(source) |srv| {
|
2012-07-13 22:57:48 -07:00
|
|
|
let doc = extract::from_srv(srv, ~"");
|
2012-02-27 18:07:16 -08:00
|
|
|
let doc = attr_pass::mk_pass().f(srv, doc);
|
2012-02-20 21:08:19 -08:00
|
|
|
run(srv, doc)
|
|
|
|
}
|
2012-01-31 18:32:37 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-20 12:23:37 -07:00
|
|
|
fn extract(desc: Option<~str>) -> Option<~str> {
|
2012-03-09 17:40:40 -08:00
|
|
|
if option::is_none(desc) {
|
2012-08-20 12:23:37 -07:00
|
|
|
return None
|
2012-01-24 17:19:27 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
parse_desc(option::get(desc))
|
|
|
|
}
|
|
|
|
|
2012-08-20 12:23:37 -07:00
|
|
|
fn parse_desc(desc: ~str) -> Option<~str> {
|
2012-01-24 17:19:27 -08:00
|
|
|
|
|
|
|
const max_brief_len: uint = 120u;
|
|
|
|
|
2012-08-06 12:34:08 -07:00
|
|
|
match first_sentence(desc) {
|
2012-08-20 12:23:37 -07:00
|
|
|
Some(first_sentence) => {
|
2012-03-09 17:52:06 -08:00
|
|
|
if str::len(first_sentence) <= max_brief_len {
|
2012-08-20 12:23:37 -07:00
|
|
|
Some(first_sentence)
|
2012-01-24 17:19:27 -08:00
|
|
|
} else {
|
2012-08-20 12:23:37 -07:00
|
|
|
None
|
2012-01-24 17:19:27 -08:00
|
|
|
}
|
2012-03-09 17:52:06 -08:00
|
|
|
}
|
2012-08-20 12:23:37 -07:00
|
|
|
None => None
|
2012-03-09 17:52:06 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-20 12:23:37 -07:00
|
|
|
fn first_sentence(s: ~str) -> Option<~str> {
|
2012-03-09 17:52:06 -08:00
|
|
|
let paras = paragraphs(s);
|
|
|
|
if vec::is_not_empty(paras) {
|
2012-03-16 14:50:15 -07:00
|
|
|
let first_para = vec::head(paras);
|
2012-08-20 12:23:37 -07:00
|
|
|
Some(str::replace(first_sentence_(first_para), ~"\n", ~" "))
|
2012-01-24 17:19:27 -08:00
|
|
|
} else {
|
2012-08-20 12:23:37 -07:00
|
|
|
None
|
2012-01-24 17:19:27 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-13 22:57:48 -07:00
|
|
|
fn first_sentence_(s: ~str) -> ~str {
|
2012-03-22 08:39:41 -07:00
|
|
|
let mut dotcount = 0;
|
2012-03-16 14:50:15 -07:00
|
|
|
// The index of the character following a single dot. This allows
|
|
|
|
// Things like [0..1) to appear in the brief description
|
2012-06-30 16:19:07 -07:00
|
|
|
let idx = do str::find(s) |ch| {
|
2012-03-16 14:50:15 -07:00
|
|
|
if ch == '.' {
|
|
|
|
dotcount += 1;
|
|
|
|
false
|
|
|
|
} else {
|
|
|
|
if dotcount == 1 {
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
dotcount = 0;
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2012-08-06 12:34:08 -07:00
|
|
|
match idx {
|
2012-08-20 12:23:37 -07:00
|
|
|
Some(idx) if idx > 2u => {
|
2012-03-16 14:50:15 -07:00
|
|
|
str::slice(s, 0u, idx - 1u)
|
|
|
|
}
|
2012-08-03 19:59:04 -07:00
|
|
|
_ => {
|
2012-07-13 22:57:48 -07:00
|
|
|
if str::ends_with(s, ~".") {
|
2012-03-16 14:50:15 -07:00
|
|
|
str::slice(s, 0u, str::len(s))
|
|
|
|
} else {
|
|
|
|
s
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-09 17:52:06 -08:00
|
|
|
}
|
|
|
|
|
2012-07-13 22:57:48 -07:00
|
|
|
fn paragraphs(s: ~str) -> ~[~str] {
|
2012-01-24 17:19:27 -08:00
|
|
|
let lines = str::lines_any(s);
|
2012-03-22 08:39:41 -07:00
|
|
|
let mut whitespace_lines = 0;
|
2012-07-13 22:57:48 -07:00
|
|
|
let mut accum = ~"";
|
2012-06-30 16:19:07 -07:00
|
|
|
let paras = do vec::foldl(~[], lines) |paras, line| {
|
2012-03-22 08:39:41 -07:00
|
|
|
let mut res = paras;
|
2012-01-24 17:19:27 -08:00
|
|
|
|
|
|
|
if str::is_whitespace(line) {
|
|
|
|
whitespace_lines += 1;
|
|
|
|
} else {
|
|
|
|
if whitespace_lines > 0 {
|
|
|
|
if str::is_not_empty(accum) {
|
2012-06-29 16:26:56 -07:00
|
|
|
res += ~[accum];
|
2012-07-13 22:57:48 -07:00
|
|
|
accum = ~"";
|
2012-01-24 17:19:27 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
whitespace_lines = 0;
|
|
|
|
|
|
|
|
accum = if str::is_empty(accum) {
|
|
|
|
line
|
|
|
|
} else {
|
2012-07-13 22:57:48 -07:00
|
|
|
accum + ~"\n" + line
|
2012-01-24 17:19:27 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
res
|
|
|
|
};
|
|
|
|
|
|
|
|
if str::is_not_empty(accum) {
|
2012-06-29 16:26:56 -07:00
|
|
|
paras + ~[accum]
|
2012-01-24 17:19:27 -08:00
|
|
|
} else {
|
|
|
|
paras
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_paragraphs_1() {
|
2012-07-13 22:57:48 -07:00
|
|
|
let paras = paragraphs(~"1\n\n2");
|
|
|
|
assert paras == ~[~"1", ~"2"];
|
2012-01-24 17:19:27 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_paragraphs_2() {
|
2012-07-13 22:57:48 -07:00
|
|
|
let paras = paragraphs(~"\n\n1\n1\n\n2\n\n");
|
|
|
|
assert paras == ~[~"1\n1", ~"2"];
|
2012-01-24 17:19:27 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_promote_short_descs() {
|
2012-08-20 12:23:37 -07:00
|
|
|
let desc = Some(~"desc");
|
2012-03-09 17:40:40 -08:00
|
|
|
let brief = extract(desc);
|
|
|
|
assert brief == desc;
|
2012-01-24 17:19:27 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_not_promote_long_descs() {
|
2012-08-20 12:23:37 -07:00
|
|
|
let desc = Some(~"Warkworth Castle is a ruined medieval building
|
2012-03-09 17:52:06 -08:00
|
|
|
in the town of the same name in the English county of Northumberland,
|
|
|
|
and the town and castle occupy a loop of the River Coquet, less than a mile
|
2012-01-24 17:19:27 -08:00
|
|
|
from England's north-east coast. When the castle was founded is uncertain,
|
|
|
|
but traditionally its construction has been ascribed to Prince Henry of
|
|
|
|
Scotland in the mid 12th century, although it may have been built by
|
|
|
|
King Henry II of England when he took control of England'snorthern
|
|
|
|
counties.");
|
2012-03-09 17:40:40 -08:00
|
|
|
let brief = extract(desc);
|
2012-08-20 12:23:37 -07:00
|
|
|
assert brief == None;
|
2012-01-24 17:19:27 -08:00
|
|
|
}
|
2012-03-09 17:52:06 -08:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_promote_first_sentence() {
|
2012-08-20 12:23:37 -07:00
|
|
|
let desc = Some(~"Warkworth Castle is a ruined medieval building
|
2012-03-09 17:52:06 -08:00
|
|
|
in the town. of the same name in the English county of Northumberland,
|
|
|
|
and the town and castle occupy a loop of the River Coquet, less than a mile
|
|
|
|
from England's north-east coast. When the castle was founded is uncertain,
|
|
|
|
but traditionally its construction has been ascribed to Prince Henry of
|
|
|
|
Scotland in the mid 12th century, although it may have been built by
|
|
|
|
King Henry II of England when he took control of England'snorthern
|
|
|
|
counties.");
|
|
|
|
let brief = extract(desc);
|
2012-08-20 12:23:37 -07:00
|
|
|
assert brief == Some(
|
2012-07-13 22:57:48 -07:00
|
|
|
~"Warkworth Castle is a ruined medieval building in the town");
|
2012-03-16 14:50:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_not_consider_double_period_to_end_sentence() {
|
2012-08-20 12:23:37 -07:00
|
|
|
let desc = Some(~"Warkworth..Castle is a ruined medieval building
|
2012-03-16 14:50:15 -07:00
|
|
|
in the town. of the same name in the English county of Northumberland,
|
|
|
|
and the town and castle occupy a loop of the River Coquet, less than a mile
|
|
|
|
from England's north-east coast. When the castle was founded is uncertain,
|
|
|
|
but traditionally its construction has been ascribed to Prince Henry of
|
|
|
|
Scotland in the mid 12th century, although it may have been built by
|
|
|
|
King Henry II of England when he took control of England'snorthern
|
|
|
|
counties.");
|
|
|
|
let brief = extract(desc);
|
2012-08-20 12:23:37 -07:00
|
|
|
assert brief == Some(
|
2012-07-13 22:57:48 -07:00
|
|
|
~"Warkworth..Castle is a ruined medieval building in the town");
|
2012-03-16 14:50:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn should_not_consider_triple_period_to_end_sentence() {
|
2012-08-20 12:23:37 -07:00
|
|
|
let desc = Some(~"Warkworth... Castle is a ruined medieval building
|
2012-03-16 14:50:15 -07:00
|
|
|
in the town. of the same name in the English county of Northumberland,
|
|
|
|
and the town and castle occupy a loop of the River Coquet, less than a mile
|
|
|
|
from England's north-east coast. When the castle was founded is uncertain,
|
|
|
|
but traditionally its construction has been ascribed to Prince Henry of
|
|
|
|
Scotland in the mid 12th century, although it may have been built by
|
|
|
|
King Henry II of England when he took control of England'snorthern
|
|
|
|
counties.");
|
|
|
|
let brief = extract(desc);
|
2012-08-20 12:23:37 -07:00
|
|
|
assert brief == Some(
|
2012-07-13 22:57:48 -07:00
|
|
|
~"Warkworth... Castle is a ruined medieval building in the town");
|
2012-03-16 14:50:15 -07:00
|
|
|
}
|