fn parse_config()

in tools/rust_analyzer/main.rs [53:102]


fn parse_config() -> anyhow::Result<Config> {
    let mut config = Config::from_args();

    // Ensure we know the workspace. If we are under `bazel run`, the
    // BUILD_WORKSPACE_DIR environment variable will be present.
    if config.workspace.is_none() {
        if let Some(ws_dir) = env::var_os("BUILD_WORKSPACE_DIRECTORY") {
            config.workspace = Some(PathBuf::from(ws_dir));
        }
    }

    if config.workspace.is_some() && config.execution_root.is_some() {
        return Ok(config);
    }

    // We need some info from `bazel info`. Fetch it now.
    let mut bazel_info_command = Command::new(&config.bazel);
    bazel_info_command.arg("info");
    if let Some(workspace) = &config.workspace {
        bazel_info_command.current_dir(workspace);
    }

    // Execute bazel info.
    let output = bazel_info_command.output()?;
    if !output.status.success() {
        return Err(anyhow!(
            "Failed to run `bazel info` ({:?}): {}",
            output.status,
            String::from_utf8_lossy(&output.stderr)
        ));
    }

    // Extract the output.
    let output = String::from_utf8_lossy(output.stdout.as_slice());
    let bazel_info = output
        .trim()
        .split('\n')
        .map(|line| line.split_at(line.find(':').expect("missing `:` in bazel info output")))
        .map(|(k, v)| (k, (&v[1..]).trim()))
        .collect::<HashMap<_, _>>();

    if config.workspace.is_none() {
        config.workspace = bazel_info.get("workspace").map(Into::into);
    }
    if config.execution_root.is_none() {
        config.execution_root = bazel_info.get("execution_root").map(Into::into);
    }

    Ok(config)
}