提交 77b409a6 编写于 作者: M mitaa

Reachability check cross-crate links

上级 cfad7ad9
......@@ -26,7 +26,7 @@
use rustc_const_eval::lookup_const_by_id;
use core::DocContext;
use core::{DocContext, DocAccessLevels};
use doctree;
use clean::{self, GetDefId};
......@@ -227,15 +227,6 @@ fn build_type(cx: &DocContext, tcx: &TyCtxt, did: DefId) -> clean::ItemEnum {
}, false)
}
fn is_item_doc_reachable(cx: &DocContext, did: DefId) -> bool {
use ::visit_lib::LibEmbargoVisitor;
if cx.analyzed_crates.borrow_mut().insert(did.krate) {
LibEmbargoVisitor::new(cx).visit_lib(did.krate);
}
cx.access_levels.borrow().is_public(did)
}
pub fn build_impls(cx: &DocContext,
tcx: &TyCtxt,
did: DefId) -> Vec<clean::Item> {
......@@ -309,7 +300,7 @@ pub fn build_impl(cx: &DocContext,
// Only inline impl if the implemented trait is
// reachable in rustdoc generated documentation
if let Some(traitref) = associated_trait {
if !is_item_doc_reachable(cx, traitref.def_id) {
if !cx.access_levels.borrow().is_doc_reachable(traitref.def_id) {
return
}
}
......@@ -341,7 +332,7 @@ pub fn build_impl(cx: &DocContext,
// Only inline impl if the implementing type is
// reachable in rustdoc generated documentation
if let Some(did) = for_.def_id() {
if !is_item_doc_reachable(cx, did) {
if !cx.access_levels.borrow().is_doc_reachable(did) {
return
}
}
......
......@@ -133,6 +133,7 @@ pub struct Crate {
impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
fn clean(&self, cx: &DocContext) -> Crate {
use rustc::session::config::Input;
use ::visit_lib::LibEmbargoVisitor;
if let Some(t) = cx.tcx_opt() {
cx.deref_trait_did.set(t.lang_items.deref_trait());
......@@ -142,6 +143,10 @@ fn clean(&self, cx: &DocContext) -> Crate {
let mut externs = Vec::new();
for cnum in cx.sess().cstore.crates() {
externs.push((cnum, CrateNum(cnum).clean(cx)));
if cx.tcx_opt().is_some() {
// Analyze doc-reachability for extern items
LibEmbargoVisitor::new(cx).visit_lib(cnum);
}
}
externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
......
......@@ -14,7 +14,6 @@
use rustc::dep_graph::DepGraph;
use rustc::session::{self, config};
use rustc::hir::def_id::DefId;
use rustc::middle::cstore::LOCAL_CRATE;
use rustc::middle::privacy::AccessLevels;
use rustc::ty::{self, TyCtxt};
use rustc::hir::map as hir_map;
......@@ -30,7 +29,7 @@
use syntax::parse::token;
use std::cell::{RefCell, Cell};
use std::collections::{HashMap, HashSet};
use std::collections::HashMap;
use std::rc::Rc;
use visit_ast::RustdocVisitor;
......@@ -47,6 +46,7 @@ pub enum MaybeTyped<'a, 'tcx: 'a> {
NotTyped(&'a session::Session)
}
pub type Externs = HashMap<String, Vec<String>>;
pub type ExternalPaths = HashMap<DefId, (Vec<String>, clean::TypeKind)>;
pub struct DocContext<'a, 'tcx: 'a> {
......@@ -55,8 +55,6 @@ pub struct DocContext<'a, 'tcx: 'a> {
pub input: Input,
pub all_crate_impls: RefCell<HashMap<ast::CrateNum, Vec<clean::Item>>>,
pub deref_trait_did: Cell<Option<DefId>>,
/// Crates which have already been processed for `Self.access_levels`
pub analyzed_crates: RefCell<HashSet<ast::CrateNum>>,
// 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
// the access levels from crateanalysis.
......@@ -89,7 +87,16 @@ pub fn tcx<'a>(&'a self) -> &'a TyCtxt<'tcx> {
}
}
pub type Externs = HashMap<String, Vec<String>>;
pub trait DocAccessLevels {
fn is_doc_reachable(&self, DefId) -> bool;
}
impl DocAccessLevels for AccessLevels<DefId> {
fn is_doc_reachable(&self, did: DefId) -> bool {
self.is_public(did)
}
}
pub fn run_core(search_paths: SearchPaths,
cfgs: Vec<String>,
......@@ -172,8 +179,6 @@ pub fn run_core(search_paths: SearchPaths,
.map(|(k, v)| (tcx.map.local_def_id(k), v))
.collect()
};
let mut analyzed_crates = HashSet::new();
analyzed_crates.insert(LOCAL_CRATE);
let ctxt = DocContext {
map: &tcx.map,
......@@ -181,7 +186,6 @@ pub fn run_core(search_paths: SearchPaths,
input: input,
all_crate_impls: RefCell::new(HashMap::new()),
deref_trait_did: Cell::new(None),
analyzed_crates: RefCell::new(analyzed_crates),
access_levels: RefCell::new(access_levels),
external_traits: RefCell::new(HashMap::new()),
renderinfo: RefCell::new(Default::default()),
......
......@@ -24,6 +24,7 @@
use rustc::hir;
use clean;
use core::DocAccessLevels;
use html::item_type::ItemType;
use html::render;
use html::render::{cache, CURRENT_LOCATION_KEY};
......@@ -298,6 +299,9 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec<String>)> {
let mut url = if did.is_local() || cache.inlined.contains(&did) {
repeat("../").take(loc.len()).collect::<String>()
} else {
if !cache.access_levels.is_doc_reachable(did) {
return None
}
match cache.extern_locations[&did.krate] {
(_, render::Remote(ref s)) => s.to_string(),
(_, render::Local) => repeat("../").take(loc.len()).collect(),
......
......@@ -246,6 +246,11 @@ pub struct Cache {
/// Set of definitions which have been inlined from external crates.
pub inlined: HashSet<DefId>,
// 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
// the access levels from crateanalysis.
pub access_levels: Arc<AccessLevels<DefId>>,
// Private fields only used when initially crawling a crate to build a cache
stack: Vec<String>,
......@@ -253,10 +258,6 @@ pub struct Cache {
parent_is_trait_impl: bool,
search_index: Vec<IndexItem>,
stripped_mod: 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
// the access levels from crateanalysis.
access_levels: Arc<AccessLevels<DefId>>,
deref_trait_did: Option<DefId>,
// In rare case where a structure is defined in one module but implemented
......
......@@ -9,7 +9,7 @@
// except according to those terms.
use std::cell::{RefCell, Cell};
use std::collections::{HashMap, HashSet};
use std::collections::HashMap;
use std::env;
use std::ffi::OsString;
use std::io::prelude::*;
......@@ -111,7 +111,6 @@ pub fn run(input: &str,
external_traits: RefCell::new(HashMap::new()),
all_crate_impls: RefCell::new(HashMap::new()),
deref_trait_did: Cell::new(None),
analyzed_crates: RefCell::new(HashSet::new()),
access_levels: Default::default(),
renderinfo: Default::default(),
};
......
......@@ -19,8 +19,7 @@
use clean::{Attributes, Clean};
// FIXME: since this is only used for cross-crate impl inlining this only
// handles traits and items for which traits can be implemented
// FIXME: this may not be exhaustive, but is sufficient for rustdocs current uses
/// Similar to `librustc_privacy::EmbargoVisitor`, but also takes
/// specific rustdoc annotations into account (i.e. `doc(hidden)`)
......@@ -69,11 +68,16 @@ pub fn visit_mod(&mut self, did: DefId) {
for item in self.cstore.item_children(did) {
if let DefLike::DlDef(def) = item.def {
match def {
Def::Mod(did) |
Def::ForeignMod(did) |
Def::Trait(did) |
Def::Struct(did) |
Def::Mod(did) |
Def::Enum(did) |
Def::TyAlias(did) => self.visit_item(did, item),
Def::TyAlias(did) |
Def::Fn(did) |
Def::Method(did) |
Def::Static(did, _) |
Def::Const(did) => self.visit_item(did, item),
_ => {}
}
}
......
// Copyright 2016 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.
pub struct Bar;
impl Bar {
pub fn bar(_: u8) -> hidden::Hidden {
hidden::Hidden
}
}
#[doc(hidden)]
pub mod hidden {
pub struct Hidden;
}
// Copyright 2016 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.
// aux-build:rustdoc-hidden-sig.rs
// build-aux-docs
// ignore-cross-compile
// @has rustdoc_hidden_sig/struct.Bar.html
// @!has - '//a/@title' 'Hidden'
// @has - '//a' 'u8'
extern crate rustdoc_hidden_sig;
// @has issue_28480/struct.Bar.html
// @!has - '//a/@title' 'Hidden'
// @has - '//a' 'u8'
pub use rustdoc_hidden_sig::Bar;
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册