Skip to content

Commit 181012e

Browse files
authored
fix(jsii): support public autoproperties in private constructor (#256)
Includes a fix in the .NET generator to add support for private constructors.
1 parent 660ae79 commit 181012e

File tree

13 files changed

+381
-122
lines changed

13 files changed

+381
-122
lines changed

packages/jsii-calc/lib/compliance.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,3 +914,11 @@ export class DoNotOverridePrivates {
914914
this.privateProperty = newValue;
915915
}
916916
}
917+
918+
/**
919+
* Class that implements interface properties automatically, but using a private constructor
920+
*/
921+
export class ClassWithPrivateConstructorAndAutomaticProperties implements IInterfaceWithProperties {
922+
private constructor(public readonly readOnlyString: string, public readWriteString: string) {
923+
}
924+
}

packages/jsii-calc/test/assembly.jsii

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,41 @@
10351035
}
10361036
]
10371037
},
1038+
"jsii-calc.ClassWithPrivateConstructorAndAutomaticProperties": {
1039+
"assembly": "jsii-calc",
1040+
"docs": {
1041+
"comment": "Class that implements interface properties automatically, but using a private constructor"
1042+
},
1043+
"fqn": "jsii-calc.ClassWithPrivateConstructorAndAutomaticProperties",
1044+
"interfaces": [
1045+
{
1046+
"fqn": "jsii-calc.IInterfaceWithProperties"
1047+
}
1048+
],
1049+
"kind": "class",
1050+
"name": "ClassWithPrivateConstructorAndAutomaticProperties",
1051+
"properties": [
1052+
{
1053+
"immutable": true,
1054+
"name": "readOnlyString",
1055+
"overrides": {
1056+
"fqn": "jsii-calc.IInterfaceWithProperties"
1057+
},
1058+
"type": {
1059+
"primitive": "string"
1060+
}
1061+
},
1062+
{
1063+
"name": "readWriteString",
1064+
"overrides": {
1065+
"fqn": "jsii-calc.IInterfaceWithProperties"
1066+
},
1067+
"type": {
1068+
"primitive": "string"
1069+
}
1070+
}
1071+
]
1072+
},
10381073
"jsii-calc.DefaultedConstructorArgument": {
10391074
"assembly": "jsii-calc",
10401075
"fqn": "jsii-calc.DefaultedConstructorArgument",
@@ -3297,5 +3332,5 @@
32973332
}
32983333
},
32993334
"version": "0.7.6",
3300-
"fingerprint": "IrPnQp841TiCOiG/Z2z18s0K8pxTwuMglW1UJ2t1zsM="
3335+
"fingerprint": "eFasWxN7YC37iWdz+dDbEFTSQCzyangrqP5Nu02rzpw="
33013336
}

packages/jsii-dotnet-generator/src/Amazon.JSII.Generator.UnitTests/Class/ClassGeneratorTests.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,36 @@ protected MyClass(DeputyProps props): base(props)
5757
Assert.Equal(expected, actual, ignoreLineEndingDifferences: true);
5858
}
5959

60+
[Fact(DisplayName = Prefix + nameof(AllowsPrivateConstructor))]
61+
public void AllowsPrivateConstructor()
62+
{
63+
ClassType classType = new ClassType
64+
(
65+
fullyQualifiedName: "myFqn",
66+
assembly: "myPackage",
67+
name: "myClass",
68+
isAbstract: false
69+
);
70+
71+
string actual = Render(classType);
72+
string expected =
73+
@"namespace MyNamespace
74+
{
75+
[JsiiClass(typeof(MyClass), ""myFqn"", ""[]"")]
76+
public class MyClass : DeputyBase
77+
{
78+
protected MyClass(ByRefValue reference): base(reference)
79+
{
80+
}
81+
82+
protected MyClass(DeputyProps props): base(props)
83+
{
84+
}
85+
}
86+
}";
87+
Assert.Equal(expected, actual, ignoreLineEndingDifferences: true);
88+
}
89+
6090
[Fact(DisplayName = Prefix + nameof(IncludesAbstractKeyword))]
6191
public void IncludesAbstractKeyword()
6292
{

packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/Class/ClassGenerator.cs

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
using Amazon.JSII.JsonModel.Spec;
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using Amazon.JSII.JsonModel.Spec;
24
using Microsoft.CodeAnalysis;
35
using Microsoft.CodeAnalysis.CSharp;
46
using Microsoft.CodeAnalysis.CSharp.Syntax;
5-
using System.Collections.Generic;
6-
using System.Linq;
77
using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
88

99
namespace Amazon.JSII.Generator.Class
@@ -97,37 +97,41 @@ IEnumerable<MemberDeclarationSyntax> CreateConstructors()
9797
{
9898
SyntaxToken typeName = Symbols.GetNameSyntaxToken(Type);
9999

100-
yield return SF.ConstructorDeclaration
101-
(
102-
SF.List<AttributeListSyntax>(),
103-
SF.TokenList(SF.Token(
104-
Type.IsAbstract || Type.Initializer.IsProtected ?
105-
SyntaxKind.ProtectedKeyword :
106-
SyntaxKind.PublicKeyword
107-
)),
108-
typeName,
109-
Type.Initializer.GetParameterListSyntax(Namespaces, Symbols),
110-
SF.ConstructorInitializer
100+
if (Type.Initializer != null)
101+
{
102+
yield return SF.ConstructorDeclaration
111103
(
112-
SyntaxKind.BaseConstructorInitializer,
113-
SF.ArgumentList(
114-
SF.SeparatedList(new[] {
115-
SF.Argument(
116-
SF.ObjectCreationExpression(
117-
SF.Token(SyntaxKind.NewKeyword),
118-
SF.ParseTypeName("DeputyProps"),
119-
SF.ArgumentList(SF.SeparatedList(
120-
new[] { GetBaseArgument() }
121-
)),
122-
null
104+
SF.List<AttributeListSyntax>(),
105+
SF.TokenList(SF.Token(
106+
Type.IsAbstract || Type.Initializer.IsProtected
107+
? SyntaxKind.ProtectedKeyword
108+
: SyntaxKind.PublicKeyword
109+
)),
110+
typeName,
111+
Type.Initializer.GetParameterListSyntax(Namespaces, Symbols),
112+
SF.ConstructorInitializer
113+
(
114+
SyntaxKind.BaseConstructorInitializer,
115+
SF.ArgumentList(
116+
SF.SeparatedList(new[]
117+
{
118+
SF.Argument(
119+
SF.ObjectCreationExpression(
120+
SF.Token(SyntaxKind.NewKeyword),
121+
SF.ParseTypeName("DeputyProps"),
122+
SF.ArgumentList(SF.SeparatedList(
123+
new[] {GetBaseArgument()}
124+
)),
125+
null
126+
)
123127
)
124-
)
125-
})
126-
)
127-
),
128-
SF.Block(),
129-
null
130-
);
128+
})
129+
)
130+
),
131+
SF.Block(),
132+
null
133+
);
134+
}
131135

132136
yield return SF.ConstructorDeclaration
133137
(

packages/jsii-dotnet-generator/src/Amazon.JSII.Generator/MethodExtensions.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
using Amazon.JSII.JsonModel.Spec;
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Amazon.JSII.JsonModel.Spec;
25
using Microsoft.CodeAnalysis;
36
using Microsoft.CodeAnalysis.CSharp.Syntax;
47
using Newtonsoft.Json;
5-
using System;
6-
using System.Collections.Generic;
7-
using System.Linq;
88
using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
99

1010
namespace Amazon.JSII.Generator
@@ -44,7 +44,7 @@ IEnumerable<ParameterSyntax> GetParameters()
4444
public static SyntaxToken GetParametersJsonSyntaxToken(this Method method)
4545
{
4646
// Strip docs before serializing.
47-
Parameter[] parameters = (method.Parameters ?? Enumerable.Empty<Parameter>())
47+
Parameter[] parameters = (method?.Parameters ?? Enumerable.Empty<Parameter>())
4848
.Select(p => new Parameter(p.Name, p.Type))
4949
.ToArray();
5050

0 commit comments

Comments
 (0)