Skip to content

Commit 563956d

Browse files
yowlsilesmo
andauthored
[C#] Idiomatic formatting (#1083)
* minor improvement to reduce unused using statements * use more idiomatic c# casing and bracket style * index on tidy-usings: f38910b use more idiomatic c# casing and bracket style * cargo fmr * remove TODO comment --------- Co-authored-by: Timmy Silesmo <silesmo@nor2.io>
1 parent 1739caf commit 563956d

File tree

4 files changed

+164
-70
lines changed

4 files changed

+164
-70
lines changed

crates/csharp/src/lib.rs

Lines changed: 141 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ impl WorldGenerator for CSharp {
461461
{access} readonly struct None {{}}
462462
463463
[StructLayout(LayoutKind.Sequential)]
464-
{access} readonly struct Result<Ok, Err>
464+
{access} readonly struct Result<TOk, TErr>
465465
{{
466466
{access} readonly byte Tag;
467467
private readonly object value;
@@ -472,43 +472,50 @@ impl WorldGenerator for CSharp {
472472
this.value = value;
473473
}}
474474
475-
{access} static Result<Ok, Err> ok(Ok ok)
475+
{access} static Result<TOk, TErr> Ok(TOk ok)
476476
{{
477-
return new Result<Ok, Err>(OK, ok!);
477+
return new Result<TOk, TErr>(Tags.Ok, ok!);
478478
}}
479479
480-
{access} static Result<Ok, Err> err(Err err)
480+
{access} static Result<TOk, TErr> Err(TErr err)
481481
{{
482-
return new Result<Ok, Err>(ERR, err!);
482+
return new Result<TOk, TErr>(Tags.Err, err!);
483483
}}
484484
485-
{access} bool IsOk => Tag == OK;
486-
{access} bool IsErr => Tag == ERR;
485+
{access} bool IsOk => Tag == Tags.Ok;
486+
{access} bool IsErr => Tag == Tags.Err;
487487
488-
{access} Ok AsOk
488+
{access} TOk AsOk
489489
{{
490490
get
491491
{{
492-
if (Tag == OK)
493-
return (Ok)value;
494-
else
495-
throw new ArgumentException("expected OK, got " + Tag);
492+
if (Tag == Tags.Ok)
493+
{{
494+
return (TOk)value;
495+
}}
496+
497+
throw new ArgumentException("expected k, got " + Tag);
496498
}}
497499
}}
498500
499-
{access} Err AsErr
501+
{access} TErr AsErr
500502
{{
501503
get
502504
{{
503-
if (Tag == ERR)
504-
return (Err)value;
505-
else
506-
throw new ArgumentException("expected ERR, got " + Tag);
505+
if (Tag == Tags.Err)
506+
{{
507+
return (TErr)value;
508+
}}
509+
510+
throw new ArgumentException("expected Err, got " + Tag);
507511
}}
508512
}}
509513
510-
{access} const byte OK = 0;
511-
{access} const byte ERR = 1;
514+
{access} class Tags
515+
{{
516+
{access} const byte Ok = 0;
517+
{access} const byte Err = 1;
518+
}}
512519
}}
513520
"#,
514521
)
@@ -1144,6 +1151,8 @@ impl InterfaceGenerator<'_> {
11441151

11451152
let import_name = &func.name;
11461153

1154+
self.gen.require_using("System.Runtime.InteropServices");
1155+
11471156
let target = if let FunctionKind::Freestanding = &func.kind {
11481157
self.require_interop_using("System.Runtime.InteropServices");
11491158
&mut self.csharp_interop_src
@@ -1865,7 +1874,7 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
18651874
.iter()
18661875
.map(|case| {
18671876
let case_name = case.name.to_csharp_ident();
1868-
let tag = case.name.to_shouty_snake_case();
1877+
let tag = case.name.to_csharp_ident_upper();
18691878
let (parameter, argument) = if let Some(ty) = self.non_empty_type(case.ty.as_ref())
18701879
{
18711880
(
@@ -1877,8 +1886,8 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
18771886
};
18781887

18791888
format!(
1880-
"{access} static {name} {case_name}({parameter}) {{
1881-
return new {name}({tag}, {argument});
1889+
"{access} static {name} {tag}({parameter}) {{
1890+
return new {name}(Tags.{tag}, {argument});
18821891
}}
18831892
"
18841893
)
@@ -1892,14 +1901,14 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
18921901
.filter_map(|case| {
18931902
self.non_empty_type(case.ty.as_ref()).map(|ty| {
18941903
let case_name = case.name.to_upper_camel_case();
1895-
let tag = case.name.to_shouty_snake_case();
1904+
let tag = case.name.to_csharp_ident_upper();
18961905
let ty = self.type_name(ty);
18971906
format!(
18981907
r#"{access} {ty} As{case_name}
18991908
{{
19001909
get
19011910
{{
1902-
if (Tag == {tag})
1911+
if (Tag == Tags.{tag})
19031912
return ({ty})value!;
19041913
else
19051914
throw new ArgumentException("expected {tag}, got " + Tag);
@@ -1917,7 +1926,7 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
19171926
.iter()
19181927
.enumerate()
19191928
.map(|(i, case)| {
1920-
let tag = case.name.to_shouty_snake_case();
1929+
let tag = case.name.to_csharp_ident_upper();
19211930
format!("{access} const {tag_type} {tag} = {i};")
19221931
})
19231932
.collect::<Vec<_>>()
@@ -1937,7 +1946,10 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
19371946
19381947
{constructors}
19391948
{accessors}
1940-
{tags}
1949+
1950+
{access} class Tags {{
1951+
{tags}
1952+
}}
19411953
}}
19421954
"
19431955
);
@@ -2195,7 +2207,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
21952207
String::new()
21962208
};
21972209

2198-
let method = case_name.to_csharp_ident();
2210+
let method = case_name.to_csharp_ident_upper();
21992211

22002212
let call = if let Some(position) = generics_position {
22012213
let (ty, generics) = ty.split_at(position);
@@ -2557,15 +2569,15 @@ impl Bindgen for FunctionBindgen<'_, '_> {
25572569
result,
25582570
..
25592571
} => self.lower_variant(
2560-
&[("ok", result.ok), ("err", result.err)],
2572+
&[("Ok", result.ok), ("Err", result.err)],
25612573
lowered_types,
25622574
&operands[0],
25632575
results,
25642576
),
25652577

25662578
Instruction::ResultLift { result, ty } => self.lift_variant(
25672579
&Type::Id(*ty),
2568-
&[("ok", result.ok), ("err", result.err)],
2580+
&[("Ok", result.ok), ("Err", result.err)],
25692581
&operands[0],
25702582
results,
25712583
),
@@ -2844,13 +2856,13 @@ impl Bindgen for FunctionBindgen<'_, '_> {
28442856
format!(
28452857
"\
28462858
case {index}: {{
2847-
ret = {head}{ty}.err(({err_ty}) e.Value){tail};
2859+
ret = {head}{ty}.Err(({err_ty}) e.Value){tail};
28482860
break;
28492861
}}
28502862
"
28512863
)
28522864
);
2853-
oks.push(format!("{ty}.ok("));
2865+
oks.push(format!("{ty}.Ok("));
28542866
payload_is_void = result.ok.is_none();
28552867
}
28562868
if !self.results.is_empty() {
@@ -3382,28 +3394,110 @@ fn is_primitive(ty: &Type) -> bool {
33823394
}
33833395

33843396
trait ToCSharpIdent: ToOwned {
3397+
fn csharp_keywords() -> Vec<&'static str>;
33853398
fn to_csharp_ident(&self) -> Self::Owned;
3399+
fn to_csharp_ident_upper(&self) -> Self::Owned;
33863400
}
33873401

33883402
impl ToCSharpIdent for str {
3403+
// Source: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/
3404+
fn csharp_keywords() -> Vec<&'static str> {
3405+
vec![
3406+
"abstract",
3407+
"as",
3408+
"base",
3409+
"bool",
3410+
"break",
3411+
"byte",
3412+
"case",
3413+
"catch",
3414+
"char",
3415+
"checked",
3416+
"class",
3417+
"const",
3418+
"continue",
3419+
"decimal",
3420+
"default",
3421+
"delegate",
3422+
"do",
3423+
"double",
3424+
"else",
3425+
"enum",
3426+
"event",
3427+
"explicit",
3428+
"extern",
3429+
"false",
3430+
"finally",
3431+
"fixed",
3432+
"float",
3433+
"for",
3434+
"foreach",
3435+
"goto",
3436+
"if",
3437+
"implicit",
3438+
"in",
3439+
"int",
3440+
"interface",
3441+
"internal",
3442+
"is",
3443+
"lock",
3444+
"long",
3445+
"namespace",
3446+
"new",
3447+
"null",
3448+
"object",
3449+
"operator",
3450+
"out",
3451+
"override",
3452+
"params",
3453+
"private",
3454+
"protected",
3455+
"public",
3456+
"readonly",
3457+
"ref",
3458+
"return",
3459+
"sbyte",
3460+
"sealed",
3461+
"short",
3462+
"sizeof",
3463+
"stackalloc",
3464+
"static",
3465+
"string",
3466+
"struct",
3467+
"switch",
3468+
"this",
3469+
"throw",
3470+
"true",
3471+
"try",
3472+
"typeof",
3473+
"uint",
3474+
"ulong",
3475+
"unchecked",
3476+
"unsafe",
3477+
"ushort",
3478+
"using",
3479+
"virtual",
3480+
"void",
3481+
"volatile",
3482+
"while",
3483+
]
3484+
}
3485+
33893486
fn to_csharp_ident(&self) -> String {
33903487
// Escape C# keywords
3391-
// Source: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/
3392-
3393-
//TODO: Repace with actual keywords
3394-
match self {
3395-
"abstract" | "as" | "base" | "bool" | "break" | "byte" | "case" | "catch" | "char"
3396-
| "checked" | "class" | "const" | "continue" | "decimal" | "default" | "delegate"
3397-
| "do" | "double" | "else" | "enum" | "event" | "explicit" | "extern" | "false"
3398-
| "finally" | "fixed" | "float" | "for" | "foreach" | "goto" | "if" | "implicit"
3399-
| "in" | "int" | "interface" | "internal" | "is" | "lock" | "long" | "namespace"
3400-
| "new" | "null" | "object" | "operator" | "out" | "override" | "params"
3401-
| "private" | "protected" | "public" | "readonly" | "ref" | "return" | "sbyte"
3402-
| "sealed" | "short" | "sizeof" | "stackalloc" | "static" | "string" | "struct"
3403-
| "switch" | "this" | "throw" | "true" | "try" | "typeof" | "uint" | "ulong"
3404-
| "unchecked" | "unsafe" | "ushort" | "using" | "virtual" | "void" | "volatile"
3405-
| "while" => format!("@{self}"),
3406-
_ => self.to_lower_camel_case(),
3488+
if Self::csharp_keywords().contains(&self) {
3489+
format!("@{}", self)
3490+
} else {
3491+
self.to_lower_camel_case()
3492+
}
3493+
}
3494+
3495+
fn to_csharp_ident_upper(&self) -> String {
3496+
// Escape C# keywords
3497+
if Self::csharp_keywords().contains(&self) {
3498+
format!("@{}", self)
3499+
} else {
3500+
self.to_upper_camel_case()
34073501
}
34083502
}
34093503
}

tests/runtime/resource_aggregates/wasm.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ public static uint Foo(
3333
var ir3 = new Import.R3(((Thing) r3.thing1).val, ((Thing) r3.thing2).val);
3434
var it1 = (((Thing) t1.Item1).val, new Import.R1(((Thing) t1.Item2.thing).val));
3535
var it2 = ((Thing) t2).val;
36-
var iv1 = Import.V1.thing(((Thing) v1.AsThing).val);
37-
var iv2 = Import.V2.thing(((Thing) v2.AsThing).val);
36+
var iv1 = Import.V1.Thing(((Thing) v1.AsThing).val);
37+
var iv2 = Import.V2.Thing(((Thing) v2.AsThing).val);
3838
var il1 = new List<Import.Thing>();
3939
foreach (var thing in l1)
4040
{
@@ -52,11 +52,11 @@ public static uint Foo(
5252
? ((Thing) o2).val
5353
: null;
5454
var iresult1 = result1.IsOk
55-
? Result<Import.Thing, None>.ok(((Thing) result1.AsOk).val)
56-
: Result<Import.Thing, None>.err(new None());
55+
? Result<Import.Thing, None>.Ok(((Thing) result1.AsOk).val)
56+
: Result<Import.Thing, None>.Err(new None());
5757
var iresult2 = result2.IsOk
58-
? Result<Import.Thing, None>.ok(((Thing) result2.AsOk).val)
59-
: Result<Import.Thing, None>.err(new None());
58+
? Result<Import.Thing, None>.Ok(((Thing) result2.AsOk).val)
59+
: Result<Import.Thing, None>.Err(new None());
6060

6161
return Host.Foo(ir1, ir2, ir3, it1, it2, iv1, iv2, il1, il2, io1, io2, iresult1, iresult2) + 4;
6262
}

tests/runtime/results/wasm.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,19 @@ public static float VariantError(float a)
4444
} catch (WitException e) {
4545
var value = (ResultsWorld.wit.imports.test.results.ITest.E3) e.Value;
4646
switch (value.Tag) {
47-
case ResultsWorld.wit.imports.test.results.ITest.E3.E1:
47+
case ResultsWorld.wit.imports.test.results.ITest.E3.Tags.E1:
4848
switch (value.AsE1) {
4949
case ResultsWorld.wit.imports.test.results.ITest.E.A:
50-
throw new WitException(ITest.E3.e1(ITest.E.A), 0);
50+
throw new WitException(ITest.E3.E1(ITest.E.A), 0);
5151
case ResultsWorld.wit.imports.test.results.ITest.E.B:
52-
throw new WitException(ITest.E3.e1(ITest.E.B), 0);
52+
throw new WitException(ITest.E3.E1(ITest.E.B), 0);
5353
case ResultsWorld.wit.imports.test.results.ITest.E.C:
54-
throw new WitException(ITest.E3.e1(ITest.E.C), 0);
54+
throw new WitException(ITest.E3.E1(ITest.E.C), 0);
5555
default:
5656
throw new Exception("unreachable");
5757
}
58-
case ResultsWorld.wit.imports.test.results.ITest.E3.E2: {
59-
throw new WitException(ITest.E3.e2(new ITest.E2(value.AsE2.line, value.AsE2.column)), 0);
58+
case ResultsWorld.wit.imports.test.results.ITest.E3.Tags.E2: {
59+
throw new WitException(ITest.E3.E2(new ITest.E2(value.AsE2.line, value.AsE2.column)), 0);
6060
}
6161
default:
6262
throw new Exception("unreachable");

0 commit comments

Comments
 (0)