Skip to content

Commit c416d23

Browse files
authored
run gofmt on generated code if available (#1457)
* run `gofmt` on generated code if available Signed-off-by: Joel Dice <joel.dice@fermyon.com> * add option to toggle gofmt Signed-off-by: Joel Dice <joel.dice@fermyon.com> --------- Signed-off-by: Joel Dice <joel.dice@fermyon.com>
1 parent e14b18c commit c416d23

File tree

1 file changed

+93
-12
lines changed

1 file changed

+93
-12
lines changed

crates/go/src/lib.rs

Lines changed: 93 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
use anyhow::Result;
22
use heck::{ToLowerCamelCase as _, ToSnakeCase as _, ToUpperCamelCase as _};
3+
use std::borrow::Cow;
34
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, hash_map};
5+
use std::fmt;
46
use std::fmt::Write as _;
7+
use std::io::{self, Write as _};
58
use std::iter;
69
use std::mem;
10+
use std::process::Command;
11+
use std::str::FromStr;
12+
use std::thread;
713
use wit_bindgen_core::abi::{
814
self, AbiVariant, Bindgen, Bitcast, FlatTypes, Instruction, LiftLower, WasmType,
915
};
@@ -27,9 +33,55 @@ const EXPORT_RETURN_AREA: &str = "exportReturnArea";
2733
const SYNC_EXPORT_PINNER: &str = "syncExportPinner";
2834
const PINNER: &str = "pinner";
2935

36+
#[derive(Default, Debug, Copy, Clone)]
37+
pub enum Format {
38+
#[default]
39+
True,
40+
False,
41+
}
42+
43+
impl fmt::Display for Format {
44+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45+
write!(
46+
f,
47+
"{}",
48+
match self {
49+
Self::True => "true",
50+
Self::False => "false",
51+
}
52+
)
53+
}
54+
}
55+
56+
impl FromStr for Format {
57+
type Err = String;
58+
59+
fn from_str(s: &str) -> Result<Format, String> {
60+
match s {
61+
"true" => Ok(Format::True),
62+
"false" => Ok(Format::False),
63+
_ => Err(format!("expected `true` or `false`; got `{s}`")),
64+
}
65+
}
66+
}
67+
3068
#[derive(Default, Debug, Clone)]
3169
#[cfg_attr(feature = "clap", derive(clap::Parser))]
3270
pub struct Opts {
71+
/// Whether or not `gofmt` should be used (if present) to format generated
72+
/// code.
73+
#[cfg_attr(
74+
feature = "clap",
75+
arg(
76+
long,
77+
default_value = "true",
78+
default_missing_value = "true",
79+
num_args = 0..=1,
80+
require_equals = true,
81+
)
82+
)]
83+
pub format: Format,
84+
3385
#[cfg_attr(feature = "clap", clap(flatten))]
3486
pub async_: AsyncFilterSet,
3587

@@ -717,8 +769,10 @@ impl WorldGenerator for Go {
717769

718770
files.push(
719771
"wit_bindings.go",
720-
format!(
721-
r#"package main
772+
&maybe_gofmt(
773+
self.opts.format,
774+
format!(
775+
r#"package main
722776
723777
import (
724778
"runtime"
@@ -734,8 +788,9 @@ var {SYNC_EXPORT_PINNER} = runtime.Pinner{{}}
734788
// Unused, but present to make the compiler happy
735789
func main() {{}}
736790
"#
737-
)
738-
.as_bytes(),
791+
)
792+
.as_bytes(),
793+
),
739794
);
740795
files.push("go.mod", b"module wit_component\n\ngo 1.25");
741796
files.push(
@@ -750,16 +805,19 @@ func main() {{}}
750805

751806
files.push(
752807
&format!("{prefix}{name}/wit_bindings.go"),
753-
format!(
754-
"package {prefix}{name}
808+
&maybe_gofmt(
809+
self.opts.format,
810+
format!(
811+
"package {prefix}{name}
755812
756813
import (
757814
{imports}
758815
)
759816
760817
{code}"
761-
)
762-
.as_bytes(),
818+
)
819+
.as_bytes(),
820+
),
763821
);
764822
}
765823
}
@@ -788,13 +846,16 @@ import (
788846

789847
files.push(
790848
"wit_types/wit_tuples.go",
791-
format!(
792-
r#"package wit_types
849+
&maybe_gofmt(
850+
self.opts.format,
851+
format!(
852+
r#"package wit_types
793853
794854
{tuples}
795855
"#
796-
)
797-
.as_bytes(),
856+
)
857+
.as_bytes(),
858+
),
798859
);
799860
}
800861

@@ -2948,3 +3009,23 @@ fn func_declaration(resolve: &Resolve, func: &Function) -> (String, bool) {
29483009
}
29493010
}
29503011
}
3012+
3013+
fn maybe_gofmt<'a>(format: Format, code: &'a [u8]) -> Cow<'a, [u8]> {
3014+
return thread::scope(|s| {
3015+
if let Format::True = format
3016+
&& let Ok((reader, mut writer)) = io::pipe()
3017+
{
3018+
s.spawn(move || {
3019+
_ = writer.write_all(&code);
3020+
});
3021+
3022+
if let Ok(output) = Command::new("gofmt").stdin(reader).output()
3023+
&& output.status.success()
3024+
{
3025+
return Cow::Owned(output.stdout);
3026+
}
3027+
}
3028+
3029+
Cow::Borrowed(code)
3030+
});
3031+
}

0 commit comments

Comments
 (0)