Skip to content

Commit

Permalink
Move lint machinery into a separate file
Browse files Browse the repository at this point in the history
  • Loading branch information
jyn514 committed Mar 2, 2021
1 parent cc62018 commit 37e4cfe
Show file tree
Hide file tree
Showing 9 changed files with 183 additions and 180 deletions.
175 changes: 7 additions & 168 deletions src/librustdoc/core.rs
Expand Up @@ -12,8 +12,6 @@ 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};
Expand All @@ -28,7 +26,6 @@ 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;

Expand Down Expand Up @@ -232,164 +229,6 @@ crate fn new_handler(
)
}

/// This function is used to setup the lint initialization. By default, in rustdoc, everything
/// is "allowed". Depending if we run in test mode or not, we want some of them to be at their
/// default level. For example, the "INVALID_CODEBLOCK_ATTRIBUTES" lint is activated in both
/// modes.
///
/// A little detail easy to forget is that there is a way to set the lint level for all lints
/// through the "WARNINGS" lint. To prevent this to happen, we set it back to its "normal" level
/// inside this function.
///
/// It returns a tuple containing:
/// * Vector of tuples of lints' name and their associated "max" level
/// * HashMap of lint id with their associated "max" level
pub(crate) fn init_lints<F>(
mut allowed_lints: Vec<String>,
lint_opts: Vec<(String, lint::Level)>,
filter_call: F,
) -> (Vec<(String, lint::Level)>, FxHashMap<lint::LintId, lint::Level>)
where
F: Fn(&lint::Lint) -> Option<(String, lint::Level)>,
{
let warnings_lint_name = lint::builtin::WARNINGS.name;

allowed_lints.push(warnings_lint_name.to_owned());
allowed_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned());

let lints = || {
lint::builtin::HardwiredLints::get_lints()
.into_iter()
.chain(rustc_lint::SoftLints::get_lints().into_iter())
};

let lint_opts = lints()
.filter_map(|lint| {
// Permit feature-gated lints to avoid feature errors when trying to
// allow all lints.
if lint.feature_gate.is_some() || allowed_lints.iter().any(|l| lint.name == l) {
None
} else {
filter_call(lint)
}
})
.chain(lint_opts.into_iter())
.collect::<Vec<_>>();

let lint_caps = lints()
.filter_map(|lint| {
// We don't want to allow *all* lints so let's ignore
// those ones.
if allowed_lints.iter().any(|l| lint.name == l) {
None
} else {
Some((lint::LintId::of(lint), lint::Allow))
}
})
.collect();
(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 {
Expand Down Expand Up @@ -418,8 +257,8 @@ crate fn create_config(
let cpath = Some(input.clone());
let input = Input::File(input);

// 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.
// By default, rustdoc ignores all lints.
// Specifically unblock lints relevant to documentation or the lint machinery itself.
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(),
Expand All @@ -428,12 +267,12 @@ crate fn create_config(
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()));
lints_to_show.extend(crate::lint::RUSTDOC_LINTS.iter().map(|lint| lint.name.to_string()));

let (lint_opts, lint_caps) = init_lints(lints_to_show, lint_opts, |lint| {
let (lint_opts, lint_caps) = crate::lint::init_lints(lints_to_show, lint_opts, |lint| {
// FIXME: why is this necessary?
if lint.name == BROKEN_INTRA_DOC_LINKS.name
|| lint.name == INVALID_CODEBLOCK_ATTRIBUTES.name
if lint.name == crate::lint::BROKEN_INTRA_DOC_LINKS.name
|| lint.name == crate::lint::INVALID_CODEBLOCK_ATTRIBUTES.name
{
None
} else {
Expand Down Expand Up @@ -474,7 +313,7 @@ crate fn create_config(
diagnostic_output: DiagnosticOutput::Default,
stderr: None,
lint_caps,
register_lints: Some(box register_lints),
register_lints: Some(box crate::lint::register_lints),
override_queries: Some(|_sess, providers, _external_providers| {
// Most lints will require typechecking, so just don't run them.
providers.lint_mod = |_, _| {};
Expand Down
9 changes: 4 additions & 5 deletions src/librustdoc/doctest.rs
Expand Up @@ -26,8 +26,8 @@ use std::str;

use crate::clean::Attributes;
use crate::config::Options;
use crate::core::init_lints;
use crate::html::markdown::{self, ErrorCodes, Ignore, LangString};
use crate::lint::init_lints;
use crate::passes::span_of_attrs;

#[derive(Clone, Default)]
Expand All @@ -44,10 +44,9 @@ crate struct TestOptions {
crate fn run(options: Options) -> Result<(), ErrorReported> {
let input = config::Input::File(options.input.clone());

let invalid_codeblock_attributes_name = crate::core::INVALID_CODEBLOCK_ATTRIBUTES.name;
let invalid_codeblock_attributes_name = crate::lint::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.
// See core::create_config for what's going on here.
let allowed_lints = vec![
invalid_codeblock_attributes_name.to_owned(),
lint::builtin::UNKNOWN_LINTS.name.to_owned(),
Expand Down Expand Up @@ -96,7 +95,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
diagnostic_output: DiagnosticOutput::Default,
stderr: None,
lint_caps,
register_lints: Some(box crate::core::register_lints),
register_lints: Some(box crate::lint::register_lints),
override_queries: None,
make_codegen_backend: None,
registry: rustc_driver::diagnostics_registry(),
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/html/markdown.rs
Expand Up @@ -720,7 +720,7 @@ impl<'tcx> ExtraInfo<'tcx> {
(None, None) => return,
};
self.tcx.struct_span_lint_hir(
crate::core::INVALID_CODEBLOCK_ATTRIBUTES,
crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
hir_id,
self.sp,
|lint| {
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/lib.rs
Expand Up @@ -86,6 +86,7 @@ mod formats;
// used by the error-index generator, so it needs to be public
pub mod html;
mod json;
crate mod lint;
mod markdown;
mod passes;
mod theme;
Expand Down

0 comments on commit 37e4cfe

Please sign in to comment.