Rollup merge of #60908 - GuillaumeGomez:errors, r=oli-obk

Fix lints handling in rustdoc

Part of #60664: now lints are handled just like any other lints you would setup in rustc. Still remains to handle `missing code examples` and `missing_docs` as part of the same group.

r? @oli-obk
This commit is contained in:
Mazdak Farrokhzad 2019-05-20 01:01:41 +02:00 committed by GitHub
commit 986aa36ed1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 123 additions and 25 deletions

View File

@ -683,7 +683,7 @@ impl Step for RustdocUi {
target: self.target,
mode: "ui",
suite: "rustdoc-ui",
path: None,
path: Some("src/test/rustdoc-ui"),
compare_mode: None,
})
}

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);
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);
builder.levels.pop(push);

View File

@ -3408,6 +3408,7 @@ pub struct Span {
pub locol: usize,
pub hiline: usize,
pub hicol: usize,
pub original: syntax_pos::Span,
}
impl Span {
@ -3416,8 +3417,13 @@ impl Span {
filename: FileName::Anon(0),
loline: 0, locol: 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 {
@ -3436,6 +3442,7 @@ impl Clean<Span> for syntax_pos::Span {
locol: lo.col.to_usize(),
hiline: hi.line,
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) {
res
} 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
// we could potentially check if something is
// "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) {
res
} 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.
continue;
}
@ -357,7 +357,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
};
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
continue;
}
@ -368,7 +368,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
} else {
ambiguity_error(
cx,
&item.attrs,
&item,
path_str,
&dox,
link_range,
@ -381,7 +381,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
if let Some(res) = macro_resolve(cx, path_str) {
(res, None)
} else {
resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
resolution_failure(cx, &item, path_str, &dox, link_range);
continue
}
}
@ -452,16 +452,24 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
/// line containing the failure as a note as well.
fn resolution_failure(
cx: &DocContext<'_>,
attrs: &Attributes,
item: &Item,
path_str: &str,
dox: &str,
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 mut diag = cx.tcx.struct_span_lint_hir(
lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
hir::CRATE_HIR_ID,
hir_id,
sp,
&format!("`[{}]` cannot be resolved, ignoring it...", path_str),
);
@ -495,12 +503,20 @@ fn resolution_failure(
fn ambiguity_error(
cx: &DocContext<'_>,
attrs: &Attributes,
item: &Item,
path_str: &str,
dox: &str,
link_range: Option<Range<usize>>,
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 mut msg = format!("`{}` is ", path_str);
@ -532,7 +548,7 @@ fn ambiguity_error(
let mut diag = cx.tcx.struct_span_lint_hir(
lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
hir::CRATE_HIR_ID,
hir_id,
sp,
&msg,
);

View File

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

View File

@ -1,6 +1,4 @@
//~ ERROR Missing code example in this documentation
#![deny(missing_doc_code_examples)]
#![deny(missing_doc_code_examples)] //~ ERROR Missing code example in this documentation
/// Some docs.
//~^ ERROR Missing code example in this documentation

View File

@ -1,25 +1,35 @@
error: Missing code example in this documentation
--> $DIR/doc-without-codeblock.rs:1:1
|
LL | / #![deny(missing_doc_code_examples)]
LL | |
LL | | /// Some docs.
LL | |
... |
LL | | pub fn bar() {}
LL | | }
| |_^
|
note: lint level defined here
--> $DIR/doc-without-codeblock.rs:3:9
--> $DIR/doc-without-codeblock.rs:1:9
|
LL | #![deny(missing_doc_code_examples)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: Missing code example in this documentation
--> $DIR/doc-without-codeblock.rs:5:1
--> $DIR/doc-without-codeblock.rs:3:1
|
LL | /// Some docs.
| ^^^^^^^^^^^^^^
error: Missing code example in this documentation
--> $DIR/doc-without-codeblock.rs:9:1
--> $DIR/doc-without-codeblock.rs:7:1
|
LL | /// And then, the princess died.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: Missing code example in this documentation
--> $DIR/doc-without-codeblock.rs:12:5
--> $DIR/doc-without-codeblock.rs:10:5
|
LL | /// Or maybe not because she saved herself!
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

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

View File

@ -0,0 +1,21 @@
error: Missing code example in this documentation
--> $DIR/lint-missing-doc-code-example.rs:19:1
|
LL | / mod module1 {
LL | | }
| |_^
|
note: lint level defined here
--> $DIR/lint-missing-doc-code-example.rs:2:9
|
LL | #![deny(missing_doc_code_examples)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: Missing code example in this documentation
--> $DIR/lint-missing-doc-code-example.rs:37:3
|
LL | /// doc
| ^^^^^^^
error: aborting due to 2 previous errors