Fix lints handling in rustdoc
This commit is contained in:
parent
548add7f61
commit
b5d4bd2a07
6 changed files with 85 additions and 17 deletions
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -321,7 +321,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
|
||||||
if let Ok(res) = self.resolve(path_str, ns, ¤t_item, parent_node) {
|
if let Ok(res) = self.resolve(path_str, ns, ¤t_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, ¤t_item, parent_node) {
|
if let Ok(res) = self.resolve(path_str, ns, ¤t_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,
|
||||||
);
|
);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
39
src/test/rustdoc-ui/lint-missing-doc-code-example.rs
Normal file
39
src/test/rustdoc-ui/lint-missing-doc-code-example.rs
Normal 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() {}
|
||||||
|
}
|
0
src/test/rustdoc-ui/lint-missing-doc-code-example.stderr
Normal file
0
src/test/rustdoc-ui/lint-missing-doc-code-example.stderr
Normal file
Loading…
Add table
Add a link
Reference in a new issue