]> git.lizzy.rs Git - rust.git/commitdiff
Merge pull request #1631 from j-clark/patch-2
authorBrian Anderson <andersrb@gmail.com>
Tue, 24 Jan 2012 21:57:29 +0000 (13:57 -0800)
committerBrian Anderson <andersrb@gmail.com>
Tue, 24 Jan 2012 21:57:29 +0000 (13:57 -0800)
Added to bad_expr_word_table reserved words

22 files changed:
configure
mk/platform.mk
src/cargo/cargo.rs
src/comp/metadata/cstore.rs
src/libcore/comm.rs
src/libcore/core.rs
src/libcore/ctypes.rs
src/libcore/str.rs
src/libcore/vec.rs
src/rt/rust_unwind.h
src/rustdoc/attr_parser.rs
src/rustdoc/attr_pass.rs
src/rustdoc/doc.rs
src/rustdoc/extract.rs
src/rustdoc/fold.rs
src/rustdoc/gen.rs
src/rustdoc/prune_undoc_pass.rs
src/rustdoc/prune_unexported_pass.rs [new file with mode: 0644]
src/rustdoc/rustdoc.rc
src/rustdoc/rustdoc.rs
src/rustdoc/tystr_pass.rs
src/snapshots.txt

index 5d94b854ea289be547f017de4d968378a04bf8db..1601f46ac1e568c6b9d2bb49db4d661229ffa582 100755 (executable)
--- a/configure
+++ b/configure
@@ -340,7 +340,8 @@ then
     CFG_CLANG_VERSION=$("$CFG_CLANG" \
                       --version \
                       | grep version \
-                      | cut -d ' ' -f 3)
+                      | sed 's/.*\(version .*\)/\1/' \
+                      | cut -d ' ' -f 2)
 
     case $CFG_CLANG_VERSION in
         (3.0svn | 3.0 | 3.1)
index 0018a3bd8e5ffcac827904fd0d34534c821671cb..10cef47e6f02d8efa204b4915f4a2b8695f6bcd4 100644 (file)
@@ -188,7 +188,8 @@ ifeq ($(CFG_C_COMPILER),clang)
   CC=clang
   CXX=clang++
   CPP=cpp
-  CFG_GCCISH_CFLAGS += -Wall -Werror -fno-rtti -g
+  # -Wno-c++11-compat allows us to use 'alignof' as an identifier in the runtime
+  CFG_GCCISH_CFLAGS += -Wall -Werror -Wno-c++11-compat -fno-rtti -g
   CFG_GCCISH_LINK_FLAGS += -g
   CFG_DEPEND_C = $(CFG_GCCISH_CROSS)$(CXX) $(CFG_GCCISH_CFLAGS) -MT "$(1)" \
     -MM $(2)
index e3af32767d3c5aa276cc0a2d83eac452b572ca23..c2b51c15e0466a9c7b3f4d873bba6ebbf592acdd 100644 (file)
@@ -476,6 +476,25 @@ fn install_package(c: cargo, wd: str, pkg: package) {
     }
 }
 
+fn cargo_suggestion(c: cargo, syncing: bool, fallback: fn())
+{
+    if c.sources.size() == 0u {
+        error("No sources defined. You may wish to run " +
+              "\"cargo init\" then \"cargo sync\".");
+        ret;
+    }
+    if !syncing {
+        let npkg = 0u;
+        c.sources.values({ |v| npkg += vec::len(v.packages) });
+        if npkg == 0u {
+            error("No packages known. You may wish to run " +
+                  "\"cargo sync\".");
+            ret;
+        }
+    }
+    fallback();
+}
+
 fn install_uuid(c: cargo, wd: str, uuid: str) {
     let ps = [];
     for_each_package(c, { |s, p|
@@ -489,7 +508,7 @@ fn install_uuid(c: cargo, wd: str, uuid: str) {
         install_package(c, wd, p);
         ret;
     } else if vec::len(ps) == 0u {
-        error("No packages.");
+        cargo_suggestion(c, false, { || error("No packages match uuid."); });
         ret;
     }
     error("Found multiple packages:");
@@ -510,7 +529,7 @@ fn install_named(c: cargo, wd: str, name: str) {
         install_package(c, wd, p);
         ret;
     } else if vec::len(ps) == 0u {
-        error("No packages.");
+        cargo_suggestion(c, false, { || error("No packages match name."); });
         ret;
     }
     error("Found multiple packages:");
@@ -651,6 +670,7 @@ fn cmd_sync(c: cargo, argv: [str]) {
     if vec::len(argv) == 3u {
         sync_one(c, argv[2], c.sources.get(argv[2]));
     } else {
+        cargo_suggestion(c, true, { || } );
         c.sources.items { |k, v|
             sync_one(c, k, v);
         }
index e3201834a3d7ff14203968f7540dc23220e65841..2201388897bc3b1449862894af0a4eb51acd60ac 100644 (file)
@@ -6,7 +6,7 @@
 import syntax::ast;
 import util::common::*;
 
-export cstore;
+export cstore::{};
 export cnum_map;
 export crate_metadata;
 export mk_cstore;
index b1376ca3ba26823eeb54ad2b88ae7e67e654d547..ef0f4bb8d8659cf57f8b32759fdb26f8197b2f58 100644 (file)
@@ -26,8 +26,8 @@
 
 export send;
 export recv;
-export chan;
-export port;
+export chan::{};
+export port::{};
 
 #[abi = "cdecl"]
 native mod rustrt {
index 93fa3522fdb8da4d070bc2b60d421ca7b9ebf30a..dc9a24785c3f2b6b31ab9cec853c8d91e6792ff6 100644 (file)
 // warn-and-below.
 
 export error, warn, info, debug;
+
+#[doc = "The error log level"]
 const error : u32 = 0_u32;
+#[doc = "The warning log level"]
 const warn : u32 = 1_u32;
+#[doc = "The info log level"]
 const info : u32 = 2_u32;
+#[doc = "The debug log level"]
 const debug : u32 = 3_u32;
 
 // A curious inner-module that's not exported that contains the binding
index 824cef878d91c8ef6c0c9b7924bf84268b698bde..f583bb646d06047bcf9392608ba0bb6c2e19e307 100644 (file)
@@ -8,7 +8,7 @@
 export c_int, c_uint, long, longlong, unsigned, ulong, ulonglong;
 export intptr_t, uintptr_t;
 export uint32_t;
-export void;
+export void::{};
 export c_float, c_double;
 export size_t, ssize_t;
 export off_t, fd_t, pid_t;
index 1cccaf0f6411cd08b58edea8730f6a40e865a010..fa1aca29efa4c0477af67bfa2adc5310f59b4d73 100644 (file)
        push_char, is_utf8, from_chars, to_chars, char_len, char_len_range,
        char_at, bytes, is_ascii, shift_byte, pop_byte,
        unsafe_from_byte, unsafe_from_bytes, from_char, char_range_at,
+       from_bytes,
        from_cstr, sbuf, as_buf, push_byte, utf8_char_width, safe_slice,
-       contains, iter_chars, loop_chars, loop_chars_sub,
-       escape;
+       contains, iter_chars, chars_iter, bytes_iter, words_iter, lines_iter,
+       loop_chars, loop_chars_sub, escape, any, all, map, windowed;
 
 #[abi = "cdecl"]
 native mod rustrt {
@@ -191,6 +192,19 @@ fn unsafe_from_bytes(v: [const u8]) -> str unsafe {
     ret scopy;
 }
 
+/*
+Function: from_bytes
+
+Safely convert a vector of bytes to a UTF-8 string, or error
+*/
+fn from_bytes(vv: [u8]) -> result::t<str, str> {
+   if is_utf8(vv) {
+      ret result::ok(unsafe_from_bytes(vv));
+   } else {
+      ret result::err("vector doesn't contain valid UTF-8");
+   }
+}
+
 /*
 Function: unsafe_from_byte
 
@@ -346,7 +360,6 @@ fn char_range_at(s: str, i: uint) -> {ch: char, next: uint} {
 
 Iterate over the characters in a string
 */
-
 fn iter_chars(s: str, it: fn(char)) {
     let pos = 0u, len = byte_len(s);
     while (pos < len) {
@@ -356,6 +369,34 @@ fn iter_chars(s: str, it: fn(char)) {
     }
 }
 
+/*
+Function: chars_iter
+
+Iterate over the characters in a string
+
+FIXME: A synonym to iter_chars
+*/
+fn chars_iter(ss: str, it: fn(char)) {
+    iter_chars(ss, it)
+}
+
+/*
+Function: bytes_iter
+
+Iterate over the bytes in a string
+
+FIXME: Should it really include the last byte '\0'?
+*/
+fn bytes_iter(ss: str, it: fn(u8)) {
+    let pos = 0u;
+    let len = byte_len(ss);
+
+    while (pos < len) {
+        it(ss[pos]);
+        pos += 1u;
+    }
+}
+
 /*
 Function: loop_chars
 
@@ -825,7 +866,7 @@ fn split_str(s: str, sep: str) -> [str] {
 
 FIXME: will be renamed to split.
 */
-fn split_func(ss: str, sepfn: fn&(cc: char)->bool) -> [str] {
+fn split_func(ss: str, sepfn: fn(cc: char)->bool) -> [str] {
     let vv: [str] = [];
     let accum: str = "";
     let ends_with_sep: bool = false;
@@ -887,6 +928,24 @@ fn words(ss: str) -> [str] {
                      {|w| 0u < str::char_len(w)});
 }
 
+/*
+Function: words_iter
+
+Apply a function to each word
+*/
+fn words_iter(ss: str, ff: fn(&&str)) {
+    vec::iter(words(ss), ff)
+}
+
+/*
+Function: lines_iter
+
+Apply a function to each lines (by '\n')
+*/
+fn lines_iter(ss: str, ff: fn(&&str)) {
+    vec::iter(lines(ss), ff)
+}
+
 /*
 Function: concat
 
@@ -1113,6 +1172,64 @@ fn escape(s: str) -> str {
     r
 }
 
+/*
+Function: all
+
+Return true if a predicate matches all characters or
+if the string contains no characters
+
+// FIXME: a synonym to loop_chars
+*/
+fn all(ss: str, ff: fn(char) -> bool) -> bool {
+    str::loop_chars(ss, ff)
+}
+
+/*
+Function: any
+
+Return true if a predicate matches any character
+(and false if it matches none or there are no characters)
+*/
+fn any(ss: str, pred: fn(char) -> bool) -> bool {
+   !all(ss, {|cc| !pred(cc)})
+}
+
+/*
+Function: map
+
+Apply a function to each character
+*/
+fn map(ss: str, ff: fn(char) -> char) -> str {
+    let result = "";
+
+    str::iter_chars(ss, {|cc|
+        str::push_char(result, ff(cc));
+    });
+
+    ret result;
+}
+
+/*
+Function: windowed
+
+Create a vector of substrings of size `nn`
+*/
+fn windowed(nn: uint, ss: str) -> [str] {
+    let ww = [];
+    let len = str::char_len(ss);
+
+    assert 1u <= nn;
+
+    let ii = 0u;
+    while ii+nn <= len {
+        let w = char_slice( ss, ii, ii+nn );
+        vec::push(ww,w);
+        ii += 1u;
+    }
+
+    ret ww;
+}
+
 #[cfg(test)]
 mod tests {
 
@@ -1491,6 +1608,23 @@ fn test_unsafe_from_bytes() {
         assert (b == "AAAAAAA");
     }
 
+    #[test]
+    fn test_from_bytes() {
+        let ss = "ศไทย中华Việt Nam";
+        let bb = [0xe0_u8, 0xb8_u8, 0xa8_u8,
+                  0xe0_u8, 0xb9_u8, 0x84_u8,
+                  0xe0_u8, 0xb8_u8, 0x97_u8,
+                  0xe0_u8, 0xb8_u8, 0xa2_u8,
+                  0xe4_u8, 0xb8_u8, 0xad_u8,
+                  0xe5_u8, 0x8d_u8, 0x8e_u8,
+                  0x56_u8, 0x69_u8, 0xe1_u8,
+                  0xbb_u8, 0x87_u8, 0x74_u8,
+                  0x20_u8, 0x4e_u8, 0x61_u8,
+                  0x6d_u8];
+
+         assert ss == result::get(from_bytes(bb));
+    }
+
     #[test]
     fn test_from_cstr() unsafe {
         let a = [65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
@@ -1563,6 +1697,77 @@ fn test_iter_chars() {
             }
             i += 1;
         }
+
+        iter_chars("") {|_ch| fail; } // should not fail
+    }
+
+    #[test]
+    fn test_chars_iter() {
+        let i = 0;
+        chars_iter("x\u03c0y") {|ch|
+            alt i {
+              0 { assert ch == 'x'; }
+              1 { assert ch == '\u03c0'; }
+              2 { assert ch == 'y'; }
+            }
+            i += 1;
+        }
+
+        chars_iter("") {|_ch| fail; } // should not fail
+    }
+
+    #[test]
+    fn test_bytes_iter() {
+        let i = 0;
+
+        bytes_iter("xyz") {|bb|
+            alt i {
+              0 { assert bb == 'x' as u8; }
+              1 { assert bb == 'y' as u8; }
+              2 { assert bb == 'z' as u8; }
+            }
+            i += 1;
+        }
+
+        bytes_iter("") {|bb| assert bb == 0u8; }
+    }
+
+    #[test]
+    fn test_words_iter() {
+        let data = "\nMary had a little lamb\nLittle lamb\n";
+
+        let ii = 0;
+
+        words_iter(data) {|ww|
+            alt ii {
+              0 { assert "Mary"   == ww; }
+              1 { assert "had"    == ww; }
+              2 { assert "a"      == ww; }
+              3 { assert "little" == ww; }
+              _ { () }
+            }
+            ii += 1;
+        }
+
+        words_iter("") {|_x| fail; } // should not fail
+    }
+
+    #[test]
+    fn test_lines_iter () {
+        let lf = "\nMary had a little lamb\nLittle lamb\n";
+
+        let ii = 0;
+
+        lines_iter(lf) {|x|
+            alt ii {
+                0 { assert "" == x; }
+                1 { assert "Mary had a little lamb" == x; }
+                2 { assert "Little lamb" == x; }
+                3 { assert "" == x; }
+                _ { () }
+            }
+            ii += 1;
+        }
     }
 
     #[test]
@@ -1572,4 +1777,46 @@ fn test_escape() {
         assert(escape("abc\ndef") == "abc\\ndef");
         assert(escape("abc\"def") == "abc\\\"def");
     }
-}
\ No newline at end of file
+
+    #[test]
+    fn test_map() {
+        assert "" == map("", char::to_upper);
+        assert "YMCA" == map("ymca", char::to_upper);
+    }
+
+    #[test]
+    fn test_all() {
+        assert true  == all("", char::is_uppercase);
+        assert false == all("ymca", char::is_uppercase);
+        assert true  == all("YMCA", char::is_uppercase);
+        assert false == all("yMCA", char::is_uppercase);
+        assert false == all("YMCy", char::is_uppercase);
+    }
+
+    #[test]
+    fn test_any() {
+        assert false  == any("", char::is_uppercase);
+        assert false == any("ymca", char::is_uppercase);
+        assert true  == any("YMCA", char::is_uppercase);
+        assert true == any("yMCA", char::is_uppercase);
+        assert true == any("Ymcy", char::is_uppercase);
+    }
+
+    #[test]
+    fn test_windowed() {
+        let data = "ประเทศไทย中";
+
+        assert ["ประ", "ระเ", "ะเท", "เทศ", "ทศไ", "ศไท", "ไทย", "ทย中"]
+            == windowed(3u, data);
+
+        assert [data] == windowed(10u, data);
+
+        assert [] == windowed(6u, "abcd");
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_windowed_() {
+        let _x = windowed(0u, "abcd");
+    }
+}
index 0a1a401242296f52e3162cd8059cbd6c62b1e6dd..8b7ea91becd53a3270ad28761b585624c31ce9e6 100644 (file)
@@ -829,6 +829,23 @@ fn permute<T: copy>(v: [const T], put: fn([T])) {
   }
 }
 
+fn windowed <TT: copy> (nn: uint, xx: [TT]) -> [[TT]] {
+   let ww = [];
+
+   assert 1u <= nn;
+
+   vec::iteri (xx, {|ii, _x|
+      let len = vec::len(xx);
+
+      if ii+nn <= len {
+         let w = vec::slice ( xx, ii, ii+nn );
+         vec::push (ww, w);
+      }
+   });
+
+   ret ww;
+}
+
 /*
 Function: to_ptr
 
@@ -1497,6 +1514,22 @@ fn test_concat() {
         assert concat([[1], [2,3]]) == [1, 2, 3];
     }
 
+    #[test]
+    fn test_windowed () {
+        assert [[1u,2u,3u],[2u,3u,4u],[3u,4u,5u],[4u,5u,6u]]
+              == windowed (3u, [1u,2u,3u,4u,5u,6u]);
+
+        assert [[1u,2u,3u,4u],[2u,3u,4u,5u],[3u,4u,5u,6u]]
+              == windowed (4u, [1u,2u,3u,4u,5u,6u]);
+
+        assert [] == windowed (7u, [1u,2u,3u,4u,5u,6u]);
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_windowed_() {
+        let _x = windowed (0u, [1u,2u,3u,4u,5u,6u]);
+    }
 }
 
 // Local Variables:
index 2a7e559d189d366f93fa0cb262666bad233aa543..61acf89b6c032060c13efcde9335533454cf4d56 100644 (file)
@@ -17,6 +17,8 @@ typedef int _Unwind_Reason_Code;
 
 #if (defined __APPLE__) || (defined __clang__)
 
+#ifndef __FreeBSD__
+
 typedef int _Unwind_Action;
 typedef void _Unwind_Exception;
 
@@ -24,3 +26,5 @@ typedef void _Unwind_Exception;
 
 #endif
 
+#endif
+
index 8074b47ab5b33f74ca8dc1848ecd09631a21b807..2427dfa178449aeab6aa1ab5b2defb8890956b28 100644 (file)
@@ -9,8 +9,8 @@
 import rustc::front::attr;
 import core::tuple;
 
-export crate_attrs, mod_attrs, fn_attrs, arg_attrs;
-export parse_crate, parse_mod, parse_fn;
+export crate_attrs, mod_attrs, fn_attrs, arg_attrs, const_attrs;
+export parse_crate, parse_mod, parse_fn, parse_const;
 
 type crate_attrs = {
     name: option<str>
     desc: str
 };
 
+type const_attrs = {
+    brief: option<str>,
+    desc: option<str>
+};
+
 fn doc_meta(
     attrs: [ast::attribute]
 ) -> option<@ast::meta_item> {
@@ -276,6 +281,47 @@ fn parse_fn_should_parse_the_argument_descriptions() {
     assert attrs.args[1] == {name: "b", desc: "arg b"};
 }
 
+fn parse_const(attrs: [ast::attribute]) -> const_attrs {
+    parse_short_doc_or(
+        attrs,
+        {|desc|
+            {
+                brief: none,
+                desc: desc
+            }
+        },
+        parse_const_long_doc
+    )
+}
+
+fn parse_const_long_doc(
+    _items: [@ast::meta_item],
+    brief: option<str>,
+    desc: option<str>
+) -> const_attrs {
+    {
+        brief: brief,
+        desc: desc
+    }
+}
+
+#[test]
+fn should_parse_const_short_doc() {
+    let source = "#[doc = \"description\"]";
+    let attrs = test::parse_attributes(source);
+    let attrs = parse_fn(attrs);
+    assert attrs.desc == some("description");
+}
+
+#[test]
+fn should_parse_const_long_doc() {
+    let source = "#[doc(brief = \"a\", desc = \"b\")]";
+    let attrs = test::parse_attributes(source);
+    let attrs = parse_fn(attrs);
+    assert attrs.brief == some("a");
+    assert attrs.desc == some("b");
+}
+
 #[cfg(test)]
 mod test {
 
index 4c945a7869f327312e1a34b58f2a74a9cee59476..bc7eb8255065998ebe24e6105b1483e48f89c1c7 100644 (file)
@@ -22,7 +22,8 @@ fn run(
     let fold = fold::fold({
         fold_crate: fold_crate,
         fold_mod: fold_mod,
-        fold_fn: fold_fn
+        fold_fn: fold_fn,
+        fold_const: fold_const
         with *fold::default_seq_fold(srv)
     });
     fold.fold_crate(fold, doc)
@@ -59,6 +60,18 @@ fn should_replace_top_module_name_with_crate_name() {
     assert doc.topmod.name == "bond";
 }
 
+fn parse_item_attrs<T>(
+    srv: astsrv::srv,
+    id: doc::ast_id,
+    parse_attrs: fn~([ast::attribute]) -> T) -> T {
+    astsrv::exec(srv) {|ctxt|
+        let attrs = alt ctxt.map.get(id) {
+          ast_map::node_item(item) { item.attrs }
+        };
+        parse_attrs(attrs)
+    }
+}
+
 fn fold_mod(fold: fold::fold<astsrv::srv>, doc: doc::moddoc) -> doc::moddoc {
     let srv = fold.ctxt;
     let attrs = if doc.id == ast::crate_node_id {
@@ -67,12 +80,7 @@ fn fold_mod(fold: fold::fold<astsrv::srv>, doc: doc::moddoc) -> doc::moddoc {
             attr_parser::parse_mod(ctxt.ast.node.attrs)
         }
     } else {
-        astsrv::exec(srv) {|ctxt|
-            let attrs = alt ctxt.map.get(doc.id) {
-              ast_map::node_item(item) { item.attrs }
-            };
-            attr_parser::parse_mod(attrs)
-        }
+        parse_item_attrs(srv, doc.id, attr_parser::parse_mod)
     };
     let doc = fold::default_seq_fold_mod(fold, doc);
     ret merge_mod_attrs(doc, attrs);
@@ -116,12 +124,7 @@ fn fold_fn(
 
     let srv = fold.ctxt;
 
-    let attrs = astsrv::exec(srv) {|ctxt|
-        let attrs = alt ctxt.map.get(doc.id) {
-          ast_map::node_item(item) { item.attrs }
-        };
-        attr_parser::parse_fn(attrs)
-    };
+    let attrs = parse_item_attrs(srv, doc.id, attr_parser::parse_fn);
     ret merge_fn_attrs(doc, attrs);
 
     fn merge_fn_attrs(
@@ -208,4 +211,30 @@ fn fold_fn_should_preserve_sig() {
     let fold = fold::default_seq_fold(srv);
     let doc = fold_fn(fold, doc.topmod.fns[0]);
     assert doc.sig == some("fn a() -> int");
-}
\ No newline at end of file
+}
+
+fn fold_const(
+    fold: fold::fold<astsrv::srv>,
+    doc: doc::constdoc
+) -> doc::constdoc {
+    let srv = fold.ctxt;
+    let attrs = parse_item_attrs(srv, doc.id, attr_parser::parse_mod);
+
+    ~{
+        brief: attrs.brief,
+        desc: attrs.desc
+        with *doc
+    }
+}
+
+#[test]
+fn fold_const_should_extract_docs() {
+    let source = "#[doc(brief = \"foo\", desc = \"bar\")]\
+                  const a: bool = true;";
+    let srv = astsrv::mk_srv_from_str(source);
+    let doc = extract::from_srv(srv, "");
+    let fold = fold::default_seq_fold(srv);
+    let doc = fold_const(fold, doc.topmod.consts[0]);
+    assert doc.brief == some("foo");
+    assert doc.desc == some("bar");
+}
index 7ccd50b9649c04ba5e9f4ca6c3f36c5901351564..e8e3e963844ffb0621e4e595d60bf0081f240b13 100644 (file)
     brief: option<str>,
     desc: option<str>,
     mods: modlist,
-    fns: fnlist
+    fns: fnlist,
+    consts: constlist
+};
+
+type constdoc = ~{
+    id: ast_id,
+    name: str,
+    brief: option<str>,
+    desc: option<str>,
+    ty: option<str>
 };
 
 type fndoc = ~{
@@ -39,4 +48,5 @@
 
 // Just to break the structural recursive types
 enum modlist = [moddoc];
+enum constlist = [constdoc];
 enum fnlist = [fndoc];
index 9ce5bfed4fed9b489c9db68291ee35904be0200f..6217c1cb3f6bf47e30bd6554b07b3067ce3c85b5 100644 (file)
@@ -65,6 +65,17 @@ fn moddoc_from_mod(
                     none
                   }
                 }
+            }),
+        consts: doc::constlist(
+            vec::filter_map(module.items) {|item|
+                alt item.node {
+                  ast::item_const(_, _) {
+                    some(constdoc_from_const(item.ident, item.id))
+                  }
+                  _ {
+                    none
+                  }
+                }
             })
     }
 }
@@ -110,6 +121,28 @@ fn argdoc_from_arg(arg: ast::arg) -> doc::argdoc {
     }
 }
 
+fn constdoc_from_const(
+    name: ast::ident,
+    id: ast::node_id
+) -> doc::constdoc {
+    ~{
+        id: id,
+        name: name,
+        brief: none,
+        desc: none,
+        ty: none
+    }
+}
+
+#[test]
+fn should_extract_const_name_and_id() {
+    let source = "const a: int = 0;";
+    let ast = parse::from_str(source);
+    let doc = extract(ast, "");
+    assert doc.topmod.consts[0].id != 0;
+    assert doc.topmod.consts[0].name == "a";
+}
+
 #[cfg(test)]
 mod tests {
 
index 0a778ba3d542be5d2a175b546b3981c5f1f35008..85751d98a4b642619a44d01cbc0e05ffdd463d59 100644 (file)
@@ -1,9 +1,13 @@
+// FIXME: Random import to solve the mystery resolve bug
+import std;
+
 export fold;
 export fold_crate, fold_mod, fold_fn, fold_modlist, fold_fnlist;
 export default_seq_fold;
 export default_seq_fold_crate;
 export default_seq_fold_mod;
 export default_seq_fold_fn;
+export default_seq_fold_const;
 export default_seq_fold_fnlist;
 
 enum fold<T> = t<T>;
 type fold_crate<T> = fn~(fold: fold<T>, doc: doc::cratedoc) -> doc::cratedoc;
 type fold_mod<T> = fn~(fold: fold<T>, doc: doc::moddoc) -> doc::moddoc;
 type fold_fn<T> = fn~(fold: fold<T>, doc: doc::fndoc) -> doc::fndoc;
-type fold_modlist<T> = fn~(fold: fold<T>,list: doc::modlist) -> doc::modlist;
-type fold_fnlist<T> = fn~(fold: fold<T>,list: doc::fnlist) -> doc::fnlist;
+type fold_const<T> = fn~(fold: fold<T>, doc: doc::constdoc) -> doc::constdoc;
+type fold_modlist<T> = fn~(fold: fold<T>, list: doc::modlist) -> doc::modlist;
+type fold_fnlist<T> = fn~(fold: fold<T>, list: doc::fnlist) -> doc::fnlist;
+type fold_constlist<T> = fn~(
+    fold: fold<T>,
+    list: doc::constlist
+) -> doc::constlist;
 
 type t<T> = {
     ctxt: T,
     fold_crate: fold_crate<T>,
     fold_mod: fold_mod<T>,
     fold_fn: fold_fn<T>,
+    fold_const: fold_const<T>,
     fold_modlist: fold_modlist<T>,
-    fold_fnlist: fold_fnlist<T>
+    fold_fnlist: fold_fnlist<T>,
+    fold_constlist: fold_constlist<T>
 };
 
 
@@ -31,16 +42,20 @@ fn mk_fold<T:copy>(
     fold_crate: fold_crate<T>,
     fold_mod: fold_mod<T>,
     fold_fn: fold_fn<T>,
+    fold_const: fold_const<T>,
     fold_modlist: fold_modlist<T>,
-    fold_fnlist: fold_fnlist<T>
+    fold_fnlist: fold_fnlist<T>,
+    fold_constlist: fold_constlist<T>
 ) -> fold<T> {
     fold({
         ctxt: ctxt,
         fold_crate: fold_crate,
         fold_mod: fold_mod,
         fold_fn: fold_fn,
+        fold_const: fold_const,
         fold_modlist: fold_modlist,
-        fold_fnlist: fold_fnlist
+        fold_fnlist: fold_fnlist,
+        fold_constlist: fold_constlist
     })
 }
 
@@ -50,8 +65,10 @@ fn default_seq_fold<T:copy>(ctxt: T) -> fold<T> {
         {|f, d| default_seq_fold_crate(f, d)},
         {|f, d| default_seq_fold_mod(f, d)},
         {|f, d| default_seq_fold_fn(f, d)},
+        {|f, d| default_seq_fold_const(f, d)},
         {|f, d| default_seq_fold_modlist(f, d)},
-        {|f, d| default_seq_fold_fnlist(f, d)}
+        {|f, d| default_seq_fold_fnlist(f, d)},
+        {|f, d| default_seq_fold_constlist(f, d)}
     )
 }
 
@@ -70,7 +87,8 @@ fn default_seq_fold_mod<T>(
 ) -> doc::moddoc {
     ~{
         mods: fold.fold_modlist(fold, doc.mods),
-        fns: fold.fold_fnlist(fold, doc.fns)
+        fns: fold.fold_fnlist(fold, doc.fns),
+        consts: fold.fold_constlist(fold, doc.consts)
         with *doc
     }
 }
@@ -82,6 +100,13 @@ fn default_seq_fold_fn<T>(
     doc
 }
 
+fn default_seq_fold_const<T>(
+    _fold: fold<T>,
+    doc: doc::constdoc
+) -> doc::constdoc {
+    doc
+}
+
 fn default_seq_fold_modlist<T>(
     fold: fold<T>,
     list: doc::modlist
@@ -100,15 +125,31 @@ fn default_seq_fold_fnlist<T>(
     })
 }
 
-#[cfg(test)]
-mod tests {
-    #[test]
-    fn default_fold_should_produce_same_doc() {
-        let source = "mod a { fn b() { } mod c { fn d() { } } }";
-        let ast = parse::from_str(source);
-        let doc = extract::extract(ast, "");
-        let fld = default_seq_fold(());
-        let folded = fld.fold_crate(fld, doc);
-        assert doc == folded;
-    }
+fn default_seq_fold_constlist<T>(
+    fold: fold<T>,
+    list: doc::constlist
+) -> doc::constlist {
+    doc::constlist(vec::map(*list) {|doc|
+        fold.fold_const(fold, doc)
+    })
+}
+
+#[test]
+fn default_fold_should_produce_same_doc() {
+    let source = "mod a { fn b() { } mod c { fn d() { } } }";
+    let ast = parse::from_str(source);
+    let doc = extract::extract(ast, "");
+    let fld = default_seq_fold(());
+    let folded = fld.fold_crate(fld, doc);
+    assert doc == folded;
+}
+
+#[test]
+fn default_fold_should_produce_same_consts() {
+    let source = "const a: int = 0;";
+    let ast = parse::from_str(source);
+    let doc = extract::extract(ast, "");
+    let fld = default_seq_fold(());
+    let folded = fld.fold_crate(fld, doc);
+    assert doc == folded;
 }
\ No newline at end of file
index d0234ad6526215e182cf551b05c6c15a7a2146b9..5859b5288e9c7825f89e33267e0817de976ffa1f 100644 (file)
@@ -81,6 +81,10 @@ fn write_mod_contents(
     write_brief(ctxt, doc.brief);
     write_desc(ctxt, doc.desc);
 
+    for constdoc in *doc.consts {
+        write_const(ctxt, constdoc);
+    }
+
     for fndoc in *doc.fns {
         write_fn(ctxt, fndoc);
     }
@@ -300,6 +304,30 @@ fn should_write_return_description_on_same_line_as_type() {
     assert str::contains(markdown, "Returns `int` - blorp");
 }
 
+fn write_const(
+    ctxt: ctxt,
+    doc: doc::constdoc
+) {
+    write_header(ctxt, h3, #fmt("Const `%s`", doc.name));
+    write_sig(ctxt, doc.ty);
+    write_brief(ctxt, doc.brief);
+    write_desc(ctxt, doc.desc);
+}
+
+#[test]
+fn should_write_const_header() {
+    let markdown = test::render("const a: bool = true;");
+    assert str::contains(markdown, "### Const `a`\n\n");
+}
+
+#[test]
+fn should_write_const_description() {
+    let markdown = test::render(
+        "#[doc(brief = \"a\", desc = \"b\")]\
+         const a: bool = true;");
+    assert str::contains(markdown, "\n\na\n\nb\n\n");
+}
+
 #[cfg(test)]
 mod test {
     fn render(source: str) -> str {
@@ -343,7 +371,7 @@ fn write_markdown_should_write_crate_header() {
     #[test]
     fn write_markdown_should_write_function_header() {
         let markdown = render("fn func() { }");
-        assert str::contains(markdown, "## Function `func`");
+        assert str::contains(markdown, "### Function `func`");
     }
 
     #[test]
index 433ed1ff839c19094eab3ea36f298a6ddbf05c8b..d447d4e472d9ff30716e441cb1890b2bd41205fb 100644 (file)
@@ -20,8 +20,10 @@ fn run(
     let fold = fold::fold({
         fold_mod: fold_mod,
         fold_fn: fold_fn,
+        fold_const: fold_const,
         fold_modlist: fold_modlist,
-        fold_fnlist: fold_fnlist
+        fold_fnlist: fold_fnlist,
+        fold_constlist: fold_constlist
         with *fold::default_seq_fold(ctxt)
     });
     fold.fold_crate(fold, doc)
@@ -109,7 +111,7 @@ fn fold_modlist(
     list: doc::modlist
 ) -> doc::modlist {
     doc::modlist(vec::filter_map(*list) {|doc|
-        let doc = fold_mod(fold, doc);
+        let doc = fold.fold_mod(fold, doc);
         if fold.ctxt.have_docs {
             some(doc)
         } else {
@@ -152,7 +154,7 @@ fn fold_fnlist(
     list: doc::fnlist
 ) -> doc::fnlist {
     doc::fnlist(vec::filter_map(*list) {|doc|
-        let doc = fold_fn(fold, doc);
+        let doc = fold.fold_fn(fold, doc);
         if fold.ctxt.have_docs {
             some(doc)
         } else {
@@ -169,3 +171,37 @@ fn should_elide_undocumented_fns() {
     let doc = run(srv, doc);
     assert vec::is_empty(*doc.topmod.fns);
 }
+
+fn fold_const(
+    fold: fold::fold<ctxt>,
+    doc: doc::constdoc
+) -> doc::constdoc {
+    let doc = fold::default_seq_fold_const(fold, doc);
+    fold.ctxt.have_docs =
+        doc.brief != none
+        || doc.desc != none;
+    ret doc;
+}
+
+fn fold_constlist(
+    fold: fold::fold<ctxt>,
+    list: doc::constlist
+) -> doc::constlist {
+    doc::constlist(vec::filter_map(*list) {|doc|
+        let doc = fold.fold_const(fold, doc);
+        if fold.ctxt.have_docs {
+            some(doc)
+        } else {
+            none
+        }
+    })
+}
+
+#[test]
+fn should_elide_undocumented_consts() {
+    let source = "const a: bool = true;";
+    let srv = astsrv::mk_srv_from_str(source);
+    let doc = extract::from_srv(srv, "");
+    let doc = run(srv, doc);
+    assert vec::is_empty(*doc.topmod.consts);
+}
diff --git a/src/rustdoc/prune_unexported_pass.rs b/src/rustdoc/prune_unexported_pass.rs
new file mode 100644 (file)
index 0000000..31fc986
--- /dev/null
@@ -0,0 +1,233 @@
+#[doc = "Prunes branches of the tree that are not exported"];
+
+import rustc::syntax::ast;
+import rustc::syntax::ast_util;
+import rustc::middle::ast_map;
+
+export mk_pass;
+
+fn mk_pass() -> pass {
+    run
+}
+
+fn run(srv: astsrv::srv, doc: doc::cratedoc) -> doc::cratedoc {
+    let fold = fold::fold({
+        fold_mod: fold_mod
+        with *fold::default_seq_fold(srv)
+    });
+    fold.fold_crate(fold, doc)
+}
+
+fn fold_mod(fold: fold::fold<astsrv::srv>, doc: doc::moddoc) -> doc::moddoc {
+    let doc = fold::default_seq_fold_mod(fold, doc);
+    ~{
+        mods: doc::modlist(exported_mods(fold.ctxt, doc)),
+        fns: doc::fnlist(exported_fns(fold.ctxt, doc)),
+        consts: doc::constlist(exported_consts(fold.ctxt, doc))
+        with *doc
+    }
+}
+
+fn exported_mods(srv: astsrv::srv, doc: doc::moddoc) -> [doc::moddoc] {
+    exported_things(
+        srv, doc,
+        exported_mods_from_crate,
+        exported_mods_from_mod
+    )
+}
+
+fn exported_fns(srv: astsrv::srv, doc: doc::moddoc) -> [doc::fndoc] {
+    exported_things(
+        srv, doc,
+        exported_fns_from_crate,
+        exported_fns_from_mod
+    )
+}
+
+fn exported_consts(srv: astsrv::srv, doc: doc::moddoc) -> [doc::constdoc] {
+    exported_things(
+        srv, doc,
+        exported_consts_from_crate,
+        exported_consts_from_mod
+    )
+}
+
+fn exported_things<T>(
+    srv: astsrv::srv,
+    doc: doc::moddoc,
+    from_crate: fn(astsrv::srv, doc::moddoc) -> [T],
+    from_mod: fn(astsrv::srv, doc::moddoc) -> [T]
+) -> [T] {
+    if doc.id == ast::crate_node_id {
+        from_crate(srv, doc)
+    } else {
+        from_mod(srv, doc)
+    }
+}
+
+fn exported_mods_from_crate(
+    srv: astsrv::srv,
+    doc: doc::moddoc
+) -> [doc::moddoc] {
+    exported_mods_from(srv, doc, is_exported_from_crate)
+}
+
+fn exported_mods_from_mod(
+    srv: astsrv::srv,
+    doc: doc::moddoc
+) -> [doc::moddoc] {
+    exported_mods_from(srv, doc, bind is_exported_from_mod(_, doc.id, _))
+}
+
+fn exported_fns_from_crate(
+    srv: astsrv::srv,
+    doc: doc::moddoc
+) -> [doc::fndoc] {
+    exported_fns_from(srv, doc, is_exported_from_crate)
+}
+
+fn exported_fns_from_mod(
+    srv: astsrv::srv,
+    doc: doc::moddoc
+) -> [doc::fndoc] {
+    exported_fns_from(srv, doc, bind is_exported_from_mod(_, doc.id, _))
+}
+
+fn exported_consts_from_crate(
+    srv: astsrv::srv,
+    doc: doc::moddoc
+) -> [doc::constdoc] {
+    exported_consts_from(srv, doc, is_exported_from_crate)
+}
+
+fn exported_consts_from_mod(
+    srv: astsrv::srv,
+    doc: doc::moddoc
+) -> [doc::constdoc] {
+    exported_consts_from(srv, doc, bind is_exported_from_mod(_, doc.id, _))
+}
+
+fn exported_fns_from(
+    srv: astsrv::srv,
+    doc: doc::moddoc,
+    is_exported: fn(astsrv::srv, str) -> bool
+) -> [doc::fndoc] {
+    vec::filter_map(*doc.fns) { |doc|
+        if is_exported(srv, doc.name) {
+            some(doc)
+        } else {
+            none
+        }
+    }
+}
+
+fn exported_mods_from(
+    srv: astsrv::srv,
+    doc: doc::moddoc,
+    is_exported: fn(astsrv::srv, str) -> bool
+) -> [doc::moddoc] {
+    vec::filter_map(*doc.mods) { |doc|
+        if is_exported(srv, doc.name) {
+            some(doc)
+        } else {
+            none
+        }
+    }
+}
+
+fn exported_consts_from(
+    srv: astsrv::srv,
+    doc: doc::moddoc,
+    is_exported: fn(astsrv::srv, str) -> bool
+) -> [doc::constdoc] {
+    vec::filter_map(*doc.consts) { |doc|
+        if is_exported(srv, doc.name) {
+            some(doc)
+        } else {
+            none
+        }
+    }
+}
+
+fn is_exported_from_mod(
+    srv: astsrv::srv,
+    mod_id: doc::ast_id,
+    item_name: str
+) -> bool {
+    astsrv::exec(srv) {|ctxt|
+        alt ctxt.map.get(mod_id) {
+          ast_map::node_item(item) {
+            alt item.node {
+              ast::item_mod(m) {
+                ast_util::is_exported(item_name, m)
+              }
+            }
+          }
+        }
+    }
+}
+
+fn is_exported_from_crate(
+    srv: astsrv::srv,
+    item_name: str
+) -> bool {
+    astsrv::exec(srv) {|ctxt|
+        ast_util::is_exported(item_name, ctxt.ast.node.module)
+    }
+}
+
+#[test]
+fn should_prune_unexported_fns() {
+    let source = "mod b { export a; fn a() { } fn b() { } }";
+    let srv = astsrv::mk_srv_from_str(source);
+    let doc = extract::from_srv(srv, "");
+    let doc = run(srv, doc);
+    assert vec::len(*doc.topmod.mods[0].fns) == 1u;
+}
+
+#[test]
+fn should_prune_unexported_fns_from_top_mod() {
+    let source = "export a; fn a() { } fn b() { }";
+    let srv = astsrv::mk_srv_from_str(source);
+    let doc = extract::from_srv(srv, "");
+    let doc = run(srv, doc);
+    assert vec::len(*doc.topmod.fns) == 1u;
+}
+
+#[test]
+fn should_prune_unexported_modules() {
+    let source = "mod a { export a; mod a { } mod b { } }";
+    let srv = astsrv::mk_srv_from_str(source);
+    let doc = extract::from_srv(srv, "");
+    let doc = run(srv, doc);
+    assert vec::len(*doc.topmod.mods[0].mods) == 1u;
+}
+
+#[test]
+fn should_prune_unexported_modules_from_top_mod() {
+    let source = "export a; mod a { } mod b { }";
+    let srv = astsrv::mk_srv_from_str(source);
+    let doc = extract::from_srv(srv, "");
+    let doc = run(srv, doc);
+    assert vec::len(*doc.topmod.mods) == 1u;
+}
+
+#[test]
+fn should_prune_unexported_consts() {
+    let source = "mod a { export a; \
+                  const a: bool = true; \
+                  const b: bool = true; }";
+    let srv = astsrv::mk_srv_from_str(source);
+    let doc = extract::from_srv(srv, "");
+    let doc = run(srv, doc);
+    assert vec::len(*doc.topmod.mods[0].consts) == 1u;
+}
+
+#[test]
+fn should_prune_unexported_consts_from_top_mod() {
+    let source = "export a; const a: bool = true; const b: bool = true;";
+    let srv = astsrv::mk_srv_from_str(source);
+    let doc = extract::from_srv(srv, "");
+    let doc = run(srv, doc);
+    assert vec::len(*doc.topmod.consts) == 1u;
+}
index 61f2311a5b8f7d877caca9333c86e7615be96653..fe73191cd08d86478de5b12a40e6ceb0ea75886b 100644 (file)
@@ -22,4 +22,5 @@ mod path_pass;
 mod attr_pass;
 mod tystr_pass;
 mod prune_undoc_pass;
+mod prune_unexported_pass;
 mod astsrv;
index a34149d4a5a8770d92b0e247768073406a0e0469..257df26a6df4cdc78154e190ea35f6aacf303638 100755 (executable)
@@ -46,7 +46,8 @@ fn pass1(
                 brief: none,
                 desc: none,
                 mods: doc::modlist([]),
-                fns: doc::fnlist([])
+                fns: doc::fnlist([]),
+                consts: doc::constlist([])
             }
         }
     }
@@ -62,7 +63,8 @@ fn pass2(
                 brief: none,
                 desc: none,
                 mods: doc::modlist([]),
-                fns: doc::fnlist([])
+                fns: doc::fnlist([]),
+                consts: doc::constlist([])
             }
         }
     }
@@ -92,6 +94,7 @@ fn run(source_file: str) {
     let srv = astsrv::mk_srv_from_file(source_file);
     let doc = extract::from_srv(srv, default_name);
     run_passes(srv, doc, [
+        prune_unexported_pass::mk_pass(),
         tystr_pass::mk_pass(),
         path_pass::mk_pass(),
         attr_pass::mk_pass(),
index 26dcaabe81665cb263b719fb6496f47c43b258af..ba73e7d39c7624316369a6e5f8b2100ee5d2f8af 100644 (file)
@@ -16,7 +16,8 @@ fn run(
     doc: doc::cratedoc
 ) -> doc::cratedoc {
     let fold = fold::fold({
-        fold_fn: fold_fn
+        fold_fn: fold_fn,
+        fold_const: fold_const
         with *fold::default_seq_fold(srv)
     });
     fold.fold_crate(fold, doc)
@@ -149,4 +150,33 @@ fn should_add_arg_types() {
     let fn_ = doc.topmod.fns[0];
     assert fn_.args[0].ty == some("int");
     assert fn_.args[1].ty == some("bool");
+}
+
+fn fold_const(
+    fold: fold::fold<astsrv::srv>,
+    doc: doc::constdoc
+) -> doc::constdoc {
+    let srv = fold.ctxt;
+
+    ~{
+        ty: some(astsrv::exec(srv) {|ctxt|
+            alt ctxt.map.get(doc.id) {
+              ast_map::node_item(@{
+                node: ast::item_const(ty, _), _
+              }) {
+                pprust::ty_to_str(ty)
+              }
+            }
+        })
+        with *doc
+    }
+}
+
+#[test]
+fn should_add_const_types() {
+    let source = "const a: bool = true;";
+    let srv = astsrv::mk_srv_from_str(source);
+    let doc = extract::from_srv(srv, "");
+    let doc = run(srv, doc);
+    assert doc.topmod.consts[0].ty == some("bool");
 }
\ No newline at end of file
index eaac5cd459ed795044b68ad7c52788b91312bee3..d3cb0b1e87570c9a41b484ceb879910c502d6701 100644 (file)
@@ -1,3 +1,10 @@
+S 2012-01-23 6db688e
+  winnt-i386 e2e854ea3b53c39c348ecff56c46ec2e742930ef
+  linux-i386 ec28f47ea12512c79d110209d7278cbdb9db826c
+  macos-i386 e2fae898344cbbfd52a8cdd21063b8aadc9ca12e
+  linux-x86_64 b8492ad26d3ad9fbf91e7e1983bec484f76aeb49
+  macos-x86_64 8a8ecedc8ab6e02881395394a8ca6cb3aca3dece
+
 S 2012-01-21 ec82735
   winnt-i386 b77e911a0651199b2459fc429c3ab05d623cd1e1
   linux-i386 177e2a4d6996f704af9e5676352278d52cfe0d18