about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2025-05-01 21:53:37 +0200
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2025-05-02 13:57:53 +0200
commitf4d41a5cbd00ee3490beb3a6fff9bd909c137153 (patch)
tree5d6af8465943e1952f897c4fe82165217383b3b9
parent5b86fa8282c6dc9d61c7f358f8cc2ea9c3a93330 (diff)
downloadrust-f4d41a5cbd00ee3490beb3a6fff9bd909c137153.tar.gz
rust-f4d41a5cbd00ee3490beb3a6fff9bd909c137153.zip
Create a builder for DocTestBuilder type
-rw-r--r--src/librustdoc/doctest.rs20
-rw-r--r--src/librustdoc/doctest/extracted.rs18
-rw-r--r--src/librustdoc/doctest/make.rs124
-rw-r--r--src/librustdoc/doctest/tests.rs23
-rw-r--r--src/librustdoc/html/markdown.rs10
5 files changed, 123 insertions, 72 deletions
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 5b85eb54a5c..e619fc6663b 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -12,7 +12,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
 use std::sync::{Arc, Mutex};
 use std::{panic, str};
 
-pub(crate) use make::DocTestBuilder;
+pub(crate) use make::{BuildDocTestBuilder, DocTestBuilder};
 pub(crate) use markdown::test as test_markdown;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
 use rustc_errors::emitter::HumanReadableErrorType;
@@ -972,16 +972,14 @@ impl CreateRunnableDocTests {
         );
 
         let edition = scraped_test.edition(&self.rustdoc_options);
-        let doctest = DocTestBuilder::new(
-            &scraped_test.text,
-            Some(&self.opts.crate_name),
-            edition,
-            self.can_merge_doctests,
-            Some(test_id),
-            Some(&scraped_test.langstr),
-            dcx,
-            scraped_test.span,
-        );
+        let doctest = BuildDocTestBuilder::new(&scraped_test.text)
+            .crate_name(&self.opts.crate_name)
+            .edition(edition)
+            .can_merge_doctests(self.can_merge_doctests)
+            .test_id(test_id)
+            .lang_str(&scraped_test.langstr)
+            .span(scraped_test.span)
+            .build(dcx);
         let is_standalone = !doctest.can_be_merged
             || scraped_test.langstr.compile_fail
             || scraped_test.langstr.test_harness
diff --git a/src/librustdoc/doctest/extracted.rs b/src/librustdoc/doctest/extracted.rs
index d82bca3279d..3b17ccc78c7 100644
--- a/src/librustdoc/doctest/extracted.rs
+++ b/src/librustdoc/doctest/extracted.rs
@@ -3,10 +3,9 @@
 //! This module contains the logic to extract doctests and output a JSON containing this
 //! information.
 
-use rustc_span::DUMMY_SP;
 use serde::Serialize;
 
-use super::{DocTestBuilder, ScrapedDocTest};
+use super::{BuildDocTestBuilder, ScrapedDocTest};
 use crate::config::Options as RustdocOptions;
 use crate::html::markdown;
 
@@ -38,16 +37,11 @@ impl ExtractedDocTests {
 
         let ScrapedDocTest { filename, line, langstr, text, name, .. } = scraped_test;
 
-        let doctest = DocTestBuilder::new(
-            &text,
-            Some(&opts.crate_name),
-            edition,
-            false,
-            None,
-            Some(&langstr),
-            None,
-            DUMMY_SP,
-        );
+        let doctest = BuildDocTestBuilder::new(&text)
+            .crate_name(&opts.crate_name)
+            .edition(edition)
+            .lang_str(&langstr)
+            .build(None);
         let (full_test_code, size) = doctest.generate_unique_doctest(
             &text,
             langstr.test_harness,
diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs
index 759b139e288..66647b88018 100644
--- a/src/librustdoc/doctest/make.rs
+++ b/src/librustdoc/doctest/make.rs
@@ -12,10 +12,10 @@ use rustc_errors::emitter::stderr_destination;
 use rustc_errors::{ColorConfig, DiagCtxtHandle};
 use rustc_parse::new_parser_from_source_str;
 use rustc_session::parse::ParseSess;
-use rustc_span::edition::Edition;
+use rustc_span::edition::{DEFAULT_EDITION, Edition};
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::sym;
-use rustc_span::{FileName, Span, kw};
+use rustc_span::{DUMMY_SP, FileName, Span, kw};
 use tracing::debug;
 
 use super::GlobalTestOptions;
@@ -35,35 +35,78 @@ struct ParseSourceInfo {
     maybe_crate_attrs: String,
 }
 
-/// This struct contains information about the doctest itself which is then used to generate
-/// doctest source code appropriately.
-pub(crate) struct DocTestBuilder {
-    pub(crate) supports_color: bool,
-    pub(crate) already_has_extern_crate: bool,
-    pub(crate) has_main_fn: bool,
-    pub(crate) crate_attrs: String,
-    /// If this is a merged doctest, it will be put into `everything_else`, otherwise it will
-    /// put into `crate_attrs`.
-    pub(crate) maybe_crate_attrs: String,
-    pub(crate) crates: String,
-    pub(crate) everything_else: String,
-    pub(crate) test_id: Option<String>,
-    pub(crate) invalid_ast: bool,
-    pub(crate) can_be_merged: bool,
+/// Builder type for `DocTestBuilder`.
+pub(crate) struct BuildDocTestBuilder<'a> {
+    source: &'a str,
+    crate_name: Option<&'a str>,
+    edition: Edition,
+    can_merge_doctests: bool,
+    // If `test_id` is `None`, it means we're generating code for a code example "run" link.
+    test_id: Option<String>,
+    lang_str: Option<&'a LangString>,
+    span: Span,
 }
 
-impl DocTestBuilder {
-    pub(crate) fn new(
-        source: &str,
-        crate_name: Option<&str>,
-        edition: Edition,
-        can_merge_doctests: bool,
-        // If `test_id` is `None`, it means we're generating code for a code example "run" link.
-        test_id: Option<String>,
-        lang_str: Option<&LangString>,
-        dcx: Option<DiagCtxtHandle<'_>>,
-        span: Span,
-    ) -> Self {
+impl<'a> BuildDocTestBuilder<'a> {
+    pub(crate) fn new(source: &'a str) -> Self {
+        Self {
+            source,
+            crate_name: None,
+            edition: DEFAULT_EDITION,
+            can_merge_doctests: false,
+            test_id: None,
+            lang_str: None,
+            span: DUMMY_SP,
+        }
+    }
+
+    #[inline]
+    pub(crate) fn crate_name(mut self, crate_name: &'a str) -> Self {
+        self.crate_name = Some(crate_name);
+        self
+    }
+
+    #[inline]
+    pub(crate) fn can_merge_doctests(mut self, can_merge_doctests: bool) -> Self {
+        self.can_merge_doctests = can_merge_doctests;
+        self
+    }
+
+    #[inline]
+    pub(crate) fn test_id(mut self, test_id: String) -> Self {
+        self.test_id = Some(test_id);
+        self
+    }
+
+    #[inline]
+    pub(crate) fn lang_str(mut self, lang_str: &'a LangString) -> Self {
+        self.lang_str = Some(lang_str);
+        self
+    }
+
+    #[inline]
+    pub(crate) fn span(mut self, span: Span) -> Self {
+        self.span = span;
+        self
+    }
+
+    #[inline]
+    pub(crate) fn edition(mut self, edition: Edition) -> Self {
+        self.edition = edition;
+        self
+    }
+
+    pub(crate) fn build(self, dcx: Option<DiagCtxtHandle<'_>>) -> DocTestBuilder {
+        let BuildDocTestBuilder {
+            source,
+            crate_name,
+            edition,
+            can_merge_doctests,
+            // If `test_id` is `None`, it means we're generating code for a code example "run" link.
+            test_id,
+            lang_str,
+            span,
+        } = self;
         let can_merge_doctests = can_merge_doctests
             && lang_str.is_some_and(|lang_str| {
                 !lang_str.compile_fail && !lang_str.test_harness && !lang_str.standalone_crate
@@ -89,7 +132,7 @@ impl DocTestBuilder {
         else {
             // If the AST returned an error, we don't want this doctest to be merged with the
             // others.
-            return Self::invalid(
+            return DocTestBuilder::invalid(
                 String::new(),
                 String::new(),
                 String::new(),
@@ -109,7 +152,7 @@ impl DocTestBuilder {
             // If this is a merged doctest and a defined macro uses `$crate`, then the path will
             // not work, so better not put it into merged doctests.
             && !(has_macro_def && everything_else.contains("$crate"));
-        Self {
+        DocTestBuilder {
             supports_color,
             has_main_fn,
             crate_attrs,
@@ -122,7 +165,26 @@ impl DocTestBuilder {
             can_be_merged,
         }
     }
+}
+
+/// This struct contains information about the doctest itself which is then used to generate
+/// doctest source code appropriately.
+pub(crate) struct DocTestBuilder {
+    pub(crate) supports_color: bool,
+    pub(crate) already_has_extern_crate: bool,
+    pub(crate) has_main_fn: bool,
+    pub(crate) crate_attrs: String,
+    /// If this is a merged doctest, it will be put into `everything_else`, otherwise it will
+    /// put into `crate_attrs`.
+    pub(crate) maybe_crate_attrs: String,
+    pub(crate) crates: String,
+    pub(crate) everything_else: String,
+    pub(crate) test_id: Option<String>,
+    pub(crate) invalid_ast: bool,
+    pub(crate) can_be_merged: bool,
+}
 
+impl DocTestBuilder {
     fn invalid(
         crate_attrs: String,
         maybe_crate_attrs: String,
diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs
index ce27a20540e..d810b784df5 100644
--- a/src/librustdoc/doctest/tests.rs
+++ b/src/librustdoc/doctest/tests.rs
@@ -1,9 +1,6 @@
 use std::path::PathBuf;
 
-use rustc_span::DUMMY_SP;
-use rustc_span::edition::DEFAULT_EDITION;
-
-use super::{DocTestBuilder, GlobalTestOptions};
+use super::{BuildDocTestBuilder, GlobalTestOptions};
 
 fn make_test(
     test_code: &str,
@@ -12,16 +9,14 @@ fn make_test(
     opts: &GlobalTestOptions,
     test_id: Option<&str>,
 ) -> (String, usize) {
-    let doctest = DocTestBuilder::new(
-        test_code,
-        crate_name,
-        DEFAULT_EDITION,
-        false,
-        test_id.map(|s| s.to_string()),
-        None,
-        None,
-        DUMMY_SP,
-    );
+    let mut builder = BuildDocTestBuilder::new(test_code);
+    if let Some(crate_name) = crate_name {
+        builder = builder.crate_name(crate_name);
+    }
+    if let Some(test_id) = test_id {
+        builder = builder.test_id(test_id.to_string());
+    }
+    let doctest = builder.build(None);
     let (code, line_offset) =
         doctest.generate_unique_doctest(test_code, dont_insert_main, opts, crate_name);
     (code, line_offset)
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 5014a5198c8..ad7dfafd90c 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -45,7 +45,7 @@ use rustc_middle::ty::TyCtxt;
 pub(crate) use rustc_resolve::rustdoc::main_body_opts;
 use rustc_resolve::rustdoc::may_be_doc_link;
 use rustc_span::edition::Edition;
-use rustc_span::{DUMMY_SP, Span, Symbol};
+use rustc_span::{Span, Symbol};
 use tracing::{debug, trace};
 
 use crate::clean::RenderedLink;
@@ -303,9 +303,11 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
                 attrs: vec![],
                 args_file: PathBuf::new(),
             };
-            let doctest = doctest::DocTestBuilder::new(
-                &test, krate, edition, false, None, None, None, DUMMY_SP,
-            );
+            let mut builder = doctest::BuildDocTestBuilder::new(&test).edition(edition);
+            if let Some(krate) = krate {
+                builder = builder.crate_name(krate);
+            }
+            let doctest = builder.build(None);
             let (test, _) = doctest.generate_unique_doctest(&test, false, &opts, krate);
             let channel = if test.contains("#![feature(") { "&amp;version=nightly" } else { "" };