Skip to content

Commit 2b6c3f8

Browse files
committed
[c#] add support for init-only setters on generated classes
1 parent 79de73c commit 2b6c3f8

File tree

13 files changed

+540
-13
lines changed

13 files changed

+540
-13
lines changed

compiler/Main.hs

+5-5
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,11 @@ csCodegen options@Cs {..} = do
112112
typeMapping = if collection_interfaces
113113
then csCollectionInterfacesTypeMapping
114114
else csTypeMapping
115-
fieldMapping = if readonly_properties
116-
then ReadOnlyProperties
117-
else if fields
118-
then PublicFields
119-
else Properties
115+
fieldMapping
116+
| readonly_properties = ReadOnlyProperties
117+
| init_only_properties = InitOnlyProperties
118+
| fields = PublicFields
119+
| otherwise = Properties
120120
constructorOptions = if constructor_parameters
121121
then ConstructorParameters
122122
else DefaultWithProtectedBase

compiler/Options.hs

+3-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ data Options
5353
, namespace :: [String]
5454
, collection_interfaces :: Bool
5555
, readonly_properties :: Bool
56+
, init_only_properties :: Bool
5657
, fields :: Bool
5758
, jobs :: Maybe Int
5859
, no_banner :: Bool
@@ -106,9 +107,10 @@ cs :: Options
106107
cs = Cs
107108
{ collection_interfaces = def &= name "c" &= help "Use interfaces rather than concrete collection types"
108109
, readonly_properties = def &= name "r" &= help "Generate private property setters"
110+
, init_only_properties = def &= name "init-only" &= help "Generate init-only property setters"
109111
, fields = def &= name "f" &= help "Generate public fields rather than properties"
110112
, structs_enabled = True &= explicit &= name "structs" &= help "Generate C# types for Bond structs and enums (true by default, use \"--structs=false\" to disable)"
111-
, constructor_parameters = def &= explicit &= name "preview-constructor-parameters" &= help "PREVIEW FEATURE: Generate a constructor that takes all the fields as parameters. Typically used with readonly-properties."
113+
, constructor_parameters = def &= explicit &= name "preview-constructor-parameters" &= help "PREVIEW FEATURE: Generate a constructor that takes all the fields as parameters. Typically used with readonly-properties or init-only-properties."
112114
} &=
113115
name "c#" &=
114116
help "Generate C# code"

compiler/src/Language/Bond/Codegen/Cs/Types_cs.hs

+3-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ data StructMapping =
3131
data FieldMapping =
3232
PublicFields | -- ^ public fields
3333
Properties | -- ^ auto-properties
34-
ReadOnlyProperties -- ^ auto-properties with private setter
34+
ReadOnlyProperties | -- ^ auto-properties with private setter
35+
InitOnlyProperties -- ^ auto-properties with init-only setter
3536
deriving Eq
3637

3738
-- | Options for how constructors should be generated.
@@ -186,6 +187,7 @@ namespace #{csNamespace}
186187
PublicFields -> [lt|#{optional fieldInitializer $ csDefault f};|]
187188
Properties -> [lt| { get; set; }|]
188189
ReadOnlyProperties -> [lt| { get; private set; }|]
190+
InitOnlyProperties -> [lt| { get; init; }|]
189191
fieldInitializer x = [lt| = #{x}|]
190192
new = if isBaseField fieldName structBase then "new " else "" :: String
191193

compiler/tests/TestMain.hs

+14
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ tests = testGroup "Compiler tests"
151151
]
152152
"complex_inheritance"
153153
"constructor-parameters"
154+
, verifyCodegenVariation
155+
[ "c#"
156+
, "--preview-constructor-parameters"
157+
, "--init-only-properties"
158+
]
159+
"complex_inheritance"
160+
"constructor-parameters_init"
154161
, verifyCodegenVariation
155162
[ "c#"
156163
, "--preview-constructor-parameters"
@@ -180,6 +187,13 @@ tests = testGroup "Compiler tests"
180187
]
181188
"empty_struct"
182189
"constructor-parameters"
190+
, verifyCodegenVariation
191+
[ "c#"
192+
, "--preview-constructor-parameters"
193+
, "--init-only-properties"
194+
]
195+
"empty_struct"
196+
"constructor-parameters_init"
183197
]
184198
, testGroup "Java"
185199
[ verifyJavaCodegen "attributes"

compiler/tests/Tests/Codegen.hs

+5-5
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,11 @@ verifyFiles options baseName variation =
9191
extra options
9292
where
9393
verify = verifyFile options baseName
94-
fieldMapping Cs {..} = if readonly_properties
95-
then ReadOnlyProperties
96-
else if fields
97-
then PublicFields
98-
else Properties
94+
fieldMapping Cs {..}
95+
| readonly_properties = ReadOnlyProperties
96+
| init_only_properties = InitOnlyProperties
97+
| fields = PublicFields
98+
| otherwise = Properties
9999
constructorOptions Cs {..} = if constructor_parameters
100100
then ConstructorParameters
101101
else DefaultWithProtectedBase
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
2+
3+
// suppress "Missing XML comment for publicly visible type or member"
4+
#pragma warning disable 1591
5+
6+
7+
#region ReSharper warnings
8+
// ReSharper disable PartialTypeWithSinglePart
9+
// ReSharper disable RedundantNameQualifier
10+
// ReSharper disable InconsistentNaming
11+
// ReSharper disable CheckNamespace
12+
// ReSharper disable UnusedParameter.Local
13+
// ReSharper disable RedundantUsingDirective
14+
#endregion
15+
16+
namespace Test
17+
{
18+
using System.Collections.Generic;
19+
20+
[System.CodeDom.Compiler.GeneratedCode("gbc", "0.12.1.0")]
21+
public enum TestEnum
22+
{
23+
EnumVal1,
24+
EnumVal2,
25+
EnumVal3,
26+
}
27+
28+
[global::Bond.Schema]
29+
[System.CodeDom.Compiler.GeneratedCode("gbc", "0.12.1.0")]
30+
public partial class Simple
31+
{
32+
[global::Bond.Id(0)]
33+
public int someInt { get; init; }
34+
35+
[global::Bond.Id(1)]
36+
public int anotherInt { get; init; }
37+
38+
[global::Bond.Id(2), global::Bond.Type(typeof(global::Bond.Tag.wstring))]
39+
public string someString { get; init; }
40+
41+
public Simple(
42+
int someInt,
43+
int anotherInt,
44+
string someString)
45+
{
46+
this.someInt = someInt;
47+
this.anotherInt = anotherInt;
48+
this.someString = someString;
49+
}
50+
51+
public Simple()
52+
{
53+
someString = "";
54+
}
55+
}
56+
57+
[global::Bond.Schema]
58+
[System.CodeDom.Compiler.GeneratedCode("gbc", "0.12.1.0")]
59+
public partial class Foo
60+
{
61+
[global::Bond.Id(0), global::Bond.Type(typeof(global::Bond.Tag.wstring))]
62+
public string someText { get; init; }
63+
64+
public Foo(
65+
string someText)
66+
{
67+
this.someText = someText;
68+
}
69+
70+
public Foo()
71+
{
72+
someText = "BaseText1";
73+
}
74+
}
75+
76+
[global::Bond.Schema]
77+
[System.CodeDom.Compiler.GeneratedCode("gbc", "0.12.1.0")]
78+
public partial class Bar
79+
: Foo
80+
{
81+
[global::Bond.Id(0)]
82+
public TestEnum testEnum { get; init; }
83+
84+
[global::Bond.Id(1), global::Bond.Type(typeof(global::Bond.Tag.wstring))]
85+
new public string someText { get; init; }
86+
87+
[global::Bond.Id(2)]
88+
public int someInt { get; init; }
89+
90+
[global::Bond.Id(3), global::Bond.Type(typeof(global::Bond.Tag.wstring))]
91+
public string moreText { get; init; }
92+
93+
[global::Bond.Id(4), global::Bond.Type(typeof(List<Simple>))]
94+
public IList<Simple> someList { get; init; }
95+
96+
[global::Bond.Id(5), global::Bond.Type(typeof(Dictionary<global::Bond.Tag.wstring, double>))]
97+
public IDictionary<string, double> someMap { get; init; }
98+
99+
[global::Bond.Id(6), global::Bond.Type(typeof(HashSet<global::Bond.Tag.wstring>))]
100+
public ISet<string> someSet { get; init; }
101+
102+
public Bar(
103+
// Base class parameters
104+
string someText,
105+
106+
// This class parameters
107+
TestEnum testEnum,
108+
string someText0,
109+
int someInt,
110+
string moreText,
111+
IList<Simple> someList,
112+
IDictionary<string, double> someMap,
113+
ISet<string> someSet
114+
) : base(
115+
someText)
116+
{
117+
this.testEnum = testEnum;
118+
this.someText = someText0;
119+
this.someInt = someInt;
120+
this.moreText = moreText;
121+
this.someList = someList;
122+
this.someMap = someMap;
123+
this.someSet = someSet;
124+
}
125+
126+
public Bar()
127+
{
128+
testEnum = TestEnum.Val2;
129+
someText = "DerivedText1";
130+
moreText = "";
131+
someList = new List<Simple>();
132+
someMap = new Dictionary<string, double>();
133+
someSet = new HashSet<string>();
134+
}
135+
}
136+
137+
[global::Bond.Schema]
138+
[System.CodeDom.Compiler.GeneratedCode("gbc", "0.12.1.0")]
139+
public partial class Baz
140+
: Bar
141+
{
142+
[global::Bond.Id(0), global::Bond.Type(typeof(global::Bond.Tag.wstring))]
143+
new public string someText { get; init; }
144+
145+
[global::Bond.Id(1), global::Bond.Type(typeof(global::Bond.Tag.wstring))]
146+
public string evenMoreText { get; init; }
147+
148+
[global::Bond.Id(2), global::Bond.Type(typeof(global::Bond.Tag.wstring))]
149+
public string someText1 { get; init; }
150+
151+
public Baz(
152+
// Base class parameters
153+
string someText,
154+
TestEnum testEnum,
155+
string someText0,
156+
int someInt,
157+
string moreText,
158+
IList<Simple> someList,
159+
IDictionary<string, double> someMap,
160+
ISet<string> someSet,
161+
162+
// This class parameters
163+
string someText1,
164+
string evenMoreText,
165+
string someText10
166+
) : base(
167+
someText,
168+
testEnum,
169+
someText0,
170+
someInt,
171+
moreText,
172+
someList,
173+
someMap,
174+
someSet)
175+
{
176+
this.someText = someText1;
177+
this.evenMoreText = evenMoreText;
178+
this.someText1 = someText10;
179+
}
180+
181+
public Baz()
182+
{
183+
someText = "";
184+
evenMoreText = "";
185+
someText1 = "";
186+
}
187+
}
188+
189+
[global::Bond.Schema]
190+
[System.CodeDom.Compiler.GeneratedCode("gbc", "0.12.1.0")]
191+
public partial class DerivedEmpty
192+
: Foo
193+
{
194+
195+
196+
public DerivedEmpty(
197+
// Base class parameters
198+
string someText
199+
) : base(
200+
someText)
201+
{
202+
203+
}
204+
205+
public DerivedEmpty()
206+
{
207+
208+
}
209+
}
210+
} // Test
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
2+
3+
// suppress "Missing XML comment for publicly visible type or member"
4+
#pragma warning disable 1591
5+
6+
7+
#region ReSharper warnings
8+
// ReSharper disable PartialTypeWithSinglePart
9+
// ReSharper disable RedundantNameQualifier
10+
// ReSharper disable InconsistentNaming
11+
// ReSharper disable CheckNamespace
12+
// ReSharper disable UnusedParameter.Local
13+
// ReSharper disable RedundantUsingDirective
14+
#endregion
15+
16+
namespace tests
17+
{
18+
using System.Collections.Generic;
19+
20+
[global::Bond.Schema]
21+
[System.CodeDom.Compiler.GeneratedCode("gbc", "0.12.1.0")]
22+
public partial class Empty
23+
{
24+
25+
public Empty()
26+
{
27+
28+
}
29+
}
30+
} // tests

0 commit comments

Comments
 (0)