Skip to content

Commit

Permalink
fix(dotnet): "Could not infer JSII type for .NET type 'AnonymousObject'"
Browse files Browse the repository at this point in the history
When obtained through an untyped way (e.g: as part of an opaque object
for example), instances of `AnonymousObject` could not be cast back to
their Kernel form, because the converter lacked a code path to handle
this type. Instead, it insisted on trying to infer a "better" run-time
type for it.

This adds the necessary code path to handle this condition and properly
return the reverse conversion.

Fixes aws/aws-cdk#7977
  • Loading branch information
RomainMuller committed Jun 8, 2020
1 parent 61f8883 commit 3567bab
Show file tree
Hide file tree
Showing 12 changed files with 394 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public RuntimeException(string message)
const string Prefix = nameof(IntegrationTests) + ".Compliance.";

private readonly IDisposable _serviceContainerFixture;

public ComplianceTests(ITestOutputHelper outputHelper, ServiceContainerFixture serviceContainerFixture)
{
serviceContainerFixture.SetOverride(outputHelper);
Expand Down Expand Up @@ -1475,5 +1475,19 @@ public void CollectionOfInterfaces_MapOfInterfaces()
Assert.IsAssignableFrom<IBell>(elt);
}
}

[Fact(DisplayName = Prefix + nameof(BurriedAnonymousObject))]
public void BurriedAnonymousObject()
{
var subject = new BurriedAnonymousObjectImpl();
Assert.True(subject.Check());
}

private sealed class BurriedAnonymousObjectImpl : BurriedAnonymousObject
{
public override object GiveItBack(object value) {
return value;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Amazon.JSII.JsonModel.Spec;
using Amazon.JSII.Runtime.Deputy;
using System;

namespace Amazon.JSII.Runtime.Services.Converters
Expand Down Expand Up @@ -89,8 +90,17 @@ protected bool IsNumeric(System.Type type)
return null;
}

if (value is AnonymousObject)
{
if (!TryConvertClass(type, referenceMap, value, out var anonResult))
{
throw new Exception("Unable to convert AnonymousObject instance!");
}
return anonResult;
}

TypeReference reference = InferType(referenceMap, value);
if (TryConvert(reference, type, referenceMap, value, out object? result))
if (TryConvert(reference, type, referenceMap, value, out var result))
{
return result;
}
Expand Down
20 changes: 20 additions & 0 deletions packages/jsii-calc/lib/compliance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2490,3 +2490,23 @@ export class InterfaceCollections {
export interface IOptionalMethod {
optional(): string | undefined;
}

/**
* See https://github.com/aws/aws-cdk/issues/7977
*/
export abstract class BurriedAnonymousObject {
public check(): boolean {
const anonymousObject = { method() { return true; } };
const result = this.giveItBack({ anonymousObject });
return anonymousObject === result.anonymousObject;
}

/**
* Implement this method and have it return it's parameter.
*
* @param value the value that should be returned.
*
* @returns `value`
*/
public abstract giveItBack(value: any): any;
}
64 changes: 63 additions & 1 deletion packages/jsii-calc/test/assembly.jsii
Original file line number Diff line number Diff line change
Expand Up @@ -1561,6 +1561,68 @@
}
]
},
"jsii-calc.BurriedAnonymousObject": {
"abstract": true,
"assembly": "jsii-calc",
"docs": {
"stability": "experimental",
"summary": "See https://github.com/aws/aws-cdk/issues/7977."
},
"fqn": "jsii-calc.BurriedAnonymousObject",
"initializer": {},
"kind": "class",
"locationInModule": {
"filename": "lib/compliance.ts",
"line": 2497
},
"methods": [
{
"docs": {
"stability": "experimental"
},
"locationInModule": {
"filename": "lib/compliance.ts",
"line": 2498
},
"name": "check",
"returns": {
"type": {
"primitive": "boolean"
}
}
},
{
"abstract": true,
"docs": {
"returns": "`value`",
"stability": "experimental",
"summary": "Implement this method and have it return it's parameter."
},
"locationInModule": {
"filename": "lib/compliance.ts",
"line": 2511
},
"name": "giveItBack",
"parameters": [
{
"docs": {
"summary": "the value that should be returned."
},
"name": "value",
"type": {
"primitive": "any"
}
}
],
"returns": {
"type": {
"primitive": "any"
}
}
}
],
"name": "BurriedAnonymousObject"
},
"jsii-calc.Calculator": {
"assembly": "jsii-calc",
"base": "jsii-calc.composition.CompositeOperation",
Expand Down Expand Up @@ -13128,5 +13190,5 @@
}
},
"version": "0.0.0",
"fingerprint": "5SbCJfv1kDW24DUhPcwzoQ1k7Moq+rKOB+Q4TSZlKPE="
"fingerprint": "7VM/RrwzNCG/6tS4XA9gNbbADHnt/th93W72D8+pe94="
}
Original file line number Diff line number Diff line change
Expand Up @@ -1561,6 +1561,68 @@
}
]
},
"jsii-calc.BurriedAnonymousObject": {
"abstract": true,
"assembly": "jsii-calc",
"docs": {
"stability": "experimental",
"summary": "See https://github.com/aws/aws-cdk/issues/7977."
},
"fqn": "jsii-calc.BurriedAnonymousObject",
"initializer": {},
"kind": "class",
"locationInModule": {
"filename": "lib/compliance.ts",
"line": 2497
},
"methods": [
{
"docs": {
"stability": "experimental"
},
"locationInModule": {
"filename": "lib/compliance.ts",
"line": 2498
},
"name": "check",
"returns": {
"type": {
"primitive": "boolean"
}
}
},
{
"abstract": true,
"docs": {
"returns": "`value`",
"stability": "experimental",
"summary": "Implement this method and have it return it's parameter."
},
"locationInModule": {
"filename": "lib/compliance.ts",
"line": 2511
},
"name": "giveItBack",
"parameters": [
{
"docs": {
"summary": "the value that should be returned."
},
"name": "value",
"type": {
"primitive": "any"
}
}
],
"returns": {
"type": {
"primitive": "any"
}
}
}
],
"name": "BurriedAnonymousObject"
},
"jsii-calc.Calculator": {
"assembly": "jsii-calc",
"base": "jsii-calc.composition.CompositeOperation",
Expand Down Expand Up @@ -13128,5 +13190,5 @@
}
},
"version": "0.0.0",
"fingerprint": "5SbCJfv1kDW24DUhPcwzoQ1k7Moq+rKOB+Q4TSZlKPE="
"fingerprint": "7VM/RrwzNCG/6tS4XA9gNbbADHnt/th93W72D8+pe94="
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using Amazon.JSII.Runtime.Deputy;

#pragma warning disable CS0672,CS0809,CS1591

namespace Amazon.JSII.Tests.CalculatorNamespace
{
/// <summary>See https://github.com/aws/aws-cdk/issues/7977.</summary>
/// <remarks>
/// <strong>Stability</strong>: Experimental
/// </remarks>
[JsiiClass(nativeType: typeof(Amazon.JSII.Tests.CalculatorNamespace.BurriedAnonymousObject), fullyQualifiedName: "jsii-calc.BurriedAnonymousObject")]
public abstract class BurriedAnonymousObject : DeputyBase
{
protected BurriedAnonymousObject(): base(new DeputyProps(new object[]{}))
{
}

/// <summary>Used by jsii to construct an instance of this class from a Javascript-owned object reference</summary>
/// <param name="reference">The Javascript-owned object reference</param>
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
protected BurriedAnonymousObject(ByRefValue reference): base(reference)
{
}

/// <summary>Used by jsii to construct an instance of this class from DeputyProps</summary>
/// <param name="props">The deputy props</param>
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
protected BurriedAnonymousObject(DeputyProps props): base(props)
{
}

/// <remarks>
/// <strong>Stability</strong>: Experimental
/// </remarks>
[JsiiMethod(name: "check", returnsJson: "{\"type\":{\"primitive\":\"boolean\"}}")]
public virtual bool Check()
{
return InvokeInstanceMethod<bool>(new System.Type[]{}, new object[]{});
}

/// <summary>Implement this method and have it return it's parameter.</summary>
/// <param name="value">the value that should be returned.</param>
/// <returns>`value`</returns>
/// <remarks>
/// <strong>Stability</strong>: Experimental
/// </remarks>
[JsiiMethod(name: "giveItBack", returnsJson: "{\"type\":{\"primitive\":\"any\"}}", parametersJson: "[{\"docs\":{\"summary\":\"the value that should be returned.\"},\"name\":\"value\",\"type\":{\"primitive\":\"any\"}}]")]
public abstract object GiveItBack(object @value);

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Amazon.JSII.Runtime.Deputy;

#pragma warning disable CS0672,CS0809,CS1591

namespace Amazon.JSII.Tests.CalculatorNamespace
{
/// <summary>See https://github.com/aws/aws-cdk/issues/7977.</summary>
/// <remarks>
/// <strong>Stability</strong>: Experimental
/// </remarks>
[JsiiTypeProxy(nativeType: typeof(Amazon.JSII.Tests.CalculatorNamespace.BurriedAnonymousObject), fullyQualifiedName: "jsii-calc.BurriedAnonymousObject")]
internal sealed class BurriedAnonymousObjectProxy : Amazon.JSII.Tests.CalculatorNamespace.BurriedAnonymousObject
{
private BurriedAnonymousObjectProxy(ByRefValue reference): base(reference)
{
}

/// <summary>Implement this method and have it return it's parameter.</summary>
/// <param name="value">the value that should be returned.</param>
/// <returns>`value`</returns>
/// <remarks>
/// <strong>Stability</strong>: Experimental
/// </remarks>
[JsiiMethod(name: "giveItBack", returnsJson: "{\"type\":{\"primitive\":\"any\"}}", parametersJson: "[{\"docs\":{\"summary\":\"the value that should be returned.\"},\"name\":\"value\",\"type\":{\"primitive\":\"any\"}}]")]
public override object GiveItBack(object @value)
{
return InvokeInstanceMethod<object>(new System.Type[]{typeof(object)}, new object[]{@value});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package software.amazon.jsii.tests.calculator;

/**
* See https://github.com/aws/aws-cdk/issues/7977.
* <p>
* EXPERIMENTAL
*/
@javax.annotation.Generated(value = "jsii-pacmak")
@software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
@software.amazon.jsii.Jsii(module = software.amazon.jsii.tests.calculator.$Module.class, fqn = "jsii-calc.BurriedAnonymousObject")
public abstract class BurriedAnonymousObject extends software.amazon.jsii.JsiiObject {

protected BurriedAnonymousObject(final software.amazon.jsii.JsiiObjectRef objRef) {
super(objRef);
}

protected BurriedAnonymousObject(final software.amazon.jsii.JsiiObject.InitializationMode initializationMode) {
super(initializationMode);
}

protected BurriedAnonymousObject() {
super(software.amazon.jsii.JsiiObject.InitializationMode.JSII);
software.amazon.jsii.JsiiEngine.getInstance().createNewObject(this);
}

/**
* EXPERIMENTAL
*/
@software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
public @org.jetbrains.annotations.NotNull java.lang.Boolean check() {
return this.jsiiCall("check", java.lang.Boolean.class);
}

/**
* Implement this method and have it return it's parameter.
* <p>
* EXPERIMENTAL
* <p>
* @return `value`
* @param value the value that should be returned. This parameter is required.
*/
@software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
public abstract @org.jetbrains.annotations.NotNull java.lang.Object giveItBack(final @org.jetbrains.annotations.NotNull java.lang.Object value);

/**
* A proxy class which represents a concrete javascript instance of this type.
*/
final static class Jsii$Proxy extends software.amazon.jsii.tests.calculator.BurriedAnonymousObject {
protected Jsii$Proxy(final software.amazon.jsii.JsiiObjectRef objRef) {
super(objRef);
}

/**
* Implement this method and have it return it's parameter.
* <p>
* EXPERIMENTAL
* <p>
* @return `value`
* @param value the value that should be returned. This parameter is required.
*/
@software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental)
@Override
public @org.jetbrains.annotations.NotNull java.lang.Object giveItBack(final @org.jetbrains.annotations.NotNull java.lang.Object value) {
return this.jsiiCall("giveItBack", java.lang.Object.class, new Object[] { value });
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jsii-calc.AugmentableClass=software.amazon.jsii.tests.calculator.AugmentableClas
jsii-calc.BaseJsii976=software.amazon.jsii.tests.calculator.BaseJsii976
jsii-calc.Bell=software.amazon.jsii.tests.calculator.Bell
jsii-calc.BinaryOperation=software.amazon.jsii.tests.calculator.BinaryOperation
jsii-calc.BurriedAnonymousObject=software.amazon.jsii.tests.calculator.BurriedAnonymousObject
jsii-calc.Calculator=software.amazon.jsii.tests.calculator.Calculator
jsii-calc.CalculatorProps=software.amazon.jsii.tests.calculator.CalculatorProps
jsii-calc.ChildStruct982=software.amazon.jsii.tests.calculator.ChildStruct982
Expand Down
Loading

0 comments on commit 3567bab

Please sign in to comment.