about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2014-12-26 10:55:16 +0200
committerEduard Burtescu <edy.burt@gmail.com>2015-01-21 16:27:26 +0200
commit3102b9e19e7af6f133777e4281d7d4e4d82fe4b0 (patch)
tree507321a1e2190d3acbac0024eb3e07bcc48cacff
parentf83a972224db1250513390589480be7e14c2a6c5 (diff)
downloadrust-3102b9e19e7af6f133777e4281d7d4e4d82fe4b0.tar.gz
rust-3102b9e19e7af6f133777e4281d7d4e4d82fe4b0.zip
rustdoc: fix fallout of merging ast::ViewItem into ast::Item.
-rw-r--r--src/librustdoc/clean/mod.rs189
-rw-r--r--src/librustdoc/doctree.rs22
-rw-r--r--src/librustdoc/html/format.rs2
-rw-r--r--src/librustdoc/html/item_type.rs40
-rw-r--r--src/librustdoc/html/render.rs88
-rw-r--r--src/librustdoc/html/static/main.css2
-rw-r--r--src/librustdoc/html/static/main.js5
-rw-r--r--src/librustdoc/passes.rs2
-rw-r--r--src/librustdoc/stability_summary.rs5
-rw-r--r--src/librustdoc/visit_ast.rs119
10 files changed, 224 insertions, 250 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 7342c9f3e81..7cae1828ef6 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -18,8 +18,7 @@ pub use self::TypeKind::*;
 pub use self::StructField::*;
 pub use self::VariantKind::*;
 pub use self::Mutability::*;
-pub use self::ViewItemInner::*;
-pub use self::ViewPath::*;
+pub use self::Import::*;
 pub use self::ItemEnum::*;
 pub use self::Attribute::*;
 pub use self::TyParamBound::*;
@@ -309,6 +308,8 @@ impl Item {
 
 #[derive(Clone, RustcEncodable, RustcDecodable)]
 pub enum ItemEnum {
+    ExternCrateItem(String, Option<String>),
+    ImportItem(Import),
     StructItem(Struct),
     EnumItem(Enum),
     FunctionItem(Function),
@@ -318,8 +319,6 @@ pub enum ItemEnum {
     ConstantItem(Constant),
     TraitItem(Trait),
     ImplItem(Impl),
-    /// `use` and `extern crate`
-    ViewItemItem(ViewItem),
     /// A method signature only. Used for required methods in traits (ie,
     /// non-default-methods).
     TyMethodItem(TyMethod),
@@ -349,27 +348,21 @@ impl Clean<Item> for doctree::Module {
         } else {
             "".to_string()
         };
-        let mut foreigns = Vec::new();
-        for subforeigns in self.foreigns.clean(cx).into_iter() {
-            for foreign in subforeigns.into_iter() {
-                foreigns.push(foreign)
-            }
-        }
-        let items: Vec<Vec<Item> > = vec!(
-            self.structs.clean(cx),
-            self.enums.clean(cx),
-            self.fns.clean(cx),
-            foreigns,
-            self.mods.clean(cx),
-            self.typedefs.clean(cx),
-            self.statics.clean(cx),
-            self.constants.clean(cx),
-            self.traits.clean(cx),
-            self.impls.clean(cx),
-            self.view_items.clean(cx).into_iter()
-                           .flat_map(|s| s.into_iter()).collect(),
-            self.macros.clean(cx),
-        );
+        let items: Vec<Item> =
+                   self.extern_crates.iter().map(|x| x.clean(cx))
+            .chain(self.imports.iter().flat_map(|x| x.clean(cx).into_iter()))
+            .chain(self.structs.iter().map(|x| x.clean(cx)))
+            .chain(self.enums.iter().map(|x| x.clean(cx)))
+            .chain(self.fns.iter().map(|x| x.clean(cx)))
+            .chain(self.foreigns.iter().flat_map(|x| x.clean(cx).into_iter()))
+            .chain(self.mods.iter().map(|x| x.clean(cx)))
+            .chain(self.typedefs.iter().map(|x| x.clean(cx)))
+            .chain(self.statics.iter().map(|x| x.clean(cx)))
+            .chain(self.constants.iter().map(|x| x.clean(cx)))
+            .chain(self.traits.iter().map(|x| x.clean(cx)))
+            .chain(self.impls.iter().map(|x| x.clean(cx)))
+            .chain(self.macros.iter().map(|x| x.clean(cx)))
+            .collect();
 
         // determine if we should display the inner contents or
         // the outer `mod` item for the source code.
@@ -395,9 +388,7 @@ impl Clean<Item> for doctree::Module {
             def_id: ast_util::local_def(self.id),
             inner: ModuleItem(Module {
                is_crate: self.is_crate,
-               items: items.iter()
-                           .flat_map(|x| x.iter().map(|x| (*x).clone()))
-                           .collect(),
+               items: items
             })
         }
     }
@@ -2120,12 +2111,21 @@ impl Clean<Item> for doctree::Impl {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
-pub struct ViewItem {
-    pub inner: ViewItemInner,
+impl Clean<Item> for doctree::ExternCrate {
+    fn clean(&self, cx: &DocContext) -> Item {
+        Item {
+            name: None,
+            attrs: self.attrs.clean(cx),
+            source: self.whence.clean(cx),
+            def_id: ast_util::local_def(0),
+            visibility: self.vis.clean(cx),
+            stability: None,
+            inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
+        }
+    }
 }
 
-impl Clean<Vec<Item>> for ast::ViewItem {
+impl Clean<Vec<Item>> for doctree::Import {
     fn clean(&self, cx: &DocContext) -> Vec<Item> {
         // We consider inlining the documentation of `pub use` statements, but we
         // forcefully don't inline if this is not public or if the
@@ -2136,81 +2136,63 @@ impl Clean<Vec<Item>> for ast::ViewItem {
                 None => false,
             }
         });
-        let convert = |&: node: &ast::ViewItem_| {
-            Item {
-                name: None,
-                attrs: self.attrs.clean(cx),
-                source: self.span.clean(cx),
-                def_id: ast_util::local_def(0),
-                visibility: self.vis.clean(cx),
-                stability: None,
-                inner: ViewItemItem(ViewItem { inner: node.clean(cx) }),
+        let (mut ret, inner) = match self.node {
+            ast::ViewPathGlob(ref p) => {
+                (vec![], GlobImport(resolve_use_source(cx, p.clean(cx), self.id)))
             }
-        };
-        let mut ret = Vec::new();
-        match self.node {
-            ast::ViewItemUse(ref path) if !denied => {
-                match path.node {
-                    ast::ViewPathGlob(..) => ret.push(convert(&self.node)),
-                    ast::ViewPathList(ref a, ref list, ref b) => {
-                        // Attempt to inline all reexported items, but be sure
-                        // to keep any non-inlineable reexports so they can be
-                        // listed in the documentation.
-                        let remaining = list.iter().filter(|path| {
-                            match inline::try_inline(cx, path.node.id(), None) {
-                                Some(items) => {
-                                    ret.extend(items.into_iter()); false
-                                }
-                                None => true,
+            ast::ViewPathList(ref p, ref list) => {
+                // Attempt to inline all reexported items, but be sure
+                // to keep any non-inlineable reexports so they can be
+                // listed in the documentation.
+                let mut ret = vec![];
+                let remaining = if !denied {
+                    let mut remaining = vec![];
+                    for path in list.iter() {
+                        match inline::try_inline(cx, path.node.id(), None) {
+                            Some(items) => {
+                                ret.extend(items.into_iter());
+                            }
+                            None => {
+                                remaining.push(path.clean(cx));
                             }
-                        }).map(|a| a.clone()).collect::<Vec<ast::PathListItem>>();
-                        if remaining.len() > 0 {
-                            let path = ast::ViewPathList(a.clone(),
-                                                         remaining,
-                                                         b.clone());
-                            let path = syntax::codemap::dummy_spanned(path);
-                            ret.push(convert(&ast::ViewItemUse(P(path))));
-                        }
-                    }
-                    ast::ViewPathSimple(ident, _, id) => {
-                        match inline::try_inline(cx, id, Some(ident)) {
-                            Some(items) => ret.extend(items.into_iter()),
-                            None => ret.push(convert(&self.node)),
                         }
                     }
-                }
-            }
-            ref n => ret.push(convert(n)),
-        }
-        return ret;
-    }
-}
-
-#[derive(Clone, RustcEncodable, RustcDecodable)]
-pub enum ViewItemInner {
-    ExternCrate(String, Option<String>, ast::NodeId),
-    Import(ViewPath)
-}
-
-impl Clean<ViewItemInner> for ast::ViewItem_ {
-    fn clean(&self, cx: &DocContext) -> ViewItemInner {
-        match self {
-            &ast::ViewItemExternCrate(ref i, ref p, ref id) => {
-                let string = match *p {
-                    None => None,
-                    Some((ref x, _)) => Some(x.get().to_string()),
+                    remaining
+                } else {
+                    list.clean(cx)
                 };
-                ExternCrate(i.clean(cx), string, *id)
+                if remaining.is_empty() {
+                    return ret;
+                }
+                (ret, ImportList(resolve_use_source(cx, p.clean(cx), self.id),
+                                 remaining))
             }
-            &ast::ViewItemUse(ref vp) => {
-                Import(vp.clean(cx))
+            ast::ViewPathSimple(i, ref p) => {
+                if !denied {
+                    match inline::try_inline(cx, self.id, Some(i)) {
+                        Some(items) => return items,
+                        None => {}
+                    }
+                }
+                (vec![], SimpleImport(i.clean(cx),
+                                      resolve_use_source(cx, p.clean(cx), self.id)))
             }
-        }
+        };
+        ret.push(Item {
+            name: None,
+            attrs: self.attrs.clean(cx),
+            source: self.whence.clean(cx),
+            def_id: ast_util::local_def(0),
+            visibility: self.vis.clean(cx),
+            stability: None,
+            inner: ImportItem(inner)
+        });
+        ret
     }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable)]
-pub enum ViewPath {
+pub enum Import {
     // use source as str;
     SimpleImport(String, ImportSource),
     // use source::*;
@@ -2225,21 +2207,6 @@ pub struct ImportSource {
     pub did: Option<ast::DefId>,
 }
 
-impl Clean<ViewPath> for ast::ViewPath {
-    fn clean(&self, cx: &DocContext) -> ViewPath {
-        match self.node {
-            ast::ViewPathSimple(ref i, ref p, id) =>
-                SimpleImport(i.clean(cx), resolve_use_source(cx, p.clean(cx), id)),
-            ast::ViewPathGlob(ref p, id) =>
-                GlobImport(resolve_use_source(cx, p.clean(cx), id)),
-            ast::ViewPathList(ref p, ref pl, id) => {
-                ImportList(resolve_use_source(cx, p.clean(cx), id),
-                           pl.clean(cx))
-            }
-        }
-    }
-}
-
 #[derive(Clone, RustcEncodable, RustcDecodable)]
 pub struct ViewListIdent {
     pub name: String,
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 99afef4173f..0e8ab594c20 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -25,6 +25,8 @@ pub struct Module {
     pub attrs: Vec<ast::Attribute>,
     pub where_outer: Span,
     pub where_inner: Span,
+    pub extern_crates: Vec<ExternCrate>,
+    pub imports: Vec<Import>,
     pub structs: Vec<Struct>,
     pub enums: Vec<Enum>,
     pub fns: Vec<Function>,
@@ -38,7 +40,6 @@ pub struct Module {
     pub stab: Option<attr::Stability>,
     pub impls: Vec<Impl>,
     pub foreigns: Vec<ast::ForeignMod>,
-    pub view_items: Vec<ast::ViewItem>,
     pub macros: Vec<Macro>,
     pub is_crate: bool,
 }
@@ -53,6 +54,8 @@ impl Module {
             where_outer: syntax::codemap::DUMMY_SP,
             where_inner: syntax::codemap::DUMMY_SP,
             attrs      : Vec::new(),
+            extern_crates: Vec::new(),
+            imports    : Vec::new(),
             structs    : Vec::new(),
             enums      : Vec::new(),
             fns        : Vec::new(),
@@ -62,7 +65,6 @@ impl Module {
             constants  : Vec::new(),
             traits     : Vec::new(),
             impls      : Vec::new(),
-            view_items : Vec::new(),
             foreigns   : Vec::new(),
             macros     : Vec::new(),
             is_crate   : false,
@@ -202,6 +204,22 @@ pub struct Macro {
     pub stab: Option<attr::Stability>,
 }
 
+pub struct ExternCrate {
+    pub name: Ident,
+    pub path: Option<String>,
+    pub vis: ast::Visibility,
+    pub attrs: Vec<ast::Attribute>,
+    pub whence: Span,
+}
+
+pub struct Import {
+    pub id: NodeId,
+    pub vis: ast::Visibility,
+    pub attrs: Vec<ast::Attribute>,
+    pub node: ast::ViewPath_,
+    pub whence: Span,
+}
+
 pub fn struct_type_from_def(sd: &ast::StructDef) -> StructType {
     if sd.ctor_id.is_some() {
         // We are in a tuple-struct
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 57b8d666c95..c8efa4c57bb 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -617,7 +617,7 @@ impl fmt::String for UnsafetySpace {
     }
 }
 
-impl fmt::String for clean::ViewPath {
+impl fmt::String for clean::Import {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             clean::SimpleImport(ref name, ref src) => {
diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs
index db3319eb765..ff7884a8616 100644
--- a/src/librustdoc/html/item_type.rs
+++ b/src/librustdoc/html/item_type.rs
@@ -22,29 +22,31 @@ use clean;
 #[derive(Copy, PartialEq, Clone)]
 pub enum ItemType {
     Module          = 0,
-    Struct          = 1,
-    Enum            = 2,
-    Function        = 3,
-    Typedef         = 4,
-    Static          = 5,
-    Trait           = 6,
-    Impl            = 7,
-    ViewItem        = 8,
-    TyMethod        = 9,
-    Method          = 10,
-    StructField     = 11,
-    Variant         = 12,
-    // we used to have ForeignFunction and ForeignStatic. they are retired now.
-    Macro           = 15,
-    Primitive       = 16,
-    AssociatedType  = 17,
-    Constant        = 18,
+    ExternCrate     = 1,
+    Import          = 2,
+    Struct          = 3,
+    Enum            = 4,
+    Function        = 5,
+    Typedef         = 6,
+    Static          = 7,
+    Trait           = 8,
+    Impl            = 9,
+    TyMethod        = 10,
+    Method          = 11,
+    StructField     = 12,
+    Variant         = 13,
+    Macro           = 14,
+    Primitive       = 15,
+    AssociatedType  = 16,
+    Constant        = 17,
 }
 
 impl ItemType {
     pub fn from_item(item: &clean::Item) -> ItemType {
         match item.inner {
             clean::ModuleItem(..)          => ItemType::Module,
+            clean::ExternCrateItem(..)     => ItemType::ExternCrate,
+            clean::ImportItem(..)          => ItemType::Import,
             clean::StructItem(..)          => ItemType::Struct,
             clean::EnumItem(..)            => ItemType::Enum,
             clean::FunctionItem(..)        => ItemType::Function,
@@ -53,7 +55,6 @@ impl ItemType {
             clean::ConstantItem(..)        => ItemType::Constant,
             clean::TraitItem(..)           => ItemType::Trait,
             clean::ImplItem(..)            => ItemType::Impl,
-            clean::ViewItemItem(..)        => ItemType::ViewItem,
             clean::TyMethodItem(..)        => ItemType::TyMethod,
             clean::MethodItem(..)          => ItemType::Method,
             clean::StructFieldItem(..)     => ItemType::StructField,
@@ -83,6 +84,8 @@ impl ItemType {
     pub fn to_static_str(&self) -> &'static str {
         match *self {
             ItemType::Module          => "mod",
+            ItemType::ExternCrate     => "externcrate",
+            ItemType::Import          => "import",
             ItemType::Struct          => "struct",
             ItemType::Enum            => "enum",
             ItemType::Function        => "fn",
@@ -90,7 +93,6 @@ impl ItemType {
             ItemType::Static          => "static",
             ItemType::Trait           => "trait",
             ItemType::Impl            => "impl",
-            ItemType::ViewItem        => "viewitem",
             ItemType::TyMethod        => "tymethod",
             ItemType::Method          => "method",
             ItemType::StructField     => "structfield",
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index ab9700d966a..6242b5d8900 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -35,7 +35,7 @@
 pub use self::ExternalLocation::*;
 
 use std::cell::RefCell;
-use std::cmp::Ordering::{self, Less, Greater, Equal};
+use std::cmp::Ordering;
 use std::collections::{HashMap, HashSet};
 use std::default::Default;
 use std::fmt;
@@ -1497,18 +1497,19 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
     // the order of item types in the listing
     fn reorder(ty: ItemType) -> u8 {
         match ty {
-            ItemType::ViewItem        => 0,
-            ItemType::Primitive       => 1,
-            ItemType::Module          => 2,
-            ItemType::Macro           => 3,
-            ItemType::Struct          => 4,
-            ItemType::Enum            => 5,
-            ItemType::Constant        => 6,
-            ItemType::Static          => 7,
-            ItemType::Trait           => 8,
-            ItemType::Function        => 9,
-            ItemType::Typedef         => 10,
-            _                         => 11 + ty as u8,
+            ItemType::ExternCrate     => 0,
+            ItemType::Import          => 1,
+            ItemType::Primitive       => 2,
+            ItemType::Module          => 3,
+            ItemType::Macro           => 4,
+            ItemType::Struct          => 5,
+            ItemType::Enum            => 6,
+            ItemType::Constant        => 7,
+            ItemType::Static          => 8,
+            ItemType::Trait           => 9,
+            ItemType::Function        => 10,
+            ItemType::Typedef         => 12,
+            _                         => 13 + ty as u8,
         }
     }
 
@@ -1518,25 +1519,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
         if ty1 == ty2 {
             return i1.name.cmp(&i2.name);
         }
-
-        let tycmp = reorder(ty1).cmp(&reorder(ty2));
-        if let Equal = tycmp {
-            // for reexports, `extern crate` takes precedence.
-            match (&i1.inner, &i2.inner) {
-                (&clean::ViewItemItem(ref a), &clean::ViewItemItem(ref b)) => {
-                    match (&a.inner, &b.inner) {
-                        (&clean::ExternCrate(..), _) => return Less,
-                        (_, &clean::ExternCrate(..)) => return Greater,
-                        _ => {}
-                    }
-                }
-                (_, _) => {}
-            }
-
-            idx1.cmp(&idx2)
-        } else {
-            tycmp
-        }
+        (reorder(ty1), idx1).cmp(&(reorder(ty2), idx2))
     }
 
     indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2));
@@ -1547,12 +1530,17 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
         let myitem = &items[idx];
 
         let myty = Some(shortty(myitem));
-        if myty != curty {
+        if curty == Some(ItemType::ExternCrate) && myty == Some(ItemType::Import) {
+            // Put `extern crate` and `use` re-exports in the same section.
+            curty = myty;
+        } else if myty != curty {
             if curty.is_some() {
                 try!(write!(w, "</table>"));
             }
             curty = myty;
             let (short, name) = match myty.unwrap() {
+                ItemType::ExternCrate |
+                ItemType::Import          => ("reexports", "Reexports"),
                 ItemType::Module          => ("modules", "Modules"),
                 ItemType::Struct          => ("structs", "Structs"),
                 ItemType::Enum            => ("enums", "Enums"),
@@ -1562,7 +1550,6 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
                 ItemType::Constant        => ("constants", "Constants"),
                 ItemType::Trait           => ("traits", "Traits"),
                 ItemType::Impl            => ("impls", "Implementations"),
-                ItemType::ViewItem        => ("reexports", "Reexports"),
                 ItemType::TyMethod        => ("tymethods", "Type Methods"),
                 ItemType::Method          => ("methods", "Methods"),
                 ItemType::StructField     => ("fields", "Struct Fields"),
@@ -1578,28 +1565,25 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
         }
 
         match myitem.inner {
-            clean::ViewItemItem(ref item) => {
-                match item.inner {
-                    clean::ExternCrate(ref name, ref src, _) => {
-                        match *src {
-                            Some(ref src) =>
-                                try!(write!(w, "<tr><td><code>extern crate \"{}\" as {}",
-                                            src.as_slice(),
-                                            name.as_slice())),
-                            None =>
-                                try!(write!(w, "<tr><td><code>extern crate {}",
-                                            name.as_slice())),
-                        }
-                        try!(write!(w, ";</code></td></tr>"));
+            clean::ExternCrateItem(ref name, ref src) => {
+                match *src {
+                    Some(ref src) => {
+                        try!(write!(w, "<tr><td><code>{}extern crate \"{}\" as {};",
+                                    VisSpace(myitem.visibility),
+                                    src.as_slice(),
+                                    name.as_slice()))
                     }
-
-                    clean::Import(ref import) => {
-                        try!(write!(w, "<tr><td><code>{}{}</code></td></tr>",
-                                      VisSpace(myitem.visibility),
-                                      *import));
+                    None => {
+                        try!(write!(w, "<tr><td><code>{}extern crate {};",
+                                    VisSpace(myitem.visibility), name.as_slice()))
                     }
                 }
+                try!(write!(w, "</code></td></tr>"));
+            }
 
+            clean::ImportItem(ref import) => {
+                try!(write!(w, "<tr><td><code>{}{}</code></td></tr>",
+                            VisSpace(myitem.visibility), *import));
             }
 
             _ => {
diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css
index 5951ac2bae7..0914f93efd8 100644
--- a/src/librustdoc/html/static/main.css
+++ b/src/librustdoc/html/static/main.css
@@ -245,7 +245,6 @@ nav.sub {
 .content .highlighted.method { background-color: #c6afb3; }
 .content .highlighted.tymethod { background-color: #c6afb3; }
 .content .highlighted.type { background-color: #c6afb3; }
-.content .highlighted.ffi { background-color: #c6afb3; }
 
 .docblock.short.nowrap {
     display: block;
@@ -365,7 +364,6 @@ p a:hover { text-decoration: underline; }
 .content span.fn, .content a.fn, .block a.current.fn { color: #8c6067; }
 .content span.method, .content a.method, .block a.current.method { color: #8c6067; }
 .content span.tymethod, .content a.tymethod, .block a.current.tymethod { color: #8c6067; }
-.content span.ffi, .content a.ffi, .block a.current.ffi { color: #8c6067; }
 .content .fnname { color: #8c6067; }
 
 .search-input {
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index f27f0cd70f4..1b0c3b00640 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -555,6 +555,8 @@
         // This mapping table should match the discriminants of
         // `rustdoc::html::item_type::ItemType` type in Rust.
         var itemTypes = ["mod",
+                         "externcrate",
+                         "import",
                          "struct",
                          "enum",
                          "fn",
@@ -562,13 +564,10 @@
                          "static",
                          "trait",
                          "impl",
-                         "viewitem",
                          "tymethod",
                          "method",
                          "structfield",
                          "variant",
-                         "ffi", // retained for backward compatibility
-                         "ffs", // retained for backward compatibility
                          "macro",
                          "primitive",
                          "associatedtype",
diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs
index 9a67b479106..0e60001e15f 100644
--- a/src/librustdoc/passes.rs
+++ b/src/librustdoc/passes.rs
@@ -149,7 +149,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
                 }
             }
 
-            clean::ViewItemItem(..) => {
+            clean::ExternCrateItem(..) | clean::ImportItem(_) => {
                 if i.visibility != Some(ast::Public) {
                     return None
                 }
diff --git a/src/librustdoc/stability_summary.rs b/src/librustdoc/stability_summary.rs
index 451dbce568e..943bc6ec996 100644
--- a/src/librustdoc/stability_summary.rs
+++ b/src/librustdoc/stability_summary.rs
@@ -21,7 +21,7 @@ use syntax::ast::Public;
 
 use clean::{Crate, Item, ModuleItem, Module, EnumItem, Enum};
 use clean::{ImplItem, Impl, Trait, TraitItem, TraitMethod, ProvidedMethod, RequiredMethod};
-use clean::{TypeTraitItem, ViewItemItem, PrimitiveItem, Stability};
+use clean::{TypeTraitItem, ExternCrateItem, ImportItem, PrimitiveItem, Stability};
 
 use html::render::cache;
 
@@ -199,7 +199,8 @@ fn summarize_item(item: &Item) -> (Counts, Option<ModuleSummary>) {
             }))
         }
         // no stability information for the following items:
-        ViewItemItem(_) | PrimitiveItem(_) => (Counts::zero(), None),
+        ExternCrateItem(..) | ImportItem(_) |
+        PrimitiveItem(_) => (Counts::zero(), None),
         _ => (item_counts, None)
     }
 }
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 428b4e92a68..848205f589e 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -20,7 +20,6 @@ use syntax::ast_map;
 use syntax::attr;
 use syntax::attr::AttrMetaMethods;
 use syntax::codemap::Span;
-use syntax::ptr::P;
 
 use rustc::middle::stability;
 
@@ -142,9 +141,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                               m: &ast::Mod,
                               name: Option<ast::Ident>) -> Module {
         let mut om = Module::new(name);
-        for item in m.view_items.iter() {
-            self.visit_view_item(item, &mut om);
-        }
         om.where_outer = span;
         om.where_inner = m.inner;
         om.attrs = attrs;
@@ -157,68 +153,41 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         om
     }
 
-    pub fn visit_view_item(&mut self, item: &ast::ViewItem, om: &mut Module) {
-        if item.vis != ast::Public {
-            return om.view_items.push(item.clone());
-        }
-        let please_inline = item.attrs.iter().any(|item| {
-            match item.meta_item_list() {
-                Some(list) => {
-                    list.iter().any(|i| i.name().get() == "inline")
-                }
-                None => false,
-            }
-        });
-        let item = match item.node {
-            ast::ViewItemUse(ref vpath) => {
-                match self.visit_view_path(&**vpath, om, please_inline) {
-                    None => return,
-                    Some(path) => {
-                        ast::ViewItem {
-                            node: ast::ViewItemUse(path),
-                            .. item.clone()
-                        }
-                    }
-                }
-            }
-            ast::ViewItemExternCrate(..) => item.clone()
-        };
-        om.view_items.push(item);
-    }
-
-    fn visit_view_path(&mut self, path: &ast::ViewPath,
+    fn visit_view_path(&mut self, path: ast::ViewPath_,
                        om: &mut Module,
-                       please_inline: bool) -> Option<P<ast::ViewPath>> {
-        match path.node {
-            ast::ViewPathSimple(dst, _, id) => {
+                       id: ast::NodeId,
+                       please_inline: bool) -> Option<ast::ViewPath_> {
+        match path {
+            ast::ViewPathSimple(dst, base) => {
                 if self.resolve_id(id, Some(dst), false, om, please_inline) {
-                    return None
+                    None
+                } else {
+                    Some(ast::ViewPathSimple(dst, base))
                 }
             }
-            ast::ViewPathList(ref p, ref paths, ref b) => {
-                let mut mine = Vec::new();
-                for path in paths.iter() {
-                    if !self.resolve_id(path.node.id(), None, false, om,
-                                        please_inline) {
-                        mine.push(path.clone());
-                    }
-                }
+            ast::ViewPathList(p, paths) => {
+                let mine = paths.into_iter().filter(|path| {
+                    !self.resolve_id(path.node.id(), None, false, om,
+                                     please_inline)
+                }).collect::<Vec<ast::PathListItem>>();
 
-                if mine.len() == 0 { return None }
-                return Some(P(::syntax::codemap::Spanned {
-                    node: ast::ViewPathList(p.clone(), mine, b.clone()),
-                    span: path.span,
-                }))
+                if mine.len() == 0 {
+                    None
+                } else {
+                    Some(ast::ViewPathList(p, mine))
+                }
             }
 
             // these are feature gated anyway
-            ast::ViewPathGlob(_, id) => {
+            ast::ViewPathGlob(base) => {
                 if self.resolve_id(id, None, true, om, please_inline) {
-                    return None
+                    None
+                } else {
+                    Some(ast::ViewPathGlob(base))
                 }
             }
         }
-        Some(P(path.clone()))
+
     }
 
     fn resolve_id(&mut self, id: ast::NodeId, renamed: Option<ast::Ident>,
@@ -242,9 +211,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 if glob {
                     match it.node {
                         ast::ItemMod(ref m) => {
-                            for vi in m.view_items.iter() {
-                                self.visit_view_item(vi, om);
-                            }
                             for i in m.items.iter() {
                                 self.visit_item(&**i, None, om);
                             }
@@ -268,6 +234,45 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         debug!("Visiting item {:?}", item);
         let name = renamed.unwrap_or(item.ident);
         match item.node {
+            ast::ItemExternCrate(ref p) => {
+                let path = match *p {
+                    None => None,
+                    Some((ref x, _)) => Some(x.get().to_string()),
+                };
+                om.extern_crates.push(ExternCrate {
+                    name: name,
+                    path: path,
+                    vis: item.vis,
+                    attrs: item.attrs.clone(),
+                    whence: item.span,
+                })
+            }
+            ast::ItemUse(ref vpath) => {
+                let node = vpath.node.clone();
+                let node = if item.vis == ast::Public {
+                    let please_inline = item.attrs.iter().any(|item| {
+                        match item.meta_item_list() {
+                            Some(list) => {
+                                list.iter().any(|i| i.name().get() == "inline")
+                            }
+                            None => false,
+                        }
+                    });
+                    match self.visit_view_path(node, om, item.id, please_inline) {
+                        None => return,
+                        Some(p) => p
+                    }
+                } else {
+                    node
+                };
+                om.imports.push(Import {
+                    id: item.id,
+                    vis: item.vis,
+                    attrs: item.attrs.clone(),
+                    node: node,
+                    whence: item.span,
+                });
+            }
             ast::ItemMod(ref m) => {
                 om.mods.push(self.visit_mod_contents(item.span,
                                                      item.attrs.clone(),