2012-12-03 16:48:01 -08:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// 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
|
|
|
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
|
|
|
|
2013-01-08 19:37:25 -08:00
|
|
|
use core::prelude::*;
|
|
|
|
|
2012-12-23 17:41:37 -05:00
|
|
|
use astsrv;
|
2012-09-18 16:48:40 -07:00
|
|
|
use doc::ItemUtils;
|
2012-12-23 17:41:37 -05:00
|
|
|
use doc;
|
2012-12-05 15:06:54 -08:00
|
|
|
use fold::Fold;
|
2012-12-23 17:41:37 -05:00
|
|
|
use fold;
|
2013-01-08 19:37:25 -08:00
|
|
|
use pass::Pass;
|
2012-12-23 17:41:37 -05:00
|
|
|
|
|
|
|
use core::str;
|
|
|
|
use core::vec;
|
2013-01-10 10:59:58 -08:00
|
|
|
use core::util;
|
2012-07-11 15:00:40 -07:00
|
|
|
|
2012-11-19 18:00:12 -08:00
|
|
|
pub fn mk_pass() -> Pass {
|
2013-01-08 14:00:45 -08:00
|
|
|
Pass {
|
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
|
|
|
}
|
|
|
|
|
2013-01-08 19:37:25 -08:00
|
|
|
pub fn run(
|
2012-09-18 16:48:40 -07:00
|
|
|
_srv: astsrv::Srv,
|
2013-01-30 19:32:36 -08:00
|
|
|
doc: doc::Doc
|
2012-09-18 16:48:40 -07:00
|
|
|
) -> doc::Doc {
|
2012-12-05 15:06:54 -08:00
|
|
|
let 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,
|
2012-12-05 15:06:54 -08:00
|
|
|
.. fold::default_any_fold(())
|
|
|
|
};
|
2012-11-29 17:51:16 -08:00
|
|
|
(fold.fold_doc)(&fold, doc)
|
2012-01-24 17:19:27 -08:00
|
|
|
}
|
|
|
|
|
2013-01-30 19:32:36 -08: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
|
|
|
|
2013-01-25 16:57:39 -08:00
|
|
|
doc::ItemDoc {
|
2013-01-30 18:52:31 -08:00
|
|
|
brief: extract(copy doc.desc),
|
2012-09-04 13:29:32 -07:00
|
|
|
.. doc
|
2012-01-26 22:19:47 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 19:32:36 -08: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
|
|
|
|
2013-01-25 16:57:39 -08:00
|
|
|
doc::TraitDoc {
|
2013-01-31 17:12:29 -08:00
|
|
|
methods: doc.methods.map(|doc| doc::MethodDoc {
|
2013-01-30 18:52:31 -08:00
|
|
|
brief: extract(copy doc.desc),
|
2013-01-30 13:14:35 -08:00
|
|
|
.. copy *doc
|
2012-09-04 13:29:32 -07:00
|
|
|
}),
|
|
|
|
.. doc
|
2012-01-30 19:24:06 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 19:32:36 -08: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);
|
|
|
|
|
2013-01-25 16:57:39 -08:00
|
|
|
doc::ImplDoc {
|
2013-01-31 17:12:29 -08:00
|
|
|
methods: doc.methods.map(|doc| doc::MethodDoc {
|
2013-01-30 18:52:31 -08:00
|
|
|
brief: extract(copy doc.desc),
|
2013-01-30 13:14:35 -08:00
|
|
|
.. copy *doc
|
2012-09-04 13:29:32 -07:00
|
|
|
}),
|
|
|
|
.. 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)]
|
2013-01-08 19:37:25 -08:00
|
|
|
pub mod test {
|
2012-12-29 17:38:20 -08:00
|
|
|
use astsrv;
|
|
|
|
use attr_pass;
|
2013-01-08 19:37:25 -08:00
|
|
|
use desc_to_brief_pass::run;
|
2012-12-29 17:38:20 -08:00
|
|
|
use doc;
|
|
|
|
use extract;
|
|
|
|
|
2013-01-30 19:32:36 -08:00
|
|
|
pub fn mk_doc(source: ~str) -> doc::Doc {
|
2013-01-30 13:14:35 -08:00
|
|
|
do astsrv::from_str(copy source) |srv| {
|
2013-01-31 20:24:03 -08:00
|
|
|
let doc = extract::from_srv(srv.clone(), ~"");
|
|
|
|
let doc = (attr_pass::mk_pass().f)(srv.clone(), doc);
|
|
|
|
run(srv.clone(), doc)
|
2012-02-20 21:08:19 -08:00
|
|
|
}
|
2012-01-31 18:32:37 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 19:32:36 -08:00
|
|
|
fn extract(desc: Option<~str>) -> Option<~str> {
|
2012-09-21 19:37:57 -07:00
|
|
|
if desc.is_none() {
|
2012-08-20 12:23:37 -07:00
|
|
|
return None
|
2012-01-24 17:19:27 -08:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:14:35 -08:00
|
|
|
parse_desc((copy desc).get())
|
2012-01-24 17:19:27 -08:00
|
|
|
}
|
|
|
|
|
2013-01-30 19:32:36 -08:00
|
|
|
fn parse_desc(desc: ~str) -> Option<~str> {
|
2012-01-24 17:19:27 -08:00
|
|
|
|
|
|
|
const max_brief_len: uint = 120u;
|
|
|
|
|
2013-01-30 13:14:35 -08:00
|
|
|
match first_sentence(copy 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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 19:32:36 -08:00
|
|
|
fn first_sentence(s: ~str) -> Option<~str> {
|
2013-01-30 13:14:35 -08:00
|
|
|
let paras = paragraphs(copy s);
|
2013-01-24 23:24:57 -05:00
|
|
|
if !paras.is_empty() {
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 19:32:36 -08: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 {
|
2013-01-30 13:14:35 -08:00
|
|
|
copy s
|
2012-03-16 14:50:15 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-09 17:52:06 -08:00
|
|
|
}
|
|
|
|
|
2013-01-30 19:32:36 -08: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
|
|
|
|
2012-09-27 22:20:47 -07:00
|
|
|
if str::is_whitespace(*line) {
|
2012-01-24 17:19:27 -08:00
|
|
|
whitespace_lines += 1;
|
|
|
|
} else {
|
|
|
|
if whitespace_lines > 0 {
|
2013-01-24 23:24:57 -05:00
|
|
|
if !accum.is_empty() {
|
2013-01-10 10:59:58 -08:00
|
|
|
let v = util::replace(&mut accum, ~"");
|
|
|
|
res.push(v);
|
2012-01-24 17:19:27 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
whitespace_lines = 0;
|
|
|
|
|
|
|
|
accum = if str::is_empty(accum) {
|
2013-01-30 13:14:35 -08:00
|
|
|
copy *line
|
2012-01-24 17:19:27 -08:00
|
|
|
} else {
|
2012-09-27 22:20:47 -07:00
|
|
|
accum + ~"\n" + *line
|
2012-01-24 17:19:27 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
res
|
|
|
|
};
|
|
|
|
|
2013-01-24 23:24:57 -05:00
|
|
|
if !accum.is_empty() {
|
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");
|
2013-01-30 18:52:31 -08:00
|
|
|
let brief = extract(copy desc);
|
2012-03-09 17:40:40 -08:00
|
|
|
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
|
|
|
}
|