Rename rustdoc lints to be a tool lint instead of built-in.

- Rename `broken_intra_doc_links` to `rustdoc::broken_intra_doc_links`
- Ensure that the old lint names still work and give deprecation errors
- Register lints even when running doctests

  Otherwise, all `rustdoc::` lints would be ignored.

- Register all existing lints as removed

  This unfortunately doesn't work with `register_renamed` because tool
  lints have not yet been registered when rustc is running. For similar
  reasons, `check_backwards_compat` doesn't work either. Call
  `register_removed` directly instead.

- Fix fallout

  + Rustdoc lints for compiler/
  + Rustdoc lints for library/

Note that this does *not* suggest `rustdoc::broken_intra_doc_links` for
`rustdoc::intra_doc_link_resolution_failure`, since there was no time
when the latter was valid.
This commit is contained in:
Joshua Nelson 2020-12-29 23:16:16 -05:00
parent 4f20caa625
commit cc62018e61
78 changed files with 301 additions and 243 deletions

View file

@ -12,6 +12,8 @@ use rustc_hir::{
Path,
};
use rustc_interface::{interface, Queries};
use rustc_lint::LintStore;
use rustc_lint_defs::{declare_tool_lint, Lint, LintId};
use rustc_middle::hir::map::Map;
use rustc_middle::middle::privacy::AccessLevels;
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
@ -24,9 +26,11 @@ use rustc_span::source_map;
use rustc_span::symbol::sym;
use rustc_span::DUMMY_SP;
use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::lazy::SyncLazy as Lazy;
use std::mem;
use std::rc::Rc;
use std::{cell::RefCell, collections::hash_map::Entry};
use crate::clean;
use crate::clean::inline::build_external_trait;
@ -286,6 +290,106 @@ where
(lint_opts, lint_caps)
}
declare_tool_lint! {
/// The `broken_intra_doc_links` lint detects failures in resolving
/// intra-doc link targets. This is a `rustdoc` only lint, see the
/// documentation in the [rustdoc book].
///
/// [rustdoc book]: ../../../rustdoc/lints.html#broken_intra_doc_links
pub rustdoc::BROKEN_INTRA_DOC_LINKS,
Warn,
"failures in resolving intra-doc link targets"
}
declare_tool_lint! {
/// This is a subset of `broken_intra_doc_links` that warns when linking from
/// a public item to a private one. This is a `rustdoc` only lint, see the
/// documentation in the [rustdoc book].
///
/// [rustdoc book]: ../../../rustdoc/lints.html#private_intra_doc_links
pub rustdoc::PRIVATE_INTRA_DOC_LINKS,
Warn,
"linking from a public item to a private one"
}
declare_tool_lint! {
/// The `invalid_codeblock_attributes` lint detects code block attributes
/// in documentation examples that have potentially mis-typed values. This
/// is a `rustdoc` only lint, see the documentation in the [rustdoc book].
///
/// [rustdoc book]: ../../../rustdoc/lints.html#invalid_codeblock_attributes
pub rustdoc::INVALID_CODEBLOCK_ATTRIBUTES,
Warn,
"codeblock attribute looks a lot like a known one"
}
declare_tool_lint! {
/// The `missing_doc_code_examples` lint detects publicly-exported items
/// without code samples in their documentation. This is a `rustdoc` only
/// lint, see the documentation in the [rustdoc book].
///
/// [rustdoc book]: ../../../rustdoc/lints.html#missing_doc_code_examples
pub rustdoc::MISSING_DOC_CODE_EXAMPLES,
Allow,
"detects publicly-exported items without code samples in their documentation"
}
declare_tool_lint! {
/// The `private_doc_tests` lint detects code samples in docs of private
/// items not documented by `rustdoc`. This is a `rustdoc` only lint, see
/// the documentation in the [rustdoc book].
///
/// [rustdoc book]: ../../../rustdoc/lints.html#private_doc_tests
pub rustdoc::PRIVATE_DOC_TESTS,
Allow,
"detects code samples in docs of private items not documented by rustdoc"
}
declare_tool_lint! {
/// The `invalid_html_tags` lint detects invalid HTML tags. This is a
/// `rustdoc` only lint, see the documentation in the [rustdoc book].
///
/// [rustdoc book]: ../../../rustdoc/lints.html#invalid_html_tags
pub rustdoc::INVALID_HTML_TAGS,
Allow,
"detects invalid HTML tags in doc comments"
}
declare_tool_lint! {
/// The `non_autolinks` lint detects when a URL could be written using
/// only angle brackets. This is a `rustdoc` only lint, see the
/// documentation in the [rustdoc book].
///
/// [rustdoc book]: ../../../rustdoc/lints.html#non_autolinks
pub rustdoc::NON_AUTOLINKS,
Warn,
"detects URLs that could be written using only angle brackets"
}
static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
vec![
BROKEN_INTRA_DOC_LINKS,
PRIVATE_INTRA_DOC_LINKS,
MISSING_DOC_CODE_EXAMPLES,
PRIVATE_DOC_TESTS,
INVALID_CODEBLOCK_ATTRIBUTES,
INVALID_HTML_TAGS,
NON_AUTOLINKS,
]
});
crate fn register_lints(_sess: &Session, lint_store: &mut LintStore) {
lint_store.register_lints(&**RUSTDOC_LINTS);
lint_store.register_group(
true,
"rustdoc",
None,
RUSTDOC_LINTS.iter().map(|&lint| LintId::of(lint)).collect(),
);
lint_store
.register_renamed("intra_doc_link_resolution_failure", "rustdoc::broken_intra_doc_links");
}
/// Parse, resolve, and typecheck the given crate.
crate fn create_config(
RustdocOptions {
@ -314,37 +418,23 @@ crate fn create_config(
let cpath = Some(input.clone());
let input = Input::File(input);
let broken_intra_doc_links = lint::builtin::BROKEN_INTRA_DOC_LINKS.name;
let private_intra_doc_links = lint::builtin::PRIVATE_INTRA_DOC_LINKS.name;
let missing_docs = rustc_lint::builtin::MISSING_DOCS.name;
let missing_doc_example = rustc_lint::builtin::MISSING_DOC_CODE_EXAMPLES.name;
let private_doc_tests = rustc_lint::builtin::PRIVATE_DOC_TESTS.name;
let no_crate_level_docs = rustc_lint::builtin::MISSING_CRATE_LEVEL_DOCS.name;
let invalid_codeblock_attributes_name = rustc_lint::builtin::INVALID_CODEBLOCK_ATTRIBUTES.name;
let invalid_html_tags = rustc_lint::builtin::INVALID_HTML_TAGS.name;
let renamed_and_removed_lints = rustc_lint::builtin::RENAMED_AND_REMOVED_LINTS.name;
let non_autolinks = rustc_lint::builtin::NON_AUTOLINKS.name;
let unknown_lints = rustc_lint::builtin::UNKNOWN_LINTS.name;
// In addition to those specific lints, we also need to allow those given through
// command line, otherwise they'll get ignored and we don't want that.
let lints_to_show = vec![
broken_intra_doc_links.to_owned(),
private_intra_doc_links.to_owned(),
missing_docs.to_owned(),
missing_doc_example.to_owned(),
private_doc_tests.to_owned(),
no_crate_level_docs.to_owned(),
invalid_codeblock_attributes_name.to_owned(),
invalid_html_tags.to_owned(),
renamed_and_removed_lints.to_owned(),
unknown_lints.to_owned(),
non_autolinks.to_owned(),
let mut lints_to_show = vec![
// it's unclear whether these should be part of rustdoc directly
rustc_lint::builtin::MISSING_DOCS.name.to_string(),
rustc_lint::builtin::MISSING_CRATE_LEVEL_DOCS.name.to_string(),
// these are definitely not part of rustdoc, but we want to warn on them anyway.
rustc_lint::builtin::RENAMED_AND_REMOVED_LINTS.name.to_string(),
rustc_lint::builtin::UNKNOWN_LINTS.name.to_string(),
];
lints_to_show.extend(RUSTDOC_LINTS.iter().map(|lint| lint.name.to_string()));
let (lint_opts, lint_caps) = init_lints(lints_to_show, lint_opts, |lint| {
// FIXME: why is this necessary?
if lint.name == broken_intra_doc_links || lint.name == invalid_codeblock_attributes_name {
if lint.name == BROKEN_INTRA_DOC_LINKS.name
|| lint.name == INVALID_CODEBLOCK_ATTRIBUTES.name
{
None
} else {
Some((lint.name_lower(), lint::Allow))
@ -384,7 +474,7 @@ crate fn create_config(
diagnostic_output: DiagnosticOutput::Default,
stderr: None,
lint_caps,
register_lints: None,
register_lints: Some(box register_lints),
override_queries: Some(|_sess, providers, _external_providers| {
// Most lints will require typechecking, so just don't run them.
providers.lint_mod = |_, _| {};

View file

@ -44,11 +44,15 @@ crate struct TestOptions {
crate fn run(options: Options) -> Result<(), ErrorReported> {
let input = config::Input::File(options.input.clone());
let invalid_codeblock_attributes_name = rustc_lint::builtin::INVALID_CODEBLOCK_ATTRIBUTES.name;
let invalid_codeblock_attributes_name = crate::core::INVALID_CODEBLOCK_ATTRIBUTES.name;
// In addition to those specific lints, we also need to allow those given through
// command line, otherwise they'll get ignored and we don't want that.
let allowed_lints = vec![invalid_codeblock_attributes_name.to_owned()];
let allowed_lints = vec![
invalid_codeblock_attributes_name.to_owned(),
lint::builtin::UNKNOWN_LINTS.name.to_owned(),
lint::builtin::RENAMED_AND_REMOVED_LINTS.name.to_owned(),
];
let (lint_opts, lint_caps) = init_lints(allowed_lints, options.lint_opts.clone(), |lint| {
if lint.name == invalid_codeblock_attributes_name {
@ -92,7 +96,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
diagnostic_output: DiagnosticOutput::Default,
stderr: None,
lint_caps,
register_lints: None,
register_lints: Some(box crate::core::register_lints),
override_queries: None,
make_codegen_backend: None,
registry: rustc_driver::diagnostics_registry(),

View file

@ -21,7 +21,6 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId;
use rustc_hir::HirId;
use rustc_middle::ty::TyCtxt;
use rustc_session::lint;
use rustc_span::edition::Edition;
use rustc_span::Span;
use std::borrow::Cow;
@ -721,7 +720,7 @@ impl<'tcx> ExtraInfo<'tcx> {
(None, None) => return,
};
self.tcx.struct_span_lint_hir(
lint::builtin::INVALID_CODEBLOCK_ATTRIBUTES,
crate::core::INVALID_CODEBLOCK_ATTRIBUTES,
hir_id,
self.sp,
|lint| {

View file

@ -45,6 +45,7 @@ extern crate rustc_infer;
extern crate rustc_interface;
extern crate rustc_lexer;
extern crate rustc_lint;
extern crate rustc_lint_defs;
extern crate rustc_metadata;
extern crate rustc_middle;
extern crate rustc_mir;

View file

@ -16,10 +16,7 @@ use rustc_hir::def_id::{CrateNum, DefId};
use rustc_middle::ty::TyCtxt;
use rustc_middle::{bug, ty};
use rustc_resolve::ParentScope;
use rustc_session::lint::{
builtin::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS},
Lint,
};
use rustc_session::lint::Lint;
use rustc_span::hygiene::{MacroKind, SyntaxContext};
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::DUMMY_SP;
@ -35,6 +32,7 @@ use std::ops::Range;
use crate::clean::{self, utils::find_nearest_parent_module, Crate, Item, ItemLink, PrimitiveType};
use crate::core::DocContext;
use crate::core::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS};
use crate::fold::DocFolder;
use crate::html::markdown::{markdown_links, MarkdownLink};
use crate::passes::Pass;

View file

@ -68,8 +68,7 @@ crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> boo
return false;
}
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_local());
let (level, source) =
cx.tcx.lint_level_at_node(lint::builtin::MISSING_DOC_CODE_EXAMPLES, hir_id);
let (level, source) = cx.tcx.lint_level_at_node(crate::core::MISSING_DOC_CODE_EXAMPLES, hir_id);
level != lint::Level::Allow || matches!(source, LintLevelSource::Default)
}
@ -91,7 +90,7 @@ crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
debug!("reporting error for {:?} (hir_id={:?})", item, hir_id);
let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span());
cx.tcx.struct_span_lint_hir(
lint::builtin::MISSING_DOC_CODE_EXAMPLES,
crate::core::MISSING_DOC_CODE_EXAMPLES,
hir_id,
sp,
|lint| lint.build("missing code example in this documentation").emit(),
@ -99,7 +98,7 @@ crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
}
} else if tests.found_tests > 0 && !cx.renderinfo.access_levels.is_public(item.def_id) {
cx.tcx.struct_span_lint_hir(
lint::builtin::PRIVATE_DOC_TESTS,
crate::core::PRIVATE_DOC_TESTS,
hir_id,
span_of_attrs(&item.attrs).unwrap_or(item.source.span()),
|lint| lint.build("documentation test in private item").emit(),

View file

@ -5,7 +5,6 @@ use crate::fold::DocFolder;
use crate::html::markdown::opts;
use core::ops::Range;
use pulldown_cmark::{Event, Parser, Tag};
use rustc_session::lint;
use std::iter::Peekable;
use std::str::CharIndices;
@ -183,7 +182,7 @@ impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> {
Some(sp) => sp,
None => span_of_attrs(&item.attrs).unwrap_or(item.source.span()),
};
cx.tcx.struct_span_lint_hir(lint::builtin::INVALID_HTML_TAGS, hir_id, sp, |lint| {
cx.tcx.struct_span_lint_hir(crate::core::INVALID_HTML_TAGS, hir_id, sp, |lint| {
lint.build(msg).emit()
});
};

View file

@ -7,7 +7,6 @@ use core::ops::Range;
use pulldown_cmark::{Event, LinkType, Parser, Tag};
use regex::Regex;
use rustc_errors::Applicability;
use rustc_session::lint;
crate const CHECK_NON_AUTOLINKS: Pass = Pass {
name: "check-non-autolinks",
@ -74,7 +73,7 @@ impl<'a, 'tcx> DocFolder for NonAutolinksLinter<'a, 'tcx> {
let sp = super::source_span_for_markdown_range(cx, &dox, &range, &item.attrs)
.or_else(|| span_of_attrs(&item.attrs))
.unwrap_or(item.source.span());
cx.tcx.struct_span_lint_hir(lint::builtin::NON_AUTOLINKS, hir_id, sp, |lint| {
cx.tcx.struct_span_lint_hir(crate::core::NON_AUTOLINKS, hir_id, sp, |lint| {
lint.build(msg)
.span_suggestion(
sp,