flowey_lib_common/
run_cargo_clippy.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Clippy
5
6use crate::run_cargo_build::CargoBuildProfile;
7use crate::run_cargo_build::CargoFeatureSet;
8use flowey::node::prelude::*;
9
10#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
11pub enum CargoPackage {
12    Workspace,
13    Crate(String),
14}
15
16flowey_request! {
17    pub struct Request {
18        pub in_folder: ReadVar<PathBuf>,
19        pub package: CargoPackage,
20        pub profile: CargoBuildProfile,
21        pub features: CargoFeatureSet,
22        pub target: target_lexicon::Triple,
23        pub extra_env: Option<Vec<(String, String)>>,
24        pub exclude: ReadVar<Option<Vec<String>>>,
25        pub keep_going: bool,
26        pub all_targets: bool,
27        /// Wait for specified side-effects to resolve before running cargo-run.
28        ///
29        /// (e.g: to allow for some ambient packages / dependencies to get
30        /// installed).
31        pub pre_build_deps: Vec<ReadVar<SideEffect>>,
32        pub done: WriteVar<SideEffect>,
33    }
34}
35
36new_flow_node!(struct Node);
37
38impl FlowNode for Node {
39    type Request = Request;
40
41    fn imports(ctx: &mut ImportCtx<'_>) {
42        ctx.import::<crate::cfg_cargo_common_flags::Node>();
43        ctx.import::<crate::install_rust::Node>();
44    }
45
46    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
47        let rust_toolchain = ctx.reqv(crate::install_rust::Request::GetRustupToolchain);
48        let flags = ctx.reqv(crate::cfg_cargo_common_flags::Request::GetFlags);
49
50        for Request {
51            in_folder,
52            package,
53            profile,
54            features,
55            target,
56            extra_env,
57            exclude,
58            keep_going,
59            all_targets,
60            pre_build_deps,
61            done,
62        } in requests
63        {
64            ctx.req(crate::install_rust::Request::InstallTargetTriple(
65                target.clone(),
66            ));
67            ctx.req(crate::install_rust::Request::InstallComponent(
68                "clippy".into(),
69            ));
70
71            ctx.emit_rust_step("cargo clippy", |ctx| {
72                pre_build_deps.claim(ctx);
73                done.claim(ctx);
74                let rust_toolchain = rust_toolchain.clone().claim(ctx);
75                let flags = flags.clone().claim(ctx);
76                let in_folder = in_folder.claim(ctx);
77                let exclude = exclude.claim(ctx);
78                move |rt| {
79                    let rust_toolchain = rt.read(rust_toolchain);
80                    let flags = rt.read(flags);
81                    let in_folder = rt.read(in_folder);
82                    let exclude = rt.read(exclude);
83
84                    let crate::cfg_cargo_common_flags::Flags { locked, verbose } = flags;
85
86                    let target = target.to_string();
87
88                    let cargo_profile = match &profile {
89                        CargoBuildProfile::Debug => "dev",
90                        CargoBuildProfile::Release => "release",
91                        CargoBuildProfile::Custom(s) => s,
92                    };
93
94                    let mut args = Vec::new();
95
96                    args.push("clippy");
97                    if verbose {
98                        args.push("--verbose");
99                    }
100                    if locked {
101                        args.push("--locked");
102                    }
103                    if keep_going {
104                        args.push("--keep-going");
105                    }
106                    if all_targets {
107                        args.push("--all-targets");
108                    }
109                    match &package {
110                        CargoPackage::Workspace => args.push("--workspace"),
111                        CargoPackage::Crate(crate_name) => {
112                            args.push("-p");
113                            args.push(crate_name);
114                        }
115                    }
116                    let feature_strings = features.to_cargo_arg_strings();
117                    args.extend(feature_strings.iter().map(|s| s.as_str()));
118                    args.push("--target");
119                    args.push(&target);
120                    args.push("--profile");
121                    args.push(cargo_profile);
122                    if let Some(exclude) = &exclude {
123                        for excluded_crate in exclude {
124                            args.push("--exclude");
125                            args.push(excluded_crate);
126                        }
127                    }
128
129                    rt.sh.change_dir(in_folder);
130
131                    let mut cmd = if let Some(rust_toolchain) = &rust_toolchain {
132                        flowey::shell_cmd!(rt, "rustup run {rust_toolchain} cargo")
133                    } else {
134                        flowey::shell_cmd!(rt, "cargo")
135                    };
136
137                    // if running in CI, no need to waste time with incremental
138                    // build artifacts
139                    if !matches!(rt.backend(), FlowBackend::Local) {
140                        cmd = cmd.env("CARGO_INCREMENTAL", "0");
141                    }
142                    if let Some(env) = extra_env {
143                        for (key, val) in env {
144                            log::info!("env: {key}={val}");
145                            cmd = cmd.env(key, val);
146                        }
147                    }
148
149                    cmd.args(args).run()?;
150
151                    Ok(())
152                }
153            });
154        }
155
156        Ok(())
157    }
158}