1
Fork 0

Fix lints handling in rustdoc

This commit is contained in:
Guillaume Gomez 2019-05-16 18:31:53 +02:00
parent 548add7f61
commit b5d4bd2a07
6 changed files with 85 additions and 17 deletions

View file

@ -778,6 +778,9 @@ fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum)
let push = builder.levels.push(&krate.attrs); let push = builder.levels.push(&krate.attrs);
builder.levels.register_id(hir::CRATE_HIR_ID); builder.levels.register_id(hir::CRATE_HIR_ID);
for macro_def in &krate.exported_macros {
builder.levels.register_id(macro_def.hir_id);
}
intravisit::walk_crate(&mut builder, krate); intravisit::walk_crate(&mut builder, krate);
builder.levels.pop(push); builder.levels.pop(push);

View file

@ -3405,6 +3405,7 @@ pub struct Span {
pub locol: usize, pub locol: usize,
pub hiline: usize, pub hiline: usize,
pub hicol: usize, pub hicol: usize,
pub original: syntax_pos::Span,
} }
impl Span { impl Span {
@ -3413,8 +3414,13 @@ impl Span {
filename: FileName::Anon(0), filename: FileName::Anon(0),
loline: 0, locol: 0, loline: 0, locol: 0,
hiline: 0, hicol: 0, hiline: 0, hicol: 0,
original: syntax_pos::DUMMY_SP,
} }
} }
pub fn span(&self) -> syntax_pos::Span {
self.original
}
} }
impl Clean<Span> for syntax_pos::Span { impl Clean<Span> for syntax_pos::Span {
@ -3433,6 +3439,7 @@ impl Clean<Span> for syntax_pos::Span {
locol: lo.col.to_usize(), locol: lo.col.to_usize(),
hiline: hi.line, hiline: hi.line,
hicol: hi.col.to_usize(), hicol: hi.col.to_usize(),
original: *self,
} }
} }
} }

View file

@ -321,7 +321,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
if let Ok(res) = self.resolve(path_str, ns, &current_item, parent_node) { if let Ok(res) = self.resolve(path_str, ns, &current_item, parent_node) {
res res
} else { } else {
resolution_failure(cx, &item.attrs, path_str, &dox, link_range); resolution_failure(cx, &item, path_str, &dox, link_range);
// This could just be a normal link or a broken link // This could just be a normal link or a broken link
// we could potentially check if something is // we could potentially check if something is
// "intra-doc-link-like" and warn in that case. // "intra-doc-link-like" and warn in that case.
@ -332,7 +332,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
if let Ok(res) = self.resolve(path_str, ns, &current_item, parent_node) { if let Ok(res) = self.resolve(path_str, ns, &current_item, parent_node) {
res res
} else { } else {
resolution_failure(cx, &item.attrs, path_str, &dox, link_range); resolution_failure(cx, &item, path_str, &dox, link_range);
// This could just be a normal link. // This could just be a normal link.
continue; continue;
} }
@ -357,7 +357,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
}; };
if candidates.is_empty() { if candidates.is_empty() {
resolution_failure(cx, &item.attrs, path_str, &dox, link_range); resolution_failure(cx, &item, path_str, &dox, link_range);
// this could just be a normal link // this could just be a normal link
continue; continue;
} }
@ -368,7 +368,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
} else { } else {
ambiguity_error( ambiguity_error(
cx, cx,
&item.attrs, &item,
path_str, path_str,
&dox, &dox,
link_range, link_range,
@ -381,7 +381,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
if let Some(res) = macro_resolve(cx, path_str) { if let Some(res) = macro_resolve(cx, path_str) {
(res, None) (res, None)
} else { } else {
resolution_failure(cx, &item.attrs, path_str, &dox, link_range); resolution_failure(cx, &item, path_str, &dox, link_range);
continue continue
} }
} }
@ -452,16 +452,24 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
/// line containing the failure as a note as well. /// line containing the failure as a note as well.
fn resolution_failure( fn resolution_failure(
cx: &DocContext<'_>, cx: &DocContext<'_>,
attrs: &Attributes, item: &Item,
path_str: &str, path_str: &str,
dox: &str, dox: &str,
link_range: Option<Range<usize>>, link_range: Option<Range<usize>>,
) { ) {
let hir_id = match cx.as_local_hir_id(item.def_id) {
Some(hir_id) => hir_id,
None => {
// If non-local, no need to check anything.
return;
}
};
let attrs = &item.attrs;
let sp = span_of_attrs(attrs); let sp = span_of_attrs(attrs);
let mut diag = cx.tcx.struct_span_lint_hir( let mut diag = cx.tcx.struct_span_lint_hir(
lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
hir::CRATE_HIR_ID, hir_id,
sp, sp,
&format!("`[{}]` cannot be resolved, ignoring it...", path_str), &format!("`[{}]` cannot be resolved, ignoring it...", path_str),
); );
@ -495,12 +503,20 @@ fn resolution_failure(
fn ambiguity_error( fn ambiguity_error(
cx: &DocContext<'_>, cx: &DocContext<'_>,
attrs: &Attributes, item: &Item,
path_str: &str, path_str: &str,
dox: &str, dox: &str,
link_range: Option<Range<usize>>, link_range: Option<Range<usize>>,
candidates: PerNS<Option<Res>>, candidates: PerNS<Option<Res>>,
) { ) {
let hir_id = match cx.as_local_hir_id(item.def_id) {
Some(hir_id) => hir_id,
None => {
// If non-local, no need to check anything.
return;
}
};
let attrs = &item.attrs;
let sp = span_of_attrs(attrs); let sp = span_of_attrs(attrs);
let mut msg = format!("`{}` is ", path_str); let mut msg = format!("`{}` is ", path_str);
@ -532,7 +548,7 @@ fn ambiguity_error(
let mut diag = cx.tcx.struct_span_lint_hir( let mut diag = cx.tcx.struct_span_lint_hir(
lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
hir::CRATE_HIR_ID, hir_id,
sp, sp,
&msg, &msg,
); );

View file

@ -1,7 +1,6 @@
//! Contains information about "passes", used to modify crate information during the documentation //! Contains information about "passes", used to modify crate information during the documentation
//! process. //! process.
use rustc::hir;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::lint as lint; use rustc::lint as lint;
use rustc::middle::privacy::AccessLevels; use rustc::middle::privacy::AccessLevels;
@ -314,10 +313,13 @@ pub fn look_for_tests<'tcx>(
item: &Item, item: &Item,
check_missing_code: bool, check_missing_code: bool,
) { ) {
if cx.as_local_hir_id(item.def_id).is_none() { let hir_id = match cx.as_local_hir_id(item.def_id) {
// If non-local, no need to check anything. Some(hir_id) => hir_id,
return; None => {
} // If non-local, no need to check anything.
return;
}
};
struct Tests { struct Tests {
found_tests: usize, found_tests: usize,
@ -336,10 +338,11 @@ pub fn look_for_tests<'tcx>(
find_testable_code(&dox, &mut tests, ErrorCodes::No); find_testable_code(&dox, &mut tests, ErrorCodes::No);
if check_missing_code == true && tests.found_tests == 0 { if check_missing_code == true && tests.found_tests == 0 {
let sp = span_of_attrs(&item.attrs).substitute_dummy(item.source.span());
let mut diag = cx.tcx.struct_span_lint_hir( let mut diag = cx.tcx.struct_span_lint_hir(
lint::builtin::MISSING_DOC_CODE_EXAMPLES, lint::builtin::MISSING_DOC_CODE_EXAMPLES,
hir::CRATE_HIR_ID, hir_id,
span_of_attrs(&item.attrs), sp,
"Missing code example in this documentation"); "Missing code example in this documentation");
diag.emit(); diag.emit();
} else if check_missing_code == false && } else if check_missing_code == false &&
@ -347,7 +350,7 @@ pub fn look_for_tests<'tcx>(
!cx.renderinfo.borrow().access_levels.is_doc_reachable(item.def_id) { !cx.renderinfo.borrow().access_levels.is_doc_reachable(item.def_id) {
let mut diag = cx.tcx.struct_span_lint_hir( let mut diag = cx.tcx.struct_span_lint_hir(
lint::builtin::PRIVATE_DOC_TESTS, lint::builtin::PRIVATE_DOC_TESTS,
hir::CRATE_HIR_ID, hir_id,
span_of_attrs(&item.attrs), span_of_attrs(&item.attrs),
"Documentation test in private item"); "Documentation test in private item");
diag.emit(); diag.emit();

View file

@ -0,0 +1,39 @@
#![deny(missing_docs)]
#![deny(missing_doc_code_examples)]
//! crate level doc
//! ```
//! println!("hello"):
//! ```
/// doc
///
/// ```
/// println!("hello");
/// ```
fn test() {
}
#[allow(missing_docs)]
mod module1 {
}
#[allow(missing_doc_code_examples)]
/// doc
mod module2 {
/// doc
pub fn test() {}
}
/// doc
///
/// ```
/// println!("hello");
/// ```
pub mod module3 {
/// doc
pub fn test() {}
}