Format .rs files with `rs_tokens_to_formatted_string`.
PiperOrigin-RevId: 487832692
diff --git a/cc_bindings_from_rs/BUILD b/cc_bindings_from_rs/BUILD
index ca2d5a4..8c81ed0 100644
--- a/cc_bindings_from_rs/BUILD
+++ b/cc_bindings_from_rs/BUILD
@@ -91,7 +91,9 @@
sh_test(
name = "cc_bindings_from_rs_sh_test",
srcs = ["cc_bindings_from_rs_sh_test.sh"],
- data = [":cc_bindings_from_rs_legacy_toolchain_runner.sar"],
+ data = [
+ ":cc_bindings_from_rs_legacy_toolchain_runner.sar",
+ ],
deps = [
"//util/shell/gbash",
"//util/shell/gbash:unit",
diff --git a/cc_bindings_from_rs/bazel_support/cc_bindings_from_rust_rule.bzl b/cc_bindings_from_rs/bazel_support/cc_bindings_from_rust_rule.bzl
index da18b08..71b24d8 100644
--- a/cc_bindings_from_rs/bazel_support/cc_bindings_from_rust_rule.bzl
+++ b/cc_bindings_from_rs/bazel_support/cc_bindings_from_rust_rule.bzl
@@ -21,10 +21,12 @@
crubit_args = ctx.actions.args()
crubit_args.add("--h-out", h_out_file)
crubit_args.add("--rs-out", rs_out_file)
+ crubit_args.add("--rustfmt-exe-path", ctx.file._rustfmt)
+ crubit_args.add("--rustfmt-config-path", ctx.file._rustfmt_cfg)
ctx.actions.run(
outputs = [h_out_file, rs_out_file],
- inputs = [crate_root],
+ inputs = [crate_root, ctx.file._rustfmt, ctx.file._rustfmt_cfg],
executable = ctx.executable._cc_bindings_from_rs_tool,
mnemonic = "CcBindingsFromRust",
progress_message = "Generating C++ bindings from Rust: %s" % h_out_file,
@@ -98,6 +100,16 @@
"_cc_toolchain": attr.label(
default = "@bazel_tools//tools/cpp:current_cc_toolchain",
),
+ "_rustfmt": attr.label(
+ default = "//third_party/unsupported_toolchains/rust/toolchains/nightly:bin/rustfmt",
+ executable = True,
+ allow_single_file = True,
+ cfg = "exec",
+ ),
+ "_rustfmt_cfg": attr.label(
+ default = "//nowhere:rustfmt.toml",
+ allow_single_file = True,
+ ),
},
fragments = ["cpp"],
)
diff --git a/cc_bindings_from_rs/cc_bindings_from_rs.rs b/cc_bindings_from_rs/cc_bindings_from_rs.rs
index 5efab52..6226426 100644
--- a/cc_bindings_from_rs/cc_bindings_from_rs.rs
+++ b/cc_bindings_from_rs/cc_bindings_from_rs.rs
@@ -29,7 +29,9 @@
use bindings::GeneratedBindings;
use cmdline::Cmdline;
-use token_stream_printer::cc_tokens_to_formatted_string;
+use token_stream_printer::{
+ cc_tokens_to_formatted_string, rs_tokens_to_formatted_string, RustfmtConfig,
+};
/// This mostly wraps and simplifies a subset of APIs from the `rustc_driver`
/// module.
@@ -159,14 +161,18 @@
fn run_with_tcx(cmdline: &Cmdline, tcx: TyCtxt) -> anyhow::Result<()> {
let bindings = GeneratedBindings::generate(tcx)?;
- write_file(&cmdline.h_out, cc_tokens_to_formatted_string(bindings.h_body)?.as_str())?;
- // TODO(b/254097223): Format `bindings.rs_body` via
- // `rs_tokens_to_formatted_string`. (This requires accepting a
- // mandatory`--rustfmt-exe-path` and an optional `--rustfmt-config-path`
- // as cmdline args). `bindings.rs_body` is mostly empty now so using
- // `cc_tokens_to_formatted_string` doesn't hurt that much in the short term.
- write_file(&cmdline.rs_out, cc_tokens_to_formatted_string(bindings.rs_body)?.as_str())?;
+ {
+ let h_body = cc_tokens_to_formatted_string(bindings.h_body)?;
+ write_file(&cmdline.h_out, &h_body)?;
+ }
+
+ {
+ let rustfmt_config =
+ RustfmtConfig::new(&cmdline.rustfmt_exe_path, cmdline.rustfmt_config_path.as_deref());
+ let rs_body = rs_tokens_to_formatted_string(bindings.rs_body, &rustfmt_config)?;
+ write_file(&cmdline.rs_out, &rs_body)?;
+ }
Ok(())
}
@@ -217,6 +223,7 @@
use itertools::Itertools;
use std::path::PathBuf;
use tempfile::{tempdir, TempDir};
+ use token_stream_printer::RUSTFMT_EXE_PATH_FOR_TESTING;
/// Test data builder (see also
/// https://testing.googleblog.com/2018/02/testing-on-toilet-cleanly-create-test.html).
@@ -317,6 +324,7 @@
"cc_bindings_from_rs_unittest_executable".to_string(),
format!("--h-out={}", h_path.display()),
format!("--rs-out={}", rs_path.display()),
+ format!("--rustfmt-exe-path={RUSTFMT_EXE_PATH_FOR_TESTING}"),
];
args.extend(self.extra_crubit_args.iter().cloned());
args.extend([
diff --git a/cc_bindings_from_rs/cc_bindings_from_rs_sh_test.sh b/cc_bindings_from_rs/cc_bindings_from_rs_sh_test.sh
index 9f0e7bd..1ceb541 100755
--- a/cc_bindings_from_rs/cc_bindings_from_rs_sh_test.sh
+++ b/cc_bindings_from_rs/cc_bindings_from_rs_sh_test.sh
@@ -20,6 +20,8 @@
rm -rf "$STDERR_PATH" "$STDOUT_PATH" "$H_OUT_PATH" "$RS_OUT_PATH"
}
+readonly DEFAULT_RUSTFMT_EXE_PATH="third_party/unsupported_toolchains/rust/toolchains/nightly/bin/rustfmt"
+
# This tests a simple happy, errors-free code path.
function test::happy_path() {
local RS_INPUT_PATH="${TEST_TMPDIR}/crate_name.rs"
@@ -35,8 +37,9 @@
delete_all_test_outputs
EXPECT_SUCCEED \
"\"${CC_BINDINGS_FROM_RS}\" >\"$STDOUT_PATH\" 2>\"$STDERR_PATH\" \
- \"--h-out=$H_OUT_PATH\" \
- \"--rs-out=$RS_OUT_PATH\" \
+ \"--h-out=${H_OUT_PATH}\" \
+ \"--rs-out=${RS_OUT_PATH}\" \
+ \"--rustfmt-exe-path=${DEFAULT_RUSTFMT_EXE_PATH}\" \
-- \
\"$RS_INPUT_PATH\" \
--crate-type=lib \
@@ -118,6 +121,7 @@
"\"${CC_BINDINGS_FROM_RS}\" >\"$STDOUT_PATH\" 2>\"$STDERR_PATH\" \
--h-out=../.. \
--rs-out=blah \
+ \"--rustfmt-exe-path=${DEFAULT_RUSTFMT_EXE_PATH}\" \
-- \
\"$RS_INPUT_PATH\" \
--crate-type=lib \
diff --git a/cc_bindings_from_rs/cmdline.rs b/cc_bindings_from_rs/cmdline.rs
index 6ec2ee3..140a950 100644
--- a/cc_bindings_from_rs/cmdline.rs
+++ b/cc_bindings_from_rs/cmdline.rs
@@ -18,6 +18,16 @@
#[clap(long, value_parser, value_name = "FILE")]
pub rs_out: PathBuf,
+ /// Path to a rustfmt executable that will be used to format the
+ /// .rs files generated by the tool.
+ #[clap(long, value_parser, value_name = "FILE")]
+ pub rustfmt_exe_path: PathBuf,
+
+ /// Path to a rustfmt.toml file that should replace the
+ /// default formatting of the .rs files generated by the tool.
+ #[clap(long, value_parser, value_name = "FILE")]
+ pub rustfmt_config_path: Option<PathBuf>,
+
/// Command line arguments of the Rust compiler.
#[clap(last = true, value_parser)]
pub rustc_args: Vec<String>,
@@ -72,16 +82,22 @@
#[test]
fn test_happy_path() {
- let cmdline =
- new_cmdline(["--h-out=foo.h", "--rs-out=foo_impl.rs"]).expect("This is a happy path");
+ let cmdline = new_cmdline([
+ "--h-out=foo.h",
+ "--rs-out=foo_impl.rs",
+ "--rustfmt-exe-path=rustfmt.exe",
+ ])
+ .expect("This is a happy path");
assert_eq!(Path::new("foo.h"), cmdline.h_out);
assert_eq!(Path::new("foo_impl.rs"), cmdline.rs_out);
+ assert_eq!(Path::new("rustfmt.exe"), cmdline.rustfmt_exe_path);
+ assert!(cmdline.rustfmt_config_path.is_none());
}
#[test]
fn test_rustc_args_happy_path() {
// Note that this test would fail without the `--` separator.
- let cmdline = new_cmdline(["--h-out=foo.h", "--rs-out=foo_impl.rs", "--", "test.rs", "--crate-type=lib"])
+ let cmdline = new_cmdline(["--h-out=foo.h", "--rs-out=foo_impl.rs", "--rustfmt-exe-path=rustfmt.exe", "--", "test.rs", "--crate-type=lib"])
.expect("This is a happy path");
let rustc_args = &cmdline.rustc_args;
assert!(
@@ -117,15 +133,19 @@
Generates C++ bindings for a Rust crate
USAGE:
- cc_bindings_from_rs_unittest_executable --h-out <FILE> --rs-out <FILE> [-- <RUSTC_ARGS>...]
+ cc_bindings_from_rs_unittest_executable [OPTIONS] --h-out <FILE> --rs-out <FILE> --rustfmt-exe-path <FILE> [-- <RUSTC_ARGS>...]
ARGS:
<RUSTC_ARGS>... Command line arguments of the Rust compiler
OPTIONS:
- --h-out <FILE> Output path for C++ header file with bindings
- -h, --help Print help information
- --rs-out <FILE> Output path for Rust implementation of the bindings
+ --h-out <FILE> Output path for C++ header file with bindings
+ -h, --help Print help information
+ --rs-out <FILE> Output path for Rust implementation of the bindings
+ --rustfmt-config-path <FILE> Path to a rustfmt.toml file that should replace the default
+ formatting of the .rs files generated by the tool
+ --rustfmt-exe-path <FILE> Path to a rustfmt executable that will be used to format
+ the .rs files generated by the tool
"#;
assert_eq!(expected_msg, clap_err.to_string());
}
@@ -136,7 +156,7 @@
let tmpfile = tmpdir.path().join("herefile");
std::fs::write(
&tmpfile,
- ["--h-out=foo.h", "--rs-out=foo_impl.rs", "--", "test.rs", "--crate-type=lib"].join("\n"),
+ ["--h-out=foo.h", "--rs-out=foo_impl.rs", "--rustfmt-exe-path=rustfmt.exe", "--", "test.rs", "--crate-type=lib"].join("\n"),
)?;
let flag_file_arg = format!("@{}", tmpfile.display());
diff --git a/common/token_stream_printer.rs b/common/token_stream_printer.rs
index b86ff7d..fb203ec 100644
--- a/common/token_stream_printer.rs
+++ b/common/token_stream_printer.rs
@@ -22,7 +22,7 @@
cmdline_args: Vec<OsString>,
}
-const RUSTFMT_EXE_PATH_FOR_TESTING: &str =
+pub const RUSTFMT_EXE_PATH_FOR_TESTING: &str =
"third_party/unsupported_toolchains/rust/toolchains/nightly/bin/rustfmt";
impl RustfmtConfig {