mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-20 19:52:48 +00:00
Reachability check cross-crate links
This commit is contained in:
parent
cfad7ad947
commit
77b409a674
@ -26,7 +26,7 @@ use rustc::middle::stability;
|
||||
|
||||
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 @@ struct CrateNum(ast::CrateNum);
|
||||
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 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
|
||||
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_driver::{driver, target_features, abort_on_err};
|
||||
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::feature_gate::UnstableFeatures;
|
||||
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 @@ impl<'b, 'tcx> DocContext<'b, '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 syntax::abi::Abi;
|
||||
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 std::cell::RefMut;
|
||||
|
||||
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 @@ impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> {
|
||||
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),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
22
src/test/auxiliary/rustdoc-hidden-sig.rs
Normal file
22
src/test/auxiliary/rustdoc-hidden-sig.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// 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;
|
||||
}
|
23
src/test/rustdoc/inline_cross/issue-28480.rs
Normal file
23
src/test/rustdoc/inline_cross/issue-28480.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// 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;
|
Loading…
Reference in New Issue
Block a user