use crate::cli::pipeline::format::{converge_full_regen_formatting, poly_lint};
use crate::core::config::ResolvedCrateConfig;
use std::path::Path;
pub fn fmt(_config: &ResolvedCrateConfig, base_dir: &Path) -> anyhow::Result<()> {
converge_full_regen_formatting(base_dir);
Ok(())
}
pub fn lint(_config: &ResolvedCrateConfig, base_dir: &Path) -> anyhow::Result<()> {
poly_lint(base_dir)
}
pub fn fmt_post_generate(_config: &ResolvedCrateConfig, base_dir: &Path) {
converge_full_regen_formatting(base_dir);
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cli::pipeline::format::is_tool_available;
fn write_minimal_mix_project(elixir_dir: &Path, content: &str) {
std::fs::create_dir_all(elixir_dir.join("lib")).unwrap();
std::fs::write(
elixir_dir.join("mix.exs"),
"defmodule Sample.MixProject do\n use Mix.Project\n\n def project do\n [app: :sample, \
version: \"0.1.0\", elixir: \"~> 1.14\"]\n end\nend\n",
)
.unwrap();
std::fs::write(
elixir_dir.join(".formatter.exs"),
"[inputs: [\"mix.exs\", \"lib/**/*.{ex,exs}\"]]\n",
)
.unwrap();
std::fs::write(elixir_dir.join("lib/sample.ex"), content).unwrap();
}
#[test]
fn fmt_runs_mix_format_the_same_way_alef_all_does() {
if !is_tool_available("mix") {
return;
}
let dir = tempfile::tempdir().expect("tempdir");
let base = dir.path();
let elixir_dir = base.join("packages/elixir");
write_minimal_mix_project(&elixir_dir, "defmodule Sample do\n def noop, do: :ok\nend\n");
fmt(&ResolvedCrateConfig::default(), base).expect("fmt must succeed");
assert_eq!(
std::fs::read_to_string(elixir_dir.join("lib/sample.ex")).unwrap(),
"defmodule Sample do\n def noop, do: :ok\nend\n",
"`alef fmt` must run `mix format` on generated Elixir source, the same way \
`alef all` does"
);
}
#[test]
fn fmt_converges_to_the_same_workspace_sorted_poly_clean_state_as_alef_all() {
let dir = tempfile::tempdir().expect("tempdir");
let base = dir.path();
std::fs::write(
base.join("Cargo.toml"),
"[workspace]\nmembers = [\"crates/pkg-py\"]\nresolver = \"2\"\n",
)
.unwrap();
let crate_dir = base.join("crates/pkg-py");
std::fs::create_dir_all(crate_dir.join("src")).unwrap();
std::fs::write(
crate_dir.join("Cargo.toml"),
"[package]\nname = \"pkg-py\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n\
[dependencies]\nserde = \"1\"\nanyhow = \"1\"\n",
)
.unwrap();
std::fs::write(crate_dir.join("src/lib.rs"), "pub fn noop() {}\n").unwrap();
fmt(&ResolvedCrateConfig::default(), base).expect("fmt must succeed");
if is_tool_available("cargo-sort") {
let toml = std::fs::read_to_string(crate_dir.join("Cargo.toml")).unwrap();
let anyhow_pos = toml.find("anyhow").expect("anyhow present");
let serde_pos = toml.find("serde").expect("serde present");
assert!(
anyhow_pos < serde_pos,
"`alef fmt` must workspace-sort a crate with no per-language cargo-sort \
residual, got: {toml}"
);
}
if is_tool_available("poly") {
let check = std::process::Command::new("poly")
.args(["fmt", "--check", &base.to_string_lossy()])
.current_dir(base)
.status()
.expect("run poly fmt --check");
assert!(
check.success(),
"the tree `alef fmt` leaves behind must already be poly-fmt-clean"
);
}
}
#[test]
fn fmt_and_fmt_post_generate_both_delegate_to_the_shared_converging_pass() {
let source = include_str!("lint.rs");
let fmt_start = source.find("pub fn fmt(").expect("fmt function");
let fmt_post_start = source
.find("pub fn fmt_post_generate(")
.expect("fmt_post_generate function");
let tests_mod_start = source.find("#[cfg(test)]").expect("test module marker");
let fmt_body = &source[fmt_start..fmt_post_start];
let fmt_post_body = &source[fmt_post_start..tests_mod_start];
assert!(
fmt_body.contains("converge_full_regen_formatting(base_dir)"),
"`fmt` must delegate to `converge_full_regen_formatting`, not a bespoke pass"
);
assert!(
fmt_post_body.contains("converge_full_regen_formatting(base_dir)"),
"`fmt_post_generate` must delegate to `converge_full_regen_formatting`, not a \
bespoke pass"
);
}
}