Skip to content

Commit

Permalink
Implement invocation location config
Browse files Browse the repository at this point in the history
  • Loading branch information
Veykril committed Oct 22, 2022
1 parent 19efa0b commit 96ce14f
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 26 deletions.
47 changes: 39 additions & 8 deletions crates/flycheck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ pub enum InvocationStrategy {
PerWorkspace,
}

#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub enum InvocationLocation {
Project(AbsPathBuf),
#[default]
Workspace,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum FlycheckConfig {
CargoCommand {
Expand All @@ -40,12 +47,14 @@ pub enum FlycheckConfig {
extra_args: Vec<String>,
extra_env: FxHashMap<String, String>,
invocation_strategy: InvocationStrategy,
invocation_location: InvocationLocation,
},
CustomCommand {
command: String,
args: Vec<String>,
extra_env: FxHashMap<String, String>,
invocation_strategy: InvocationStrategy,
invocation_location: InvocationLocation,
},
}

Expand Down Expand Up @@ -275,7 +284,7 @@ impl FlycheckActor {
}

fn check_command(&self) -> Command {
let (mut cmd, args, invocation_strategy) = match &self.config {
let (mut cmd, args, invocation_strategy, invocation_location) = match &self.config {
FlycheckConfig::CargoCommand {
command,
target_triple,
Expand All @@ -286,6 +295,7 @@ impl FlycheckActor {
features,
extra_env,
invocation_strategy,
invocation_location,
} => {
let mut cmd = Command::new(toolchain::cargo());
cmd.arg(command);
Expand All @@ -309,18 +319,39 @@ impl FlycheckActor {
}
}
cmd.envs(extra_env);
(cmd, extra_args, invocation_strategy)
(cmd, extra_args, invocation_strategy, invocation_location)
}
FlycheckConfig::CustomCommand { command, args, extra_env, invocation_strategy } => {
FlycheckConfig::CustomCommand {
command,
args,
extra_env,
invocation_strategy,
invocation_location,
} => {
let mut cmd = Command::new(command);
cmd.envs(extra_env);
(cmd, args, invocation_strategy)
(cmd, args, invocation_strategy, invocation_location)
}
};
match invocation_strategy {
InvocationStrategy::PerWorkspace => cmd.current_dir(&self.root),
InvocationStrategy::Once => cmd.args(args),
};

match invocation_location {
InvocationLocation::Workspace => {
match invocation_strategy {
InvocationStrategy::Once => {
cmd.current_dir(&self.root);
}
InvocationStrategy::PerWorkspace => {
// FIXME: cmd.current_dir(&affected_workspace);
cmd.current_dir(&self.root);
}
}
}
InvocationLocation::Project(root) => {
cmd.current_dir(root);
}
}

cmd.args(args);
cmd
}

Expand Down
39 changes: 22 additions & 17 deletions crates/project-model/src/build_scripts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ use semver::Version;
use serde::Deserialize;

use crate::{
cfg_flag::CfgFlag, CargoConfig, CargoFeatures, CargoWorkspace, InvocationStrategy, Package,
cfg_flag::CfgFlag, CargoConfig, CargoFeatures, CargoWorkspace, InvocationLocation,
InvocationStrategy, Package,
};

#[derive(Debug, Default, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -55,10 +56,7 @@ impl BuildScriptOutput {
}

impl WorkspaceBuildScripts {
fn build_command(
config: &CargoConfig,
workspace_root: Option<&path::Path>,
) -> io::Result<Command> {
fn build_command(config: &CargoConfig, current_dir: &path::Path) -> io::Result<Command> {
let mut cmd = match config.run_build_script_command.as_deref() {
Some([program, args @ ..]) => {
let mut cmd = Command::new(program);
Expand Down Expand Up @@ -94,14 +92,11 @@ impl WorkspaceBuildScripts {
}
}

if let Some(workspace_root) = workspace_root {
cmd.current_dir(workspace_root);
}

cmd
}
};

cmd.current_dir(current_dir);
cmd.envs(&config.extra_env);
if config.wrap_rustc_in_build_scripts {
// Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use
Expand All @@ -124,19 +119,19 @@ impl WorkspaceBuildScripts {
) -> io::Result<WorkspaceBuildScripts> {
const RUST_1_62: Version = Version::new(1, 62, 0);

let workspace_root: &path::Path = &workspace.workspace_root().as_ref();
let current_dir = match &config.invocation_location {
InvocationLocation::Project(root) => root.as_path(),
InvocationLocation::Workspace => &workspace.workspace_root(),
}
.as_ref();

match Self::run_per_ws(
Self::build_command(config, Some(workspace_root))?,
workspace,
progress,
) {
match Self::run_per_ws(Self::build_command(config, current_dir)?, workspace, progress) {
Ok(WorkspaceBuildScripts { error: Some(error), .. })
if toolchain.as_ref().map_or(false, |it| *it >= RUST_1_62) =>
{
// building build scripts failed, attempt to build with --keep-going so
// that we potentially get more build data
let mut cmd = Self::build_command(config, Some(workspace_root))?;
let mut cmd = Self::build_command(config, current_dir)?;
cmd.args(&["-Z", "unstable-options", "--keep-going"]).env("RUSTC_BOOTSTRAP", "1");
let mut res = Self::run_per_ws(cmd, workspace, progress)?;
res.error = Some(error);
Expand All @@ -154,7 +149,17 @@ impl WorkspaceBuildScripts {
progress: &dyn Fn(String),
) -> io::Result<Vec<WorkspaceBuildScripts>> {
assert_eq!(config.invocation_strategy, InvocationStrategy::Once);
let cmd = Self::build_command(config, None)?;

let current_dir = match &config.invocation_location {
InvocationLocation::Project(root) => root,
InvocationLocation::Workspace => {
return Err(io::Error::new(
io::ErrorKind::Other,
"Cannot run build scripts from workspace with invocation strategy `once`",
))
}
};
let cmd = Self::build_command(config, current_dir.as_path().as_ref())?;
// NB: Cargo.toml could have been modified between `cargo metadata` and
// `cargo check`. We shouldn't assume that package ids we see here are
// exactly those from `config`.
Expand Down
3 changes: 2 additions & 1 deletion crates/project-model/src/cargo_workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_hash::FxHashMap;
use serde::Deserialize;
use serde_json::from_value;

use crate::{utf8_stdout, ManifestPath};
use crate::{utf8_stdout, InvocationLocation, ManifestPath};
use crate::{CfgOverrides, InvocationStrategy};

/// [`CargoWorkspace`] represents the logical structure of, well, a Cargo
Expand Down Expand Up @@ -107,6 +107,7 @@ pub struct CargoConfig {
/// Extra env vars to set when invoking the cargo command
pub extra_env: FxHashMap<String, String>,
pub invocation_strategy: InvocationStrategy,
pub invocation_location: InvocationLocation,
}

impl CargoConfig {
Expand Down
7 changes: 7 additions & 0 deletions crates/project-model/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,10 @@ pub enum InvocationStrategy {
#[default]
PerWorkspace,
}

#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub enum InvocationLocation {
Project(AbsPathBuf),
#[default]
Workspace,
}
32 changes: 32 additions & 0 deletions crates/rust-analyzer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ config_data! {
cargo_autoreload: bool = "true",
/// Run build scripts (`build.rs`) for more precise code analysis.
cargo_buildScripts_enable: bool = "true",
/// Specifies the working directory for running build scripts.
/// - "workspace": run build scripts for a workspace in the workspace's root directory.
/// This is incompatible with `#rust-analyzer.cargo.buildScripts.invocationStrategy#` set to `once`.
/// - "project": run build scripts in the project's root directory.
cargo_buildScripts_invocationLocation: InvocationLocation = "\"workspace\"",
/// Specifies the invocation strategy to use when running the build scripts command.
/// If `per_workspace` is set, the command will be executed for each workspace from the
/// corresponding workspace root.
Expand Down Expand Up @@ -129,6 +134,12 @@ config_data! {
///
/// Set to `"all"` to pass `--all-features` to Cargo.
checkOnSave_features: Option<CargoFeaturesDef> = "null",
/// Specifies the working directory for running checks.
/// - "workspace": run checks for workspaces in the corresponding workspaces' root directories.
// FIXME: Ideally we would support this in some way
/// This falls back to "project" if `#rust-analyzer.cargo.checkOnSave.invocationStrategy#` is set to `once`.
/// - "project": run checks in the project's root directory.
checkOnSave_invocationLocation: InvocationLocation = "\"workspace\"",
/// Specifies the invocation strategy to use when running the checkOnSave command.
/// If `per_workspace` is set, the command will be executed for each workspace from the
/// corresponding workspace root.
Expand Down Expand Up @@ -1074,6 +1085,12 @@ impl Config {
InvocationStrategy::Once => project_model::InvocationStrategy::Once,
InvocationStrategy::PerWorkspace => project_model::InvocationStrategy::PerWorkspace,
},
invocation_location: match self.data.cargo_buildScripts_invocationLocation {
InvocationLocation::Project => {
project_model::InvocationLocation::Project(self.root_path.clone())
}
InvocationLocation::Workspace => project_model::InvocationLocation::Workspace,
},
run_build_script_command: self.data.cargo_buildScripts_overrideCommand.clone(),
extra_env: self.data.cargo_extraEnv.clone(),
}
Expand Down Expand Up @@ -1101,6 +1118,12 @@ impl Config {
InvocationStrategy::Once => flycheck::InvocationStrategy::Once,
InvocationStrategy::PerWorkspace => flycheck::InvocationStrategy::PerWorkspace,
};
let invocation_location = match self.data.checkOnSave_invocationLocation {
InvocationLocation::Project => {
flycheck::InvocationLocation::Project(self.root_path.clone())
}
InvocationLocation::Workspace => flycheck::InvocationLocation::Workspace,
};
let flycheck_config = match &self.data.checkOnSave_overrideCommand {
Some(args) if !args.is_empty() => {
let mut args = args.clone();
Expand All @@ -1110,6 +1133,7 @@ impl Config {
args,
extra_env: self.check_on_save_extra_env(),
invocation_strategy,
invocation_location,
}
}
Some(_) | None => FlycheckConfig::CargoCommand {
Expand Down Expand Up @@ -1140,6 +1164,7 @@ impl Config {
extra_args: self.data.checkOnSave_extraArgs.clone(),
extra_env: self.check_on_save_extra_env(),
invocation_strategy,
invocation_location,
},
};
Some(flycheck_config)
Expand Down Expand Up @@ -1618,6 +1643,13 @@ enum InvocationStrategy {
PerWorkspace,
}

#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
enum InvocationLocation {
Project,
Workspace,
}

#[derive(Deserialize, Debug, Clone)]
#[serde(untagged)]
enum LifetimeElisionDef {
Expand Down

0 comments on commit 96ce14f

Please sign in to comment.