rustdoc: adopt to the new lint API

This commit is contained in:
Maybe Waffle 2022-09-16 19:07:20 +04:00
parent 7e90a41844
commit 6ecacf76bc
7 changed files with 61 additions and 78 deletions

View File

@ -404,12 +404,8 @@ pub(crate) fn run_global_ctxt(
tcx.struct_lint_node( tcx.struct_lint_node(
crate::lint::MISSING_CRATE_LEVEL_DOCS, crate::lint::MISSING_CRATE_LEVEL_DOCS,
DocContext::as_local_hir_id(tcx, krate.module.item_id).unwrap(), DocContext::as_local_hir_id(tcx, krate.module.item_id).unwrap(),
|lint| { "no documentation found for this crate's top-level module",
let mut diag = |lint| lint.help(help),
lint.build("no documentation found for this crate's top-level module");
diag.help(&help);
diag.emit();
},
); );
} }

View File

@ -813,11 +813,8 @@ impl<'tcx> ExtraInfo<'tcx> {
crate::lint::INVALID_CODEBLOCK_ATTRIBUTES, crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
hir_id, hir_id,
self.sp, self.sp,
|lint| { msg,
let mut diag = lint.build(msg); |lint| lint.help(help),
diag.help(help);
diag.emit();
},
); );
} }
} }

View File

@ -71,16 +71,14 @@ impl<'a, 'tcx> DocVisitor for BareUrlsLinter<'a, 'tcx> {
let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| { let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| {
let sp = super::source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs) let sp = super::source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs)
.unwrap_or_else(|| item.attr_span(cx.tcx)); .unwrap_or_else(|| item.attr_span(cx.tcx));
cx.tcx.struct_span_lint_hir(crate::lint::BARE_URLS, hir_id, sp, |lint| { cx.tcx.struct_span_lint_hir(crate::lint::BARE_URLS, hir_id, sp, msg, |lint| {
lint.build(msg) lint.note("bare URLs are not automatically turned into clickable links")
.note("bare URLs are not automatically turned into clickable links")
.span_suggestion( .span_suggestion(
sp, sp,
"use an automatic link instead", "use an automatic link instead",
format!("<{}>", url), format!("<{}>", url),
Applicability::MachineApplicable, Applicability::MachineApplicable,
) )
.emit();
}); });
}; };

View File

@ -2,7 +2,7 @@
use rustc_data_structures::sync::{Lock, Lrc}; use rustc_data_structures::sync::{Lock, Lrc};
use rustc_errors::{ use rustc_errors::{
emitter::Emitter, translation::Translate, Applicability, Diagnostic, Handler, emitter::Emitter, translation::Translate, Applicability, Diagnostic, Handler,
LazyFallbackBundle, LintDiagnosticBuilder, LazyFallbackBundle,
}; };
use rustc_parse::parse_stream_from_source_str; use rustc_parse::parse_stream_from_source_str;
use rustc_session::parse::ParseSess; use rustc_session::parse::ParseSess;
@ -97,48 +97,10 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
None => (item.attr_span(self.cx.tcx), false), None => (item.attr_span(self.cx.tcx), false),
}; };
// lambda that will use the lint to start a new diagnostic and add let msg = if buffer.has_errors {
// a suggestion to it when needed. "could not parse code block as Rust code"
let diag_builder = |lint: LintDiagnosticBuilder<'_, ()>| { } else {
let explanation = if is_ignore { "Rust code block is empty"
"`ignore` code blocks require valid Rust code for syntax highlighting; \
mark blocks that do not contain Rust code as text"
} else {
"mark blocks that do not contain Rust code as text"
};
let msg = if buffer.has_errors {
"could not parse code block as Rust code"
} else {
"Rust code block is empty"
};
let mut diag = lint.build(msg);
if precise_span {
if is_ignore {
// giving an accurate suggestion is hard because `ignore` might not have come first in the list.
// just give a `help` instead.
diag.span_help(
sp.from_inner(InnerSpan::new(0, 3)),
&format!("{}: ```text", explanation),
);
} else if empty_block {
diag.span_suggestion(
sp.from_inner(InnerSpan::new(0, 3)).shrink_to_hi(),
explanation,
"text",
Applicability::MachineApplicable,
);
}
} else if empty_block || is_ignore {
diag.help(&format!("{}: ```text", explanation));
}
// FIXME(#67563): Provide more context for these errors by displaying the spans inline.
for message in buffer.messages.iter() {
diag.note(message);
}
diag.emit();
}; };
// Finally build and emit the completed diagnostic. // Finally build and emit the completed diagnostic.
@ -148,7 +110,42 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
crate::lint::INVALID_RUST_CODEBLOCKS, crate::lint::INVALID_RUST_CODEBLOCKS,
hir_id, hir_id,
sp, sp,
diag_builder, msg,
|lint| {
let explanation = if is_ignore {
"`ignore` code blocks require valid Rust code for syntax highlighting; \
mark blocks that do not contain Rust code as text"
} else {
"mark blocks that do not contain Rust code as text"
};
if precise_span {
if is_ignore {
// giving an accurate suggestion is hard because `ignore` might not have come first in the list.
// just give a `help` instead.
lint.span_help(
sp.from_inner(InnerSpan::new(0, 3)),
&format!("{}: ```text", explanation),
);
} else if empty_block {
lint.span_suggestion(
sp.from_inner(InnerSpan::new(0, 3)).shrink_to_hi(),
explanation,
"text",
Applicability::MachineApplicable,
);
}
} else if empty_block || is_ignore {
lint.help(&format!("{}: ```text", explanation));
}
// FIXME(#67563): Provide more context for these errors by displaying the spans inline.
for message in buffer.messages.iter() {
lint.note(message);
}
lint
},
); );
} }
} }

View File

@ -125,9 +125,8 @@ pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item
crate::lint::MISSING_DOC_CODE_EXAMPLES, crate::lint::MISSING_DOC_CODE_EXAMPLES,
hir_id, hir_id,
sp, sp,
|lint| { "missing code example in this documentation",
lint.build("missing code example in this documentation").emit(); |lint| lint,
},
); );
} }
} else if tests.found_tests > 0 } else if tests.found_tests > 0
@ -137,9 +136,8 @@ pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item
crate::lint::PRIVATE_DOC_TESTS, crate::lint::PRIVATE_DOC_TESTS,
hir_id, hir_id,
item.attr_span(cx.tcx), item.attr_span(cx.tcx),
|lint| { "documentation test in private item",
lint.build("documentation test in private item").emit(); |lint| lint,
},
); );
} }
} }

View File

@ -1609,9 +1609,7 @@ fn report_diagnostic(
let sp = item.attr_span(tcx); let sp = item.attr_span(tcx);
tcx.struct_span_lint_hir(lint, hir_id, sp, |lint| { tcx.struct_span_lint_hir(lint, hir_id, sp, msg, |lint| {
let mut diag = lint.build(msg);
let span = let span =
super::source_span_for_markdown_range(tcx, dox, link_range, &item.attrs).map(|sp| { super::source_span_for_markdown_range(tcx, dox, link_range, &item.attrs).map(|sp| {
if dox.as_bytes().get(link_range.start) == Some(&b'`') if dox.as_bytes().get(link_range.start) == Some(&b'`')
@ -1624,7 +1622,7 @@ fn report_diagnostic(
}); });
if let Some(sp) = span { if let Some(sp) = span {
diag.set_span(sp); lint.set_span(sp);
} else { } else {
// blah blah blah\nblah\nblah [blah] blah blah\nblah blah // blah blah blah\nblah\nblah [blah] blah blah\nblah blah
// ^ ~~~~ // ^ ~~~~
@ -1634,7 +1632,7 @@ fn report_diagnostic(
let line = dox[last_new_line_offset..].lines().next().unwrap_or(""); let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
// Print the line containing the `link_range` and manually mark it with '^'s. // Print the line containing the `link_range` and manually mark it with '^'s.
diag.note(&format!( lint.note(&format!(
"the link appears in this line:\n\n{line}\n\ "the link appears in this line:\n\n{line}\n\
{indicator: <before$}{indicator:^<found$}", {indicator: <before$}{indicator:^<found$}",
line = line, line = line,
@ -1644,9 +1642,9 @@ fn report_diagnostic(
)); ));
} }
decorate(&mut diag, span); decorate(lint, span);
diag.emit(); lint
}); });
} }

View File

@ -240,9 +240,8 @@ impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
Some(sp) => sp, Some(sp) => sp,
None => item.attr_span(tcx), None => item.attr_span(tcx),
}; };
tcx.struct_span_lint_hir(crate::lint::INVALID_HTML_TAGS, hir_id, sp, |lint| { tcx.struct_span_lint_hir(crate::lint::INVALID_HTML_TAGS, hir_id, sp, msg, |lint| {
use rustc_lint_defs::Applicability; use rustc_lint_defs::Applicability;
let mut diag = lint.build(msg);
// If a tag looks like `<this>`, it might actually be a generic. // If a tag looks like `<this>`, it might actually be a generic.
// We don't try to detect stuff `<like, this>` because that's not valid HTML, // We don't try to detect stuff `<like, this>` because that's not valid HTML,
// and we don't try to detect stuff `<like this>` because that's not valid Rust. // and we don't try to detect stuff `<like this>` because that's not valid Rust.
@ -305,11 +304,10 @@ impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
if (generics_start > 0 && dox.as_bytes()[generics_start - 1] == b'<') if (generics_start > 0 && dox.as_bytes()[generics_start - 1] == b'<')
|| (generics_end < dox.len() && dox.as_bytes()[generics_end] == b'>') || (generics_end < dox.len() && dox.as_bytes()[generics_end] == b'>')
{ {
diag.emit(); return lint;
return;
} }
// multipart form is chosen here because ``Vec<i32>`` would be confusing. // multipart form is chosen here because ``Vec<i32>`` would be confusing.
diag.multipart_suggestion( lint.multipart_suggestion(
"try marking as source code", "try marking as source code",
vec![ vec![
(generics_sp.shrink_to_lo(), String::from("`")), (generics_sp.shrink_to_lo(), String::from("`")),
@ -318,7 +316,8 @@ impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
} }
diag.emit()
lint
}); });
}; };