]> git.lizzy.rs Git - rust.git/commitdiff
rustdoc: Suck in all impls from external crates
authorAlex Crichton <alex@alexcrichton.com>
Thu, 29 May 2014 08:35:44 +0000 (01:35 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Sun, 1 Jun 2014 04:59:50 +0000 (21:59 -0700)
There is currently no way to query all impls for a type from an external crate,
and with primitive types in play this is also quite difficult. Instead of
filtering, just suck in all impls from upstream crates into the local AST, and
have them get stripped later.

This will allow population of all implementations of traits for primitive types,
as well as filling in some corner cases with inlining documentation in other
cases.

src/librustdoc/clean/inline.rs
src/librustdoc/core.rs
src/librustdoc/test.rs

index b60e0a70dd0ec745a6b5b4397bff24b627b85c97..0c2714355dc24b6bc0a7c2c3be4c5e7c2db96607 100644 (file)
@@ -67,12 +67,12 @@ fn try_inline_def(cx: &core::DocContext,
         }
         ast::DefStruct(did) => {
             record_extern_fqn(cx, did, clean::TypeStruct);
-            ret.extend(build_impls(tcx, did).move_iter());
+            ret.extend(build_impls(cx, tcx, did).move_iter());
             clean::StructItem(build_struct(tcx, did))
         }
         ast::DefTy(did) => {
             record_extern_fqn(cx, did, clean::TypeEnum);
-            ret.extend(build_impls(tcx, did).move_iter());
+            ret.extend(build_impls(cx, tcx, did).move_iter());
             build_type(tcx, did)
         }
         // Assume that the enum type is reexported next to the variant, and
@@ -193,7 +193,8 @@ fn build_type(tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum {
     })
 }
 
-fn build_impls(tcx: &ty::ctxt,
+fn build_impls(cx: &core::DocContext,
+               tcx: &ty::ctxt,
                did: ast::DefId) -> Vec<clean::Item> {
     ty::populate_implementations_for_type_if_necessary(tcx, did);
     let mut impls = Vec::new();
@@ -205,6 +206,38 @@ fn build_impls(tcx: &ty::ctxt,
         }
     }
 
+    // If this is the first time we've inlined something from this crate, then
+    // we inline *all* impls from the crate into this crate. Note that there's
+    // currently no way for us to filter this based on type, and we likely need
+    // many impls for a variety of reasons.
+    //
+    // Primarily, the impls will be used to populate the documentation for this
+    // type being inlined, but impls can also be used when generating
+    // documentation for primitives (no way to find those specifically).
+    if cx.populated_crate_impls.borrow_mut().insert(did.krate) {
+        csearch::each_top_level_item_of_crate(&tcx.sess.cstore,
+                                              did.krate,
+                                              |def, _, _| {
+            populate_impls(tcx, def, &mut impls)
+        });
+
+        fn populate_impls(tcx: &ty::ctxt,
+                          def: decoder::DefLike,
+                          impls: &mut Vec<clean::Item>) {
+            match def {
+                decoder::DlImpl(did) => impls.push(build_impl(tcx, did)),
+                decoder::DlDef(ast::DefMod(did)) => {
+                    csearch::each_child_of_item(&tcx.sess.cstore,
+                                                did,
+                                                |def, _, _| {
+                        populate_impls(tcx, def, impls)
+                    })
+                }
+                _ => {}
+            }
+        }
+    }
+
     impls
 }
 
@@ -268,7 +301,8 @@ fn build_module(cx: &core::DocContext, tcx: &ty::ctxt,
                     None => {}
                 }
             }
-            decoder::DlImpl(did) => items.push(build_impl(tcx, did)),
+            // All impls were inlined above
+            decoder::DlImpl(..) => {}
             decoder::DlField => fail!("unimplemented field"),
         }
     });
index 27e39e1235c67ff44d7dc91acd2b2fcf460107c5..87b19fecb1f2025bf97747982767b7c5ef944e92 100644 (file)
@@ -42,6 +42,7 @@ pub struct DocContext {
     pub external_traits: RefCell<Option<HashMap<ast::DefId, clean::Trait>>>,
     pub external_typarams: RefCell<Option<HashMap<ast::DefId, String>>>,
     pub inlined: RefCell<Option<HashSet<ast::DefId>>>,
+    pub populated_crate_impls: RefCell<HashSet<ast::CrateNum>>,
 }
 
 impl DocContext {
@@ -114,6 +115,7 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<String>)
         external_typarams: RefCell::new(Some(HashMap::new())),
         external_paths: RefCell::new(Some(HashMap::new())),
         inlined: RefCell::new(Some(HashSet::new())),
+        populated_crate_impls: RefCell::new(HashSet::new()),
     }, CrateAnalysis {
         exported_items: exported_items,
         public_items: public_items,
index e5fc8f1f1a178fffa5ad2aa9f1abef06bd0f862b..c1f61de9be2f72c09d7b3335a6e3450dc86c3629 100644 (file)
@@ -79,6 +79,7 @@ pub fn run(input: &str,
         external_traits: RefCell::new(None),
         external_typarams: RefCell::new(None),
         inlined: RefCell::new(None),
+        populated_crate_impls: RefCell::new(HashSet::new()),
     };
     super::ctxtkey.replace(Some(ctx));