Add new lint for automatic_links improvements
This commit is contained in:
parent
8c20701219
commit
2980367030
@ -67,7 +67,7 @@ use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::lint::builtin::{
|
||||
BARE_TRAIT_OBJECTS, BROKEN_INTRA_DOC_LINKS, ELIDED_LIFETIMES_IN_PATHS,
|
||||
AUTOMATIC_LINKS, BARE_TRAIT_OBJECTS, BROKEN_INTRA_DOC_LINKS, ELIDED_LIFETIMES_IN_PATHS,
|
||||
EXPLICIT_OUTLIVES_REQUIREMENTS, INVALID_CODEBLOCK_ATTRIBUTES, INVALID_HTML_TAGS,
|
||||
MISSING_DOC_CODE_EXAMPLES, PRIVATE_DOC_TESTS,
|
||||
};
|
||||
@ -313,6 +313,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
|
||||
|
||||
add_lint_group!(
|
||||
"rustdoc",
|
||||
AUTOMATIC_LINKS,
|
||||
BROKEN_INTRA_DOC_LINKS,
|
||||
PRIVATE_INTRA_DOC_LINKS,
|
||||
INVALID_CODEBLOCK_ATTRIBUTES,
|
||||
|
@ -1890,6 +1890,17 @@ declare_lint! {
|
||||
"detects invalid HTML tags in doc comments"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `automatic_links` lint detects when a URL/email address could be
|
||||
/// written using only brackets. This is a `rustdoc` only lint, see the
|
||||
/// documentation in the [rustdoc book].
|
||||
///
|
||||
/// [rustdoc book]: ../../../rustdoc/lints.html#automatic_links
|
||||
pub AUTOMATIC_LINKS,
|
||||
Allow,
|
||||
"detects URLs/email adresses that could be written using only brackets"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `where_clauses_object_safety` lint detects for [object safety] of
|
||||
/// [where clauses].
|
||||
@ -2795,6 +2806,7 @@ declare_lint_pass! {
|
||||
MISSING_DOC_CODE_EXAMPLES,
|
||||
INVALID_HTML_TAGS,
|
||||
PRIVATE_DOC_TESTS,
|
||||
AUTOMATIC_LINKS,
|
||||
WHERE_CLAUSES_OBJECT_SAFETY,
|
||||
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
|
||||
MACRO_USE_EXTERN_CRATE,
|
||||
|
@ -330,11 +330,13 @@ pub fn run_core(
|
||||
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 automatic_links = rustc_lint::builtin::AUTOMATIC_LINKS.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![
|
||||
automatic_links.to_owned(),
|
||||
intra_link_resolution_failure_name.to_owned(),
|
||||
missing_docs.to_owned(),
|
||||
missing_doc_example.to_owned(),
|
||||
|
93
src/librustdoc/passes/automatic_links.rs
Normal file
93
src/librustdoc/passes/automatic_links.rs
Normal file
@ -0,0 +1,93 @@
|
||||
use super::{span_of_attrs, Pass};
|
||||
use crate::clean::*;
|
||||
use crate::core::DocContext;
|
||||
use crate::fold::DocFolder;
|
||||
use crate::html::markdown::opts;
|
||||
use pulldown_cmark::{Event, Parser, Tag};
|
||||
use rustc_feature::UnstableFeatures;
|
||||
use rustc_session::lint;
|
||||
|
||||
pub const CHECK_AUTOMATIC_LINKS: Pass = Pass {
|
||||
name: "check-automatic-links",
|
||||
run: check_automatic_links,
|
||||
description: "detects URLS/email addresses that could be written using brackets",
|
||||
};
|
||||
|
||||
struct AutomaticLinksLinter<'a, 'tcx> {
|
||||
cx: &'a DocContext<'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> AutomaticLinksLinter<'a, 'tcx> {
|
||||
fn new(cx: &'a DocContext<'tcx>) -> Self {
|
||||
AutomaticLinksLinter { cx }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_automatic_links(krate: Crate, cx: &DocContext<'_>) -> Crate {
|
||||
if !UnstableFeatures::from_environment().is_nightly_build() {
|
||||
krate
|
||||
} else {
|
||||
let mut coll = AutomaticLinksLinter::new(cx);
|
||||
|
||||
coll.fold_crate(krate)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> DocFolder for AutomaticLinksLinter<'a, 'tcx> {
|
||||
fn fold_item(&mut self, item: Item) -> Option<Item> {
|
||||
let hir_id = match self.cx.as_local_hir_id(item.def_id) {
|
||||
Some(hir_id) => hir_id,
|
||||
None => {
|
||||
// If non-local, no need to check anything.
|
||||
return self.fold_item_recur(item);
|
||||
}
|
||||
};
|
||||
let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
|
||||
if !dox.is_empty() {
|
||||
let cx = &self.cx;
|
||||
|
||||
let p = Parser::new_ext(&dox, opts()).into_offset_iter();
|
||||
|
||||
let mut title = String::new();
|
||||
let mut in_link = false;
|
||||
|
||||
for (event, range) in p {
|
||||
match event {
|
||||
Event::Start(Tag::Link(..)) => in_link = true,
|
||||
Event::End(Tag::Link(_, url, _)) => {
|
||||
in_link = false;
|
||||
if url.as_ref() != title {
|
||||
continue;
|
||||
}
|
||||
let sp = match super::source_span_for_markdown_range(
|
||||
cx,
|
||||
&dox,
|
||||
&range,
|
||||
&item.attrs,
|
||||
) {
|
||||
Some(sp) => sp,
|
||||
None => span_of_attrs(&item.attrs).unwrap_or(item.source.span()),
|
||||
};
|
||||
cx.tcx.struct_span_lint_hir(
|
||||
lint::builtin::AUTOMATIC_LINKS,
|
||||
hir_id,
|
||||
sp,
|
||||
|lint| {
|
||||
lint.build("Unneeded long form for URL")
|
||||
.help(&format!("Try with `<{}>` instead", url))
|
||||
.emit()
|
||||
},
|
||||
);
|
||||
title.clear();
|
||||
}
|
||||
Event::Text(s) if in_link => {
|
||||
title.push_str(&s);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.fold_item_recur(item)
|
||||
}
|
||||
}
|
@ -11,6 +11,9 @@ use crate::core::DocContext;
|
||||
mod stripper;
|
||||
pub use stripper::*;
|
||||
|
||||
mod automatic_links;
|
||||
pub use self::automatic_links::CHECK_AUTOMATIC_LINKS;
|
||||
|
||||
mod collapse_docs;
|
||||
pub use self::collapse_docs::COLLAPSE_DOCS;
|
||||
|
||||
@ -90,6 +93,7 @@ pub const PASSES: &[Pass] = &[
|
||||
COLLECT_TRAIT_IMPLS,
|
||||
CALCULATE_DOC_COVERAGE,
|
||||
CHECK_INVALID_HTML_TAGS,
|
||||
CHECK_AUTOMATIC_LINKS,
|
||||
];
|
||||
|
||||
/// The list of passes run by default.
|
||||
@ -105,6 +109,7 @@ pub const DEFAULT_PASSES: &[ConditionalPass] = &[
|
||||
ConditionalPass::always(CHECK_CODE_BLOCK_SYNTAX),
|
||||
ConditionalPass::always(CHECK_INVALID_HTML_TAGS),
|
||||
ConditionalPass::always(PROPAGATE_DOC_CFG),
|
||||
ConditionalPass::always(CHECK_AUTOMATIC_LINKS),
|
||||
];
|
||||
|
||||
/// The list of default passes run when `--doc-coverage` is passed to rustdoc.
|
||||
|
Loading…
Reference in New Issue
Block a user