1use anyhow::Ok;
2use strum::IntoEnumIterator;
3
4use crate::{
5 commands::WARN_IGNORED_ONLY_ARGS,
6 endgroup, group,
7 prelude::{Context, Environment},
8 utils::{
9 process::{run_process_for_package, run_process_for_workspace},
10 workspace::{get_workspace_members, WorkspaceMember, WorkspaceMemberType},
11 },
12};
13
14use super::Target;
15
16#[tracel_xtask_macros::declare_command_args(Target, DocSubCommand)]
17pub struct DocCmdArgs {}
18
19pub fn handle_command(args: DocCmdArgs, _env: Environment, _ctx: Context) -> anyhow::Result<()> {
20 if args.target == Target::Workspace && !args.only.is_empty() {
21 warn!("{WARN_IGNORED_ONLY_ARGS}");
22 }
23 match args.get_command() {
24 DocSubCommand::Build => run_documentation_build(&args.target, &args.exclude, &args.only),
25 DocSubCommand::Tests => run_documentation(&args.target, &args.exclude, &args.only),
26 }
27}
28
29fn run_documentation_build(
30 target: &Target,
31 excluded: &Vec<String>,
32 only: &Vec<String>,
33) -> anyhow::Result<()> {
34 match target {
35 Target::Workspace => {
36 group!("Build Workspace documentation");
37 run_process_for_workspace(
38 "cargo",
39 &["doc", "--workspace", "--no-deps", "--color=always"],
40 excluded,
41 None,
42 None,
43 "Workspace documentation build failed",
44 None,
45 None,
46 )?;
47 endgroup!();
48 }
49 Target::Crates | Target::Examples => {
50 let members = match target {
51 Target::Crates => get_workspace_members(WorkspaceMemberType::Crate),
52 Target::Examples => get_workspace_members(WorkspaceMemberType::Example),
53 _ => unreachable!(),
54 };
55
56 for member in members {
57 group!("Doc Build: {}", member.name);
58 run_process_for_package(
59 "cargo",
60 &member.name,
61 &["doc", "-p", &member.name, "--no-deps", "--color=always"],
62 excluded,
63 only,
64 &format!("Format check execution failed for {}", &member.name),
65 None,
66 None,
67 )?;
68 endgroup!();
69 }
70 }
71 Target::AllPackages => {
72 Target::iter()
73 .filter(|t| *t != Target::AllPackages && *t != Target::Workspace)
74 .try_for_each(|t| run_documentation_build(&t, excluded, only))?;
75 }
76 }
77 Ok(())
78}
79
80pub(crate) fn run_documentation(
81 target: &Target,
82 excluded: &[String],
83 only: &[String],
84) -> anyhow::Result<()> {
85 match target {
86 Target::Workspace => {
87 group!("Workspace Documentation Tests");
88 run_process_for_workspace(
89 "cargo",
90 &["test", "--workspace", "--doc", "--color", "always"],
91 excluded,
92 Some(r"Doc-tests (\w+)"),
93 Some("Doc Tests"),
94 "Workspace documentation test failed",
95 None,
96 None,
97 )?;
98 endgroup!();
99 }
100 Target::Crates | Target::Examples => {
101 let members = match target {
102 Target::Crates => get_workspace_members(WorkspaceMemberType::Crate),
103 Target::Examples => get_workspace_members(WorkspaceMemberType::Example),
104 _ => unreachable!(),
105 };
106
107 for member in members {
108 run_doc_test(&member, excluded, only)?;
109 }
110 }
111 Target::AllPackages => {
112 Target::iter()
113 .filter(|t| *t != Target::AllPackages && *t != Target::Workspace)
114 .try_for_each(|t| run_documentation(&t, excluded, only))?;
115 }
116 }
117 Ok(())
118}
119
120fn run_doc_test(
121 member: &WorkspaceMember,
122 excluded: &[String],
123 only: &[String],
124) -> Result<(), anyhow::Error> {
125 group!("Doc Tests: {}", member.name);
126 run_process_for_package(
127 "cargo",
128 &member.name,
129 &["test", "--doc", "-p", &member.name],
130 excluded,
131 only,
132 &format!(
133 "Failed to execute documentation test for '{}'",
134 &member.name
135 ),
136 Some("no library targets found"),
137 Some(&format!(
138 "No library found to test documentation for in the crate '{}'",
139 &member.name
140 )),
141 )?;
142 endgroup!();
143 Ok(())
144}