Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[c#] add support for init-only setters on generated classes #1155

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions compiler/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,11 @@ csCodegen options@Cs {..} = do
typeMapping = if collection_interfaces
then csCollectionInterfacesTypeMapping
else csTypeMapping
fieldMapping = if readonly_properties
then ReadOnlyProperties
else if fields
then PublicFields
else Properties
fieldMapping
| readonly_properties = ReadOnlyProperties
| init_only_properties = InitOnlyProperties
| fields = PublicFields
| otherwise = Properties
constructorOptions = if constructor_parameters
then ConstructorParameters
else DefaultWithProtectedBase
Expand Down
4 changes: 3 additions & 1 deletion compiler/Options.hs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ data Options
, namespace :: [String]
, collection_interfaces :: Bool
, readonly_properties :: Bool
, init_only_properties :: Bool
, fields :: Bool
, jobs :: Maybe Int
, no_banner :: Bool
Expand Down Expand Up @@ -106,9 +107,10 @@ cs :: Options
cs = Cs
{ collection_interfaces = def &= name "c" &= help "Use interfaces rather than concrete collection types"
, readonly_properties = def &= name "r" &= help "Generate private property setters"
, init_only_properties = def &= name "init-only" &= help "Generate init-only property setters"
, fields = def &= name "f" &= help "Generate public fields rather than properties"
, structs_enabled = True &= explicit &= name "structs" &= help "Generate C# types for Bond structs and enums (true by default, use \"--structs=false\" to disable)"
, 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."
, 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."
} &=
name "c#" &=
help "Generate C# code"
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/Language/Bond/Codegen/Cs/Types_cs.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ data StructMapping =
data FieldMapping =
PublicFields | -- ^ public fields
Properties | -- ^ auto-properties
ReadOnlyProperties -- ^ auto-properties with private setter
ReadOnlyProperties | -- ^ auto-properties with private setter
InitOnlyProperties -- ^ auto-properties with init-only setter
deriving Eq

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

Expand Down
14 changes: 14 additions & 0 deletions compiler/tests/TestMain.hs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,13 @@ tests = testGroup "Compiler tests"
]
"complex_inheritance"
"constructor-parameters"
, verifyCodegenVariation
[ "c#"
, "--preview-constructor-parameters"
, "--init-only-properties"
]
"complex_inheritance"
"constructor-parameters_init"
, verifyCodegenVariation
[ "c#"
, "--preview-constructor-parameters"
Expand Down Expand Up @@ -180,6 +187,13 @@ tests = testGroup "Compiler tests"
]
"empty_struct"
"constructor-parameters"
, verifyCodegenVariation
[ "c#"
, "--preview-constructor-parameters"
, "--init-only-properties"
]
"empty_struct"
"constructor-parameters_init"
]
, testGroup "Java"
[ verifyJavaCodegen "attributes"
Expand Down
10 changes: 5 additions & 5 deletions compiler/tests/Tests/Codegen.hs
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@ verifyFiles options baseName variation =
extra options
where
verify = verifyFile options baseName
fieldMapping Cs {..} = if readonly_properties
then ReadOnlyProperties
else if fields
then PublicFields
else Properties
fieldMapping Cs {..}
| readonly_properties = ReadOnlyProperties
| init_only_properties = InitOnlyProperties
| fields = PublicFields
| otherwise = Properties
constructorOptions Cs {..} = if constructor_parameters
then ConstructorParameters
else DefaultWithProtectedBase
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@


// suppress "Missing XML comment for publicly visible type or member"
#pragma warning disable 1591


#region ReSharper warnings
// ReSharper disable PartialTypeWithSinglePart
// ReSharper disable RedundantNameQualifier
// ReSharper disable InconsistentNaming
// ReSharper disable CheckNamespace
// ReSharper disable UnusedParameter.Local
// ReSharper disable RedundantUsingDirective
#endregion

namespace Test
{
using System.Collections.Generic;

[System.CodeDom.Compiler.GeneratedCode("gbc", "0.12.1.0")]
public enum TestEnum
{
EnumVal1,
EnumVal2,
EnumVal3,
}

[global::Bond.Schema]
[System.CodeDom.Compiler.GeneratedCode("gbc", "0.12.1.0")]
public partial class Simple
{
[global::Bond.Id(0)]
public int someInt { get; init; }

[global::Bond.Id(1)]
public int anotherInt { get; init; }

[global::Bond.Id(2), global::Bond.Type(typeof(global::Bond.Tag.wstring))]
public string someString { get; init; }

public Simple(
int someInt,
int anotherInt,
string someString)
{
this.someInt = someInt;
this.anotherInt = anotherInt;
this.someString = someString;
}

public Simple()
{
someString = "";
}
}

[global::Bond.Schema]
[System.CodeDom.Compiler.GeneratedCode("gbc", "0.12.1.0")]
public partial class Foo
{
[global::Bond.Id(0), global::Bond.Type(typeof(global::Bond.Tag.wstring))]
public string someText { get; init; }

public Foo(
string someText)
{
this.someText = someText;
}

public Foo()
{
someText = "BaseText1";
}
}

[global::Bond.Schema]
[System.CodeDom.Compiler.GeneratedCode("gbc", "0.12.1.0")]
public partial class Bar
: Foo
{
[global::Bond.Id(0)]
public TestEnum testEnum { get; init; }

[global::Bond.Id(1), global::Bond.Type(typeof(global::Bond.Tag.wstring))]
new public string someText { get; init; }

[global::Bond.Id(2)]
public int someInt { get; init; }

[global::Bond.Id(3), global::Bond.Type(typeof(global::Bond.Tag.wstring))]
public string moreText { get; init; }

[global::Bond.Id(4), global::Bond.Type(typeof(List<Simple>))]
public IList<Simple> someList { get; init; }

[global::Bond.Id(5), global::Bond.Type(typeof(Dictionary<global::Bond.Tag.wstring, double>))]
public IDictionary<string, double> someMap { get; init; }

[global::Bond.Id(6), global::Bond.Type(typeof(HashSet<global::Bond.Tag.wstring>))]
public ISet<string> someSet { get; init; }

public Bar(
// Base class parameters
string someText,

// This class parameters
TestEnum testEnum,
string someText0,
int someInt,
string moreText,
IList<Simple> someList,
IDictionary<string, double> someMap,
ISet<string> someSet
) : base(
someText)
{
this.testEnum = testEnum;
this.someText = someText0;
this.someInt = someInt;
this.moreText = moreText;
this.someList = someList;
this.someMap = someMap;
this.someSet = someSet;
}

public Bar()
{
testEnum = TestEnum.Val2;
someText = "DerivedText1";
moreText = "";
someList = new List<Simple>();
someMap = new Dictionary<string, double>();
someSet = new HashSet<string>();
}
}

[global::Bond.Schema]
[System.CodeDom.Compiler.GeneratedCode("gbc", "0.12.1.0")]
public partial class Baz
: Bar
{
[global::Bond.Id(0), global::Bond.Type(typeof(global::Bond.Tag.wstring))]
new public string someText { get; init; }

[global::Bond.Id(1), global::Bond.Type(typeof(global::Bond.Tag.wstring))]
public string evenMoreText { get; init; }

[global::Bond.Id(2), global::Bond.Type(typeof(global::Bond.Tag.wstring))]
public string someText1 { get; init; }

public Baz(
// Base class parameters
string someText,
TestEnum testEnum,
string someText0,
int someInt,
string moreText,
IList<Simple> someList,
IDictionary<string, double> someMap,
ISet<string> someSet,

// This class parameters
string someText1,
string evenMoreText,
string someText10
) : base(
someText,
testEnum,
someText0,
someInt,
moreText,
someList,
someMap,
someSet)
{
this.someText = someText1;
this.evenMoreText = evenMoreText;
this.someText1 = someText10;
}

public Baz()
{
someText = "";
evenMoreText = "";
someText1 = "";
}
}

[global::Bond.Schema]
[System.CodeDom.Compiler.GeneratedCode("gbc", "0.12.1.0")]
public partial class DerivedEmpty
: Foo
{


public DerivedEmpty(
// Base class parameters
string someText
) : base(
someText)
{

}

public DerivedEmpty()
{

}
}
} // Test
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@


// suppress "Missing XML comment for publicly visible type or member"
#pragma warning disable 1591


#region ReSharper warnings
// ReSharper disable PartialTypeWithSinglePart
// ReSharper disable RedundantNameQualifier
// ReSharper disable InconsistentNaming
// ReSharper disable CheckNamespace
// ReSharper disable UnusedParameter.Local
// ReSharper disable RedundantUsingDirective
#endregion

namespace tests
{
using System.Collections.Generic;

[global::Bond.Schema]
[System.CodeDom.Compiler.GeneratedCode("gbc", "0.12.1.0")]
public partial class Empty
{

public Empty()
{

}
}
} // tests
Loading