Skip to content

Commit

Permalink
fix(dotnet): Correctly handle 'void' callback results (#471)
Browse files Browse the repository at this point in the history
Previously, it attempted to generate an OptionalValue instance with no
`Type`, which is illegal.
  • Loading branch information
RomainMuller authored Apr 18, 2019
1 parent 7c6eeac commit 81e41bd
Show file tree
Hide file tree
Showing 18 changed files with 357 additions and 16 deletions.
19 changes: 19 additions & 0 deletions packages/jsii-calc/lib/compliance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1663,3 +1663,22 @@ export class StaticContext {

private constructor() { }
}

/**
* This test is used to validate the runtimes can return correctly from a void callback.
*
* - Implement `overrideMe` (method does not have to do anything).
* - Invoke `callMe`
* - Verify that `methodWasCalled` is `true`.
*/
export abstract class VoidCallback {
private _methodWasCalled = false;
public get methodWasCalled(): boolean {
return this._methodWasCalled;
}
public callMe(): void {
this.overrideMe();
this._methodWasCalled = true;
}
protected abstract overrideMe(): void;
}
49 changes: 48 additions & 1 deletion packages/jsii-calc/test/assembly.jsii
Original file line number Diff line number Diff line change
Expand Up @@ -6551,6 +6551,53 @@
],
"name": "VirtualMethodPlayground"
},
"jsii-calc.VoidCallback": {
"abstract": true,
"assembly": "jsii-calc",
"docs": {
"remarks": "- Implement `overrideMe` (method does not have to do anything).\n- Invoke `callMe`\n- Verify that `methodWasCalled` is `true`.",
"summary": "This test is used to validate the runtimes can return correctly from a void callback."
},
"fqn": "jsii-calc.VoidCallback",
"initializer": {},
"kind": "class",
"locationInModule": {
"filename": "lib/compliance.ts",
"line": 1674
},
"methods": [
{
"locationInModule": {
"filename": "lib/compliance.ts",
"line": 1679
},
"name": "callMe"
},
{
"abstract": true,
"locationInModule": {
"filename": "lib/compliance.ts",
"line": 1683
},
"name": "overrideMe",
"protected": true
}
],
"name": "VoidCallback",
"properties": [
{
"immutable": true,
"locationInModule": {
"filename": "lib/compliance.ts",
"line": 1676
},
"name": "methodWasCalled",
"type": {
"primitive": "boolean"
}
}
]
},
"jsii-calc.composition.CompositeOperation": {
"abstract": true,
"assembly": "jsii-calc",
Expand Down Expand Up @@ -6697,5 +6744,5 @@
}
},
"version": "0.10.1",
"fingerprint": "xAP41ArR/7KF9tmWHGtBlronNIVBQ/oDKKrhPoZ8otA="
"fingerprint": "975zFxt3ZCRvNKhp/Yh0HUwj9Gqz6I7YcagcGWY7UIY="
}
Original file line number Diff line number Diff line change
Expand Up @@ -905,7 +905,24 @@ public void ObjectIdDoesNotGetReallocatedWhenTheConstructorPassesThisOut()

Assert.NotNull(obj);
}

[Fact(DisplayName = Prefix + nameof(CorrectlyReturnsFromVoidCallback))]
public void CorrectlyReturnsFromVoidCallback()
{
var voidCallback = new VoidCallbackImpl();
voidCallback.CallMe();

Assert.True(voidCallback.MethodWasCalled);
}

class VoidCallbackImpl : VoidCallback
{
protected override void OverrideMe()
{
// Do nothing!
}
}

class PartiallyInitializedThisConsumerImpl : PartiallyInitializedThisConsumer
{
public override String ConsumePartiallyInitializedThis(ConstructorPassesThisOut obj, DateTime dt, AllTypesEnum ev)
Expand Down Expand Up @@ -961,10 +978,6 @@ public AddTen(int value)
}
}

class DerivedFromAllTypes : AllTypes
{
}

class OverrideAsyncMethods : AsyncVirtualMethods
{
public override double OverrideMe(double mult)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,8 @@ static CallbackResult InvokeMethod(InvokeRequest request, IReferenceMap referenc
}

JsiiMethodAttribute attribute = methodInfo.GetCustomAttribute<JsiiMethodAttribute>();
return new CallbackResult(
attribute?.Returns,
methodInfo.Invoke(deputy, request.Arguments.Select(arg => FromKernel(arg, referenceMap)).ToArray())
);
var returnValue = methodInfo.Invoke(deputy, request.Arguments.Select(arg => FromKernel(arg, referenceMap)).ToArray());
return attribute?.Returns != null ? new CallbackResult(attribute?.Returns, returnValue) : null;
}

static CallbackResult InvokeGetter(GetRequest request, IReferenceMap referenceMap)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Override[] GetOverrides()

IEnumerable<Override> GetMethodOverrides()
{
foreach (MethodInfo method in type.GetMethods())
foreach (MethodInfo method in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
JsiiMethodAttribute inheritedAttribute = method.GetCustomAttribute<JsiiMethodAttribute>(true);
JsiiMethodAttribute uninheritedAttribute = method.GetCustomAttribute<JsiiMethodAttribute>(false);
Expand All @@ -77,7 +77,7 @@ IEnumerable<Override> GetMethodOverrides()

IEnumerable<Override> GetPropertyOverrides()
{
foreach (PropertyInfo property in type.GetProperties())
foreach (PropertyInfo property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
JsiiPropertyAttribute inheritedAttribute = property.GetCustomAttribute<JsiiPropertyAttribute>(true);
JsiiPropertyAttribute uninheritedAttribute = property.GetCustomAttribute<JsiiPropertyAttribute>(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static FieldInfo GetEnumMember(Type enumType, string name)

public static MethodInfo GetNativeMethod(Type classType, string name)
{
MethodInfo methodInfo = classType.GetMethods().FirstOrDefault(method =>
MethodInfo methodInfo = classType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(method =>
{
JsiiMethodAttribute attribute = method.GetCustomAttribute<JsiiMethodAttribute>();
Expand All @@ -44,7 +44,7 @@ public static MethodInfo GetNativeMethod(Type classType, string name)

public static PropertyInfo GetNativeProperty(Type classType, string name)
{
PropertyInfo propertyInfo = classType.GetProperties().FirstOrDefault(property =>
PropertyInfo propertyInfo = classType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(property =>
{
JsiiPropertyAttribute attribute = property.GetCustomAttribute<JsiiPropertyAttribute>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6551,6 +6551,53 @@
],
"name": "VirtualMethodPlayground"
},
"jsii-calc.VoidCallback": {
"abstract": true,
"assembly": "jsii-calc",
"docs": {
"remarks": "- Implement `overrideMe` (method does not have to do anything).\n- Invoke `callMe`\n- Verify that `methodWasCalled` is `true`.",
"summary": "This test is used to validate the runtimes can return correctly from a void callback."
},
"fqn": "jsii-calc.VoidCallback",
"initializer": {},
"kind": "class",
"locationInModule": {
"filename": "lib/compliance.ts",
"line": 1674
},
"methods": [
{
"locationInModule": {
"filename": "lib/compliance.ts",
"line": 1679
},
"name": "callMe"
},
{
"abstract": true,
"locationInModule": {
"filename": "lib/compliance.ts",
"line": 1683
},
"name": "overrideMe",
"protected": true
}
],
"name": "VoidCallback",
"properties": [
{
"immutable": true,
"locationInModule": {
"filename": "lib/compliance.ts",
"line": 1676
},
"name": "methodWasCalled",
"type": {
"primitive": "boolean"
}
}
]
},
"jsii-calc.composition.CompositeOperation": {
"abstract": true,
"assembly": "jsii-calc",
Expand Down Expand Up @@ -6697,5 +6744,5 @@
}
},
"version": "0.10.1",
"fingerprint": "xAP41ArR/7KF9tmWHGtBlronNIVBQ/oDKKrhPoZ8otA="
"fingerprint": "975zFxt3ZCRvNKhp/Yh0HUwj9Gqz6I7YcagcGWY7UIY="
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Amazon.JSII.Runtime.Deputy;

namespace Amazon.JSII.Tests.CalculatorNamespace
{
/// <summary>This test is used to validate the runtimes can return correctly from a void callback.</summary>
/// <remarks>
/// - Implement `overrideMe` (method does not have to do anything).
/// - Invoke `callMe`
/// - Verify that `methodWasCalled` is `true`.
/// </remarks>
[JsiiClass(nativeType: typeof(VoidCallback), fullyQualifiedName: "jsii-calc.VoidCallback")]
public abstract class VoidCallback : DeputyBase
{
protected VoidCallback(): base(new DeputyProps(new object[]{}))
{
}

protected VoidCallback(ByRefValue reference): base(reference)
{
}

protected VoidCallback(DeputyProps props): base(props)
{
}

[JsiiProperty(name: "methodWasCalled", typeJson: "{\"primitive\":\"boolean\"}")]
public virtual bool MethodWasCalled
{
get => GetInstanceProperty<bool>();
}

[JsiiMethod(name: "callMe")]
public virtual void CallMe()
{
InvokeInstanceVoidMethod(new object[]{});
}

[JsiiMethod(name: "overrideMe")]
protected abstract void OverrideMe();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Amazon.JSII.Runtime.Deputy;

namespace Amazon.JSII.Tests.CalculatorNamespace
{
/// <summary>This test is used to validate the runtimes can return correctly from a void callback.</summary>
/// <remarks>
/// - Implement `overrideMe` (method does not have to do anything).
/// - Invoke `callMe`
/// - Verify that `methodWasCalled` is `true`.
/// </remarks>
[JsiiTypeProxy(nativeType: typeof(VoidCallback), fullyQualifiedName: "jsii-calc.VoidCallback")]
internal sealed class VoidCallbackProxy : VoidCallback
{
private VoidCallbackProxy(ByRefValue reference): base(reference)
{
}

[JsiiMethod(name: "overrideMe")]
protected override void OverrideMe()
{
InvokeInstanceVoidMethod(new object[]{});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ protected Class<?> resolveClass(final String fqn) throws ClassNotFoundException
case "jsii-calc.UsesInterfaceWithProperties": return software.amazon.jsii.tests.calculator.UsesInterfaceWithProperties.class;
case "jsii-calc.VariadicMethod": return software.amazon.jsii.tests.calculator.VariadicMethod.class;
case "jsii-calc.VirtualMethodPlayground": return software.amazon.jsii.tests.calculator.VirtualMethodPlayground.class;
case "jsii-calc.VoidCallback": return software.amazon.jsii.tests.calculator.VoidCallback.class;
case "jsii-calc.composition.CompositeOperation": return software.amazon.jsii.tests.calculator.composition.CompositeOperation.class;
case "jsii-calc.composition.CompositeOperation.CompositionStringStyle": return software.amazon.jsii.tests.calculator.composition.CompositeOperation.CompositionStringStyle.class;
default: throw new ClassNotFoundException("Unknown JSII type: " + fqn);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package software.amazon.jsii.tests.calculator;

/**
* This test is used to validate the runtimes can return correctly from a void callback.
*
* - Implement `overrideMe` (method does not have to do anything).
* - Invoke `callMe`
* - Verify that `methodWasCalled` is `true`.
*/
@javax.annotation.Generated(value = "jsii-pacmak")
@software.amazon.jsii.Jsii(module = software.amazon.jsii.tests.calculator.$Module.class, fqn = "jsii-calc.VoidCallback")
public abstract class VoidCallback extends software.amazon.jsii.JsiiObject {
protected VoidCallback(final software.amazon.jsii.JsiiObject.InitializationMode mode) {
super(mode);
}
public VoidCallback() {
super(software.amazon.jsii.JsiiObject.InitializationMode.Jsii);
software.amazon.jsii.JsiiEngine.getInstance().createNewObject(this);
}

public void callMe() {
this.jsiiCall("callMe", Void.class);
}

protected abstract void overrideMe();

public java.lang.Boolean getMethodWasCalled() {
return this.jsiiGet("methodWasCalled", java.lang.Boolean.class);
}

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

@Override
protected void overrideMe() {
this.jsiiCall("overrideMe", Void.class);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2450,6 +2450,35 @@ def sum_sync(self, count: jsii.Number) -> jsii.Number:
return jsii.invoke(self, "sumSync", [count])


class VoidCallback(metaclass=jsii.JSIIAbstractClass, jsii_type="jsii-calc.VoidCallback"):
@staticmethod
def __jsii_proxy_class__():
return _VoidCallbackProxy

def __init__(self) -> None:
jsii.create(VoidCallback, self, [])

@jsii.member(jsii_name="callMe")
def call_me(self) -> None:
return jsii.invoke(self, "callMe", [])

@jsii.member(jsii_name="overrideMe")
@abc.abstractmethod
def _override_me(self) -> None:
...

@property
@jsii.member(jsii_name="methodWasCalled")
def method_was_called(self) -> bool:
return jsii.get(self, "methodWasCalled")


class _VoidCallbackProxy(VoidCallback):
@jsii.member(jsii_name="overrideMe")
def _override_me(self) -> None:
return jsii.invoke(self, "overrideMe", [])


class composition:
class CompositeOperation(scope.jsii_calc_lib.Operation, metaclass=jsii.JSIIAbstractClass, jsii_type="jsii-calc.composition.CompositeOperation"):
@staticmethod
Expand Down Expand Up @@ -2629,6 +2658,6 @@ def parts(self, value: typing.List[scope.jsii_calc_lib.Value]):
return jsii.set(self, "parts", value)


__all__ = ["AbstractClass", "AbstractClassBase", "AbstractClassReturner", "Add", "AllTypes", "AllTypesEnum", "AllowedMethodNames", "AsyncVirtualMethods", "AugmentableClass", "BinaryOperation", "Calculator", "CalculatorProps", "ClassThatImplementsTheInternalInterface", "ClassThatImplementsThePrivateInterface", "ClassWithDocs", "ClassWithMutableObjectLiteralProperty", "ClassWithPrivateConstructorAndAutomaticProperties", "ConstructorPassesThisOut", "Constructors", "ConsumersOfThisCrazyTypeSystem", "DefaultedConstructorArgument", "DerivedClassHasNoProperties", "DerivedStruct", "DoNotOverridePrivates", "DoNotRecognizeAnyAsOptional", "DocumentedClass", "DontComplainAboutVariadicAfterOptional", "DoubleTrouble", "EraseUndefinedHashValues", "EraseUndefinedHashValuesOptions", "ExportedBaseClass", "ExtendsInternalInterface", "GiveMeStructs", "Greetee", "GreetingAugmenter", "IAnotherPublicInterface", "IExtendsPrivateInterface", "IFriendlier", "IFriendlyRandomGenerator", "IInterfaceImplementedByAbstractClass", "IInterfaceThatShouldNotBeADataType", "IInterfaceWithInternal", "IInterfaceWithMethods", "IInterfaceWithOptionalMethodArguments", "IInterfaceWithProperties", "IInterfaceWithPropertiesExtension", "IJSII417Derived", "IJSII417PublicBaseOfBase", "IMutableObjectLiteral", "INonInternalInterface", "IPrivatelyImplemented", "IPublicInterface", "IPublicInterface2", "IRandomNumberGenerator", "IReturnsNumber", "ImplementInternalInterface", "ImplementsInterfaceWithInternal", "ImplementsInterfaceWithInternalSubclass", "ImplementsPrivateInterface", "ImplictBaseOfBase", "InbetweenClass", "InterfaceInNamespaceIncludesClasses", "InterfaceInNamespaceOnlyInterface", "JSII417Derived", "JSII417PublicBaseOfBase", "JSObjectLiteralForInterface", "JSObjectLiteralToNative", "JSObjectLiteralToNativeClass", "JavaReservedWords", "JsiiAgent", "LoadBalancedFargateServiceProps", "Multiply", "Negate", "NodeStandardLibrary", "NullShouldBeTreatedAsUndefined", "NullShouldBeTreatedAsUndefinedData", "NumberGenerator", "ObjectRefsInCollections", "Old", "OptionalConstructorArgument", "OptionalStruct", "OptionalStructConsumer", "OverrideReturnsObject", "PartiallyInitializedThisConsumer", "Polymorphism", "Power", "PublicClass", "PythonReservedWords", "ReferenceEnumFromScopedPackage", "ReturnsPrivateImplementationOfInterface", "RuntimeTypeChecking", "SingleInstanceTwoTypes", "StaticContext", "Statics", "StringEnum", "StripInternal", "Sum", "SyncVirtualMethods", "Thrower", "UnaryOperation", "UnionProperties", "UseBundledDependency", "UseCalcBase", "UsesInterfaceWithProperties", "VariadicMethod", "VirtualMethodPlayground", "__jsii_assembly__", "composition"]
__all__ = ["AbstractClass", "AbstractClassBase", "AbstractClassReturner", "Add", "AllTypes", "AllTypesEnum", "AllowedMethodNames", "AsyncVirtualMethods", "AugmentableClass", "BinaryOperation", "Calculator", "CalculatorProps", "ClassThatImplementsTheInternalInterface", "ClassThatImplementsThePrivateInterface", "ClassWithDocs", "ClassWithMutableObjectLiteralProperty", "ClassWithPrivateConstructorAndAutomaticProperties", "ConstructorPassesThisOut", "Constructors", "ConsumersOfThisCrazyTypeSystem", "DefaultedConstructorArgument", "DerivedClassHasNoProperties", "DerivedStruct", "DoNotOverridePrivates", "DoNotRecognizeAnyAsOptional", "DocumentedClass", "DontComplainAboutVariadicAfterOptional", "DoubleTrouble", "EraseUndefinedHashValues", "EraseUndefinedHashValuesOptions", "ExportedBaseClass", "ExtendsInternalInterface", "GiveMeStructs", "Greetee", "GreetingAugmenter", "IAnotherPublicInterface", "IExtendsPrivateInterface", "IFriendlier", "IFriendlyRandomGenerator", "IInterfaceImplementedByAbstractClass", "IInterfaceThatShouldNotBeADataType", "IInterfaceWithInternal", "IInterfaceWithMethods", "IInterfaceWithOptionalMethodArguments", "IInterfaceWithProperties", "IInterfaceWithPropertiesExtension", "IJSII417Derived", "IJSII417PublicBaseOfBase", "IMutableObjectLiteral", "INonInternalInterface", "IPrivatelyImplemented", "IPublicInterface", "IPublicInterface2", "IRandomNumberGenerator", "IReturnsNumber", "ImplementInternalInterface", "ImplementsInterfaceWithInternal", "ImplementsInterfaceWithInternalSubclass", "ImplementsPrivateInterface", "ImplictBaseOfBase", "InbetweenClass", "InterfaceInNamespaceIncludesClasses", "InterfaceInNamespaceOnlyInterface", "JSII417Derived", "JSII417PublicBaseOfBase", "JSObjectLiteralForInterface", "JSObjectLiteralToNative", "JSObjectLiteralToNativeClass", "JavaReservedWords", "JsiiAgent", "LoadBalancedFargateServiceProps", "Multiply", "Negate", "NodeStandardLibrary", "NullShouldBeTreatedAsUndefined", "NullShouldBeTreatedAsUndefinedData", "NumberGenerator", "ObjectRefsInCollections", "Old", "OptionalConstructorArgument", "OptionalStruct", "OptionalStructConsumer", "OverrideReturnsObject", "PartiallyInitializedThisConsumer", "Polymorphism", "Power", "PublicClass", "PythonReservedWords", "ReferenceEnumFromScopedPackage", "ReturnsPrivateImplementationOfInterface", "RuntimeTypeChecking", "SingleInstanceTwoTypes", "StaticContext", "Statics", "StringEnum", "StripInternal", "Sum", "SyncVirtualMethods", "Thrower", "UnaryOperation", "UnionProperties", "UseBundledDependency", "UseCalcBase", "UsesInterfaceWithProperties", "VariadicMethod", "VirtualMethodPlayground", "VoidCallback", "__jsii_assembly__", "composition"]

publication.publish()
Loading

0 comments on commit 81e41bd

Please sign in to comment.