diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs index 287a1f50b5aa1..0928980e390a8 100644 --- a/src/librustdoc/passes/lint/bare_urls.rs +++ b/src/librustdoc/passes/lint/bare_urls.rs @@ -2,14 +2,13 @@ //! Suggests wrapping the link with angle brackets: `Go to .` to linkify it. use core::ops::Range; +use std::mem; use std::sync::LazyLock; use regex::Regex; use rustc_errors::{Applicability, DiagDecorator}; use rustc_hir::HirId; -use rustc_resolve::rustdoc::pulldown_cmark::{ - DefaultBrokenLinkCallback, Event, Tag, TextMergeWithOffset, -}; +use rustc_resolve::rustdoc::pulldown_cmark::{Event, Parser, Tag}; use rustc_resolve::rustdoc::source_span_for_markdown_range; use tracing::trace; @@ -56,20 +55,21 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & ); }; - // pulldown-cmark can split a URL into multiple `Text` events while processing - // characters such as `_` according to CommonMark's emphasis rules. - // `TextMergeWithOffset` merges these events so we can check the complete URL. - let mut p = TextMergeWithOffset::::new_ext(dox, main_body_opts()); + let mut p = Parser::new_ext(dox, main_body_opts()).into_offset_iter(); while let Some((event, range)) = p.next() { match event { Event::Text(s) => find_raw_urls(cx, dox, &s, range, &report_diag), // We don't want to check the text inside code blocks or links. Event::Start(tag @ (Tag::CodeBlock(_) | Tag::Link { .. })) => { - let end = tag.to_end(); for (event, _) in p.by_ref() { - if matches!(event, Event::End(tag) if tag == end) { - break; + match event { + Event::End(end) + if mem::discriminant(&end) == mem::discriminant(&tag.to_end()) => + { + break; + } + _ => {} } } } @@ -83,12 +83,7 @@ static URL_REGEX: LazyLock = LazyLock::new(|| { r"https?://", // url scheme r"([-a-zA-Z0-9@:%._\+~#=]{2,256}\.)+", // one or more subdomains r"[a-zA-Z]{2,63}", // root domain - // Match URL characters and balanced parenthesized segments, without - // consuming a trailing `)` that belongs to the surrounding prose. - r"\b(?:", - r"[-a-zA-Z0-9@:%_\+.~#?&/=]", - r"|\([-a-zA-Z0-9@:%_\+.~#?&/=]*\)", - r")*", + r"\b([-a-zA-Z0-9@:%_\+.~#?&/=]*)", // optional query or url fragments )) .expect("failed to build regex") }); diff --git a/tests/rustdoc-ui/lints/bare-urls.fixed b/tests/rustdoc-ui/lints/bare-urls.fixed index b18aae11c77cf..996214b5ff14f 100644 --- a/tests/rustdoc-ui/lints/bare-urls.fixed +++ b/tests/rustdoc-ui/lints/bare-urls.fixed @@ -92,7 +92,3 @@ pub fn trailing_period() {} /// ] //~^ ERROR this URL is not a hyperlink pub fn lint_with_brackets() {} - -/// See -//~^ ERROR this URL is not a hyperlink -pub fn hippo() {} diff --git a/tests/rustdoc-ui/lints/bare-urls.rs b/tests/rustdoc-ui/lints/bare-urls.rs index fb39ec6b6ccbd..9b4fe68e00322 100644 --- a/tests/rustdoc-ui/lints/bare-urls.rs +++ b/tests/rustdoc-ui/lints/bare-urls.rs @@ -92,7 +92,3 @@ pub fn trailing_period() {} /// https://bloob.blob] //~^ ERROR this URL is not a hyperlink pub fn lint_with_brackets() {} - -/// See https://en.wikipedia.org/wiki/Rust_(programming_language) -//~^ ERROR this URL is not a hyperlink -pub fn hippo() {} diff --git a/tests/rustdoc-ui/lints/bare-urls.stderr b/tests/rustdoc-ui/lints/bare-urls.stderr index a3a291e8e4bca..05ddd2ed42ab1 100644 --- a/tests/rustdoc-ui/lints/bare-urls.stderr +++ b/tests/rustdoc-ui/lints/bare-urls.stderr @@ -364,17 +364,5 @@ help: use an automatic link instead LL | /// ] | + + -error: this URL is not a hyperlink - --> $DIR/bare-urls.rs:96:9 - | -LL | /// See https://en.wikipedia.org/wiki/Rust_(programming_language) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: bare URLs are not automatically turned into clickable links -help: use an automatic link instead - | -LL | /// See - | + + - -error: aborting due to 31 previous errors +error: aborting due to 30 previous errors