diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs index 0c623dba369..ba452775015 100644 --- a/src/tools/clippy/clippy_lints/src/doc/mod.rs +++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs @@ -655,205 +655,6 @@ fn check_doc<'a, Events: Iterator, Range, trimmed_text: &str, range: Range, fragments: Fragments<'_>) { - if trimmed_text.starts_with('\'') - && trimmed_text.ends_with('\'') - && let Some(span) = fragments.span(cx, range) - { - span_lint( - cx, - DOC_LINK_WITH_QUOTES, - span, - "possible intra-doc link using quotes instead of backticks", - ); - } -} - -fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, range: Range, fragments: Fragments<'_>) { - fn has_needless_main(code: String, edition: Edition) -> bool { - rustc_driver::catch_fatal_errors(|| { - rustc_span::create_session_globals_then(edition, || { - let filename = FileName::anon_source_code(&code); - - let fallback_bundle = - rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false); - let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle); - let handler = Handler::with_emitter(Box::new(emitter)).disable_warnings(); - #[expect(clippy::arc_with_non_send_sync)] // `Lrc` is expected by with_span_handler - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let sess = ParseSess::with_span_handler(handler, sm); - - let mut parser = match maybe_new_parser_from_source_str(&sess, filename, code) { - Ok(p) => p, - Err(errs) => { - drop(errs); - return false; - }, - }; - - let mut relevant_main_found = false; - loop { - match parser.parse_item(ForceCollect::No) { - Ok(Some(item)) => match &item.kind { - ItemKind::Fn(box Fn { - sig, body: Some(block), .. - }) if item.ident.name == sym::main => { - let is_async = sig.header.coro_kind.map_or(false, |coro| coro.is_async()); - let returns_nothing = match &sig.decl.output { - FnRetTy::Default(..) => true, - FnRetTy::Ty(ty) if ty.kind.is_unit() => true, - FnRetTy::Ty(_) => false, - }; - - if returns_nothing && !is_async && !block.stmts.is_empty() { - // This main function should be linted, but only if there are no other functions - relevant_main_found = true; - } else { - // This main function should not be linted, we're done - return false; - } - }, - // Tests with one of these items are ignored - ItemKind::Static(..) - | ItemKind::Const(..) - | ItemKind::ExternCrate(..) - | ItemKind::ForeignMod(..) - // Another function was found; this case is ignored - | ItemKind::Fn(..) => return false, - _ => {}, - }, - Ok(None) => break, - Err(e) => { - e.cancel(); - return false; - }, - } - } - - relevant_main_found - }) - }) - .ok() - .unwrap_or_default() - } - - let trailing_whitespace = text.len() - text.trim_end().len(); - - // Because of the global session, we need to create a new session in a different thread with - // the edition we need. - let text = text.to_owned(); - if thread::spawn(move || has_needless_main(text, edition)) - .join() - .expect("thread::spawn failed") - && let Some(span) = fragments.span(cx, range.start..range.end - trailing_whitespace) - { - span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest"); - } -} - -fn check_text(cx: &LateContext<'_>, valid_idents: &FxHashSet, text: &str, span: Span) { - for word in text.split(|c: char| c.is_whitespace() || c == '\'') { - // Trim punctuation as in `some comment (see foo::bar).` - // ^^ - // Or even as in `_foo bar_` which is emphasized. Also preserve `::` as a prefix/suffix. - let mut word = word.trim_matches(|c: char| !c.is_alphanumeric() && c != ':'); - - // Remove leading or trailing single `:` which may be part of a sentence. - if word.starts_with(':') && !word.starts_with("::") { - word = word.trim_start_matches(':'); - } - if word.ends_with(':') && !word.ends_with("::") { - word = word.trim_end_matches(':'); - } - - if valid_idents.contains(word) || word.chars().all(|c| c == ':') { - continue; - } - - // Adjust for the current word - let offset = word.as_ptr() as usize - text.as_ptr() as usize; - let span = Span::new( - span.lo() + BytePos::from_usize(offset), - span.lo() + BytePos::from_usize(offset + word.len()), - span.ctxt(), - span.parent(), - ); - - check_word(cx, word, span); - } -} - -fn check_word(cx: &LateContext<'_>, word: &str, span: Span) { - /// Checks if a string is upper-camel-case, i.e., starts with an uppercase and - /// contains at least two uppercase letters (`Clippy` is ok) and one lower-case - /// letter (`NASA` is ok). - /// Plurals are also excluded (`IDs` is ok). - fn is_camel_case(s: &str) -> bool { - if s.starts_with(|c: char| c.is_ascii_digit() | c.is_ascii_lowercase()) { - return false; - } - - let s = s.strip_suffix('s').unwrap_or(s); - - s.chars().all(char::is_alphanumeric) - && s.chars().filter(|&c| c.is_uppercase()).take(2).count() > 1 - && s.chars().filter(|&c| c.is_lowercase()).take(1).count() > 0 - } - - fn has_underscore(s: &str) -> bool { - s != "_" && !s.contains("\\_") && s.contains('_') - } - - fn has_hyphen(s: &str) -> bool { - s != "-" && s.contains('-') - } - - if let Ok(url) = Url::parse(word) { - // try to get around the fact that `foo::bar` parses as a valid URL - if !url.cannot_be_a_base() { - span_lint( - cx, - DOC_MARKDOWN, - span, - "you should put bare URLs between `<`/`>` or make a proper Markdown link", - ); - - return; - } - } - - // We assume that mixed-case words are not meant to be put inside backticks. (Issue #2343) - if has_underscore(word) && has_hyphen(word) { - return; - } - - if has_underscore(word) || word.contains("::") || is_camel_case(word) { - let mut applicability = Applicability::MachineApplicable; - - span_lint_and_then( - cx, - DOC_MARKDOWN, - span, - "item in documentation is missing backticks", - |diag| { - let snippet = snippet_with_applicability(cx, span, "..", &mut applicability); - diag.span_suggestion_with_style( - span, - "try", - format!("`{snippet}`"), - applicability, - // always show the suggestion in a separate line, since the - // inline presentation adds another pair of backticks - SuggestionStyle::ShowAlways, - ); - }, - ); - } -} - ->>>>>>> d116f1718f1 (Merge Async and Gen into CoroutineKind):src/tools/clippy/clippy_lints/src/doc.rs struct FindPanicUnwrap<'a, 'tcx> { cx: &'a LateContext<'tcx>, panic_span: Option,