]> git.lizzy.rs Git - rust.git/commitdiff
resolve paths when cleaning docs
authorQuietMisdreavus <grey@quietmisdreavus.net>
Fri, 22 Dec 2017 19:12:54 +0000 (13:12 -0600)
committerManish Goregaokar <manishsmail@gmail.com>
Mon, 22 Jan 2018 09:51:28 +0000 (15:21 +0530)
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs
src/librustdoc/html/markdown.rs

index 6b58decd0b5d810277a6708543c6658f20e12cd3..3f7750cacc2cf03b04acabba0f063a86406ae25b 100644 (file)
@@ -23,8 +23,9 @@
 use syntax::ast;
 use syntax::attr;
 use syntax::codemap::Spanned;
+use syntax::feature_gate::UnstableFeatures;
 use syntax::ptr::P;
-use syntax::symbol::keywords;
+use syntax::symbol::{keywords, Symbol};
 use syntax_pos::{self, DUMMY_SP, Pos, FileName};
 
 use rustc::middle::const_val::ConstVal;
@@ -33,6 +34,7 @@
 use rustc::middle::lang_items;
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc::hir::lowering::Resolver;
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, AdtKind};
 use rustc::middle::stability;
@@ -43,7 +45,7 @@
 
 use rustc_const_math::ConstInt;
 use std::default::Default;
-use std::{mem, slice, vec};
+use std::{mem, slice, vec, iter};
 use std::iter::FromIterator;
 use std::rc::Rc;
 use std::sync::Arc;
@@ -53,6 +55,7 @@
 use doctree;
 use visit_ast;
 use html::item_type::ItemType;
+use html::markdown::markdown_links;
 
 pub mod inline;
 pub mod cfg;
@@ -633,6 +636,7 @@ pub struct Attributes {
     pub other_attrs: Vec<ast::Attribute>,
     pub cfg: Option<Rc<Cfg>>,
     pub span: Option<syntax_pos::Span>,
+    pub links: Vec<(String, DefId)>,
 }
 
 impl Attributes {
@@ -762,11 +766,13 @@ pub fn from_ast(diagnostic: &::errors::Handler,
                 Some(attr.clone())
             })
         }).collect();
+
         Attributes {
             doc_strings,
             other_attrs,
             cfg: if cfg == Cfg::True { None } else { Some(Rc::new(cfg)) },
             span: sp,
+            links: vec![],
         }
     }
 
@@ -795,7 +801,38 @@ fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a> {
 
 impl Clean<Attributes> for [ast::Attribute] {
     fn clean(&self, cx: &DocContext) -> Attributes {
-        Attributes::from_ast(cx.sess().diagnostic(), self)
+        let mut attrs = Attributes::from_ast(cx.sess().diagnostic(), self);
+
+        if UnstableFeatures::from_environment().is_nightly_build() {
+            let dox = attrs.collapsed_doc_value().unwrap_or_else(String::new);
+            for link in markdown_links(&dox, cx.render_type) {
+                if !link.starts_with("::") {
+                    // FIXME (misdreavus): can only support absolute paths because of limitations
+                    // in Resolver. this may, with a lot of effort, figure out how to resolve paths
+                    // within scopes, but the one use of `resolve_hir_path` i found in the HIR
+                    // lowering code itself used an absolute path. we're brushing up against some
+                    // structural limitations in the compiler already, but this may be a design one
+                    // as well >_>
+                    continue;
+                }
+
+                let mut path = hir::Path {
+                    span: DUMMY_SP,
+                    def: Def::Err,
+                    segments: iter::once(keywords::CrateRoot.name()).chain({
+                        link.split("::").skip(1).map(Symbol::intern)
+                    }).map(hir::PathSegment::from_name).collect(),
+                };
+
+                cx.resolver.borrow_mut().resolve_hir_path(&mut path, false);
+
+                if path.def != Def::Err {
+                    attrs.links.push((link, path.def.def_id()));
+                }
+            }
+        }
+
+        attrs
     }
 }
 
index b094567b15ea5f143c98359d8b0e480b59422a31..008285e96533670a4410cdb29a4edb13f981914c 100644 (file)
@@ -46,7 +46,7 @@
 
 pub struct DocContext<'a, 'tcx: 'a, 'rcx> {
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    pub resolver: resolve::Resolver<'rcx>,
+    pub resolver: RefCell<resolve::Resolver<'rcx>>,
     pub populated_all_crate_impls: Cell<bool>,
     // Note that external items for which `doc(hidden)` applies to are shown as
     // non-reachable while local items aren't. This is because we're reusing
@@ -227,7 +227,7 @@ pub fn run_core(search_paths: SearchPaths,
 
         let ctxt = DocContext {
             tcx,
-            resolver,
+            resolver: RefCell::new(resolver),
             populated_all_crate_impls: Cell::new(false),
             access_levels: RefCell::new(access_levels),
             external_traits: Default::default(),
index 498c8911dc0362b79b9347279b21f7bc2bef5e42..9bb35da246c8991c6f7236492e4bc710aa1e5072 100644 (file)
@@ -1169,6 +1169,8 @@ pub fn markdown_links(md: &str, render_type: RenderType) -> Vec<String> {
                     let s = unsafe { (*link).as_bytes() };
                     let s = str::from_utf8(&s).unwrap().to_owned();
 
+                    debug!("found link: {}", s);
+
                     links.push(s);
                 }
 
@@ -1214,6 +1216,7 @@ pub fn markdown_links(md: &str, render_type: RenderType) -> Vec<String> {
 
             for ev in iter {
                 if let Event::Start(Tag::Link(dest, _)) = ev {
+                    debug!("found link: {}", dest);
                     links.push(dest.into_owned());
                 }
             }