Skip to content

Commit

Permalink
fix(.net): missing dynamic type checking for collection-nested unions (
Browse files Browse the repository at this point in the history
…#3720)

The .NET runtime type checking was not checking type unions that
are nested within a collection (list or map), although this is
necessary since the `is <type>` guard does not allow making any
assumption about the contents of the collection.

This adds the missing checks, and replaces the guard clauses
with a `switch` statement using pattern matching, resulting
in somewhat more elegant code (also with better `null` safety).

---

By submitting this pull request, I confirm that my contribution is made under the terms of the [Apache 2.0 license].

[Apache 2.0 license]: https://www.apache.org/licenses/LICENSE-2.0
  • Loading branch information
RomainMuller committed Aug 23, 2022
1 parent 897155e commit 362326e
Show file tree
Hide file tree
Showing 13 changed files with 1,764 additions and 592 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,29 @@ public void AnonymousObjectIsValid()
Assert.IsType<AnonymousObject>(anonymousObject);
Assert.Equal("A", UseOptions.Consume(anonymousObject));
}

[Fact(DisplayName = Prefix + nameof(NestedUnion))]
public void NestedUnion()
{
var exception1 = Assert.Throws<System.ArgumentException>(() =>
new ClassWithNestedUnion(new object[] { 1337.42 }));
Assert.Equal("Expected argument unionProperty[0] to be one of: System.Collections.Generic.IDictionary<string, object>, object[]; received System.Double (Parameter 'unionProperty')", exception1.Message);

var exception2 = Assert.Throws<System.ArgumentException>(() =>
new ClassWithNestedUnion(new object[]
{ new object[] { new StructA { RequiredString = "present" }, 1337 } }));
Assert.Equal("Expected argument unionProperty[0][1] to be one of: Amazon.JSII.Tests.CalculatorNamespace.IStructA, Amazon.JSII.Tests.CalculatorNamespace.IStructB; received System.Int32 (Parameter 'unionProperty')", exception2.Message);

var exception3 = Assert.Throws<System.ArgumentException>(() =>
new ClassWithNestedUnion(new object[]
{
new Dictionary<string, object>
{
{ "good", new StructA { RequiredString = "present" } },
{ "bad", "Not a StructA or StructB" }
}
}));
Assert.Equal("Expected argument unionProperty[0][\"bad\"] to be one of: Amazon.JSII.Tests.CalculatorNamespace.IStructA, Amazon.JSII.Tests.CalculatorNamespace.IStructB; received System.String (Parameter 'unionProperty')", exception3.Message);
}
}
}
8 changes: 8 additions & 0 deletions packages/jsii-calc/lib/compliance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3074,3 +3074,11 @@ export class ClassWithCollectionOfUnions {
export interface StructWithCollectionOfUnionts {
readonly unionProperty: Array<Record<string, StructA | StructB>>;
}

export class ClassWithNestedUnion {
public constructor(
public unionProperty: Array<
Array<StructA | StructB> | Record<string, StructA | StructB>
>,
) {}
}
132 changes: 131 additions & 1 deletion packages/jsii-calc/test/assembly.jsii
Original file line number Diff line number Diff line change
Expand Up @@ -2976,6 +2976,136 @@
],
"symbolId": "lib/compliance:ClassWithMutableObjectLiteralProperty"
},
"jsii-calc.ClassWithNestedUnion": {
"assembly": "jsii-calc",
"docs": {
"stability": "stable"
},
"fqn": "jsii-calc.ClassWithNestedUnion",
"initializer": {
"docs": {
"stability": "stable"
},
"locationInModule": {
"filename": "lib/compliance.ts",
"line": 3079
},
"parameters": [
{
"name": "unionProperty",
"type": {
"collection": {
"elementtype": {
"union": {
"types": [
{
"collection": {
"elementtype": {
"union": {
"types": [
{
"fqn": "jsii-calc.StructA"
},
{
"fqn": "jsii-calc.StructB"
}
]
}
},
"kind": "map"
}
},
{
"collection": {
"elementtype": {
"union": {
"types": [
{
"fqn": "jsii-calc.StructA"
},
{
"fqn": "jsii-calc.StructB"
}
]
}
},
"kind": "array"
}
}
]
}
},
"kind": "array"
}
}
}
]
},
"kind": "class",
"locationInModule": {
"filename": "lib/compliance.ts",
"line": 3078
},
"name": "ClassWithNestedUnion",
"properties": [
{
"docs": {
"stability": "stable"
},
"locationInModule": {
"filename": "lib/compliance.ts",
"line": 3080
},
"name": "unionProperty",
"type": {
"collection": {
"elementtype": {
"union": {
"types": [
{
"collection": {
"elementtype": {
"union": {
"types": [
{
"fqn": "jsii-calc.StructA"
},
{
"fqn": "jsii-calc.StructB"
}
]
}
},
"kind": "map"
}
},
{
"collection": {
"elementtype": {
"union": {
"types": [
{
"fqn": "jsii-calc.StructA"
},
{
"fqn": "jsii-calc.StructB"
}
]
}
},
"kind": "array"
}
}
]
}
},
"kind": "array"
}
}
}
],
"symbolId": "lib/compliance:ClassWithNestedUnion"
},
"jsii-calc.ClassWithPrivateConstructorAndAutomaticProperties": {
"assembly": "jsii-calc",
"docs": {
Expand Down Expand Up @@ -18001,5 +18131,5 @@
}
},
"version": "3.20.120",
"fingerprint": "w4jjSmxpafX7pHdksFL0F5FZxa/zM6MB8oFCANIU05k="
"fingerprint": "LBLJQQycukWu6zWQmp2/IbKS/Sfd+4e2zWrX+1KA+Aw="
}
Loading

0 comments on commit 362326e

Please sign in to comment.