From e15919b277d8c2fac717294bae965596e4d77ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Tue, 30 Oct 2018 17:42:52 +0100 Subject: [PATCH 1/3] fix(runtime/dotnet): Correct a number of type mappings The `jsii` compiler incorrectly mapped types homonym with a standard type (`String`, `Number`, ...) to the primitive type on usage sites. This commit corrects this behavior and adjusts the C# tests accordingly. Additionally, when the return type of a callback was an interface, the C# runtime was unable to determine the correct JSII type to use, despite it has the information on the type of the callback method available. The resolution behavior has also been fixes, as well as a couple of other glitches that became apparent as a result of the `Number` type starting to be correctly represented as the `@scope/jsii-calc-lib.Number` type. Fixes #290 Fixes awslabs/aws-cdk#1027 --- packages/jsii-calc-lib/lib/index.ts | 15 +++++-- packages/jsii-calc-lib/test/assembly.jsii | 29 ++++++++++++- packages/jsii-calc/lib/compliance.ts | 6 +-- packages/jsii-calc/test/assembly.jsii | 14 ++++-- .../ComplianceTests.cs | 43 +++++++++++++++++-- .../Amazon.JSII.Runtime/CallbackExtensions.cs | 22 +++++++--- .../Converters/FrameworkToJsiiConverter.cs | 4 ++ .../.jsii | 29 ++++++++++++- .../LibNamespace/IDoublableProxy.cs | 19 ++++++++ .../LibNamespace/IIDoublable.cs | 15 +++++++ .../LibNamespace/Number.cs | 2 +- .../jsii/tests/calculator/lib/$Module.java | 1 + .../jsii/tests/calculator/lib/IDoublable.java | 23 ++++++++++ .../jsii/tests/calculator/lib/Number.java | 3 +- .../sphinx/_scope_jsii-calc-lib.rst | 40 +++++++++++++++++ .../.jsii | 14 ++++-- .../Tests/CalculatorNamespace/AllTypes.cs | 11 ++--- .../CalculatorNamespace/IIReturnsNumber.cs | 9 ++-- .../IReturnsNumberProxy.cs | 13 +++--- .../jsii/tests/calculator/AllTypes.java | 8 +++- .../jsii/tests/calculator/IReturnsNumber.java | 12 +++--- .../expected.jsii-calc/sphinx/jsii-calc.rst | 12 +++--- packages/jsii/lib/assembler.ts | 20 ++++++--- packages/jsii/lib/compiler.ts | 14 ++++-- 24 files changed, 309 insertions(+), 69 deletions(-) create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/IDoublableProxy.cs create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/IIDoublable.cs create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/IDoublable.java diff --git a/packages/jsii-calc-lib/lib/index.ts b/packages/jsii-calc-lib/lib/index.ts index e7d0a1a801..fc05371a8f 100644 --- a/packages/jsii-calc-lib/lib/index.ts +++ b/packages/jsii-calc-lib/lib/index.ts @@ -7,20 +7,27 @@ export abstract class Value extends base.Base { /** * The value. */ - abstract readonly value: number + public abstract readonly value: number; /** * String representation of the value. */ - toString() { + public toString() { return this.value.toString(); } } +/** + * The general contract for a concrete number. + */ +export interface IDoublable { + readonly doubleValue: number; +} + /** * Represents a concrete number. */ -export class Number extends Value { +export class Number extends Value implements IDoublable { /** * Creates a Number object. * @param value The number. @@ -41,7 +48,7 @@ export class Number extends Value { * Represents an operation on values. */ export abstract class Operation extends Value { - abstract toString(): string + public abstract toString(): string; } /** diff --git a/packages/jsii-calc-lib/test/assembly.jsii b/packages/jsii-calc-lib/test/assembly.jsii index e351e0ce08..dc6ac23805 100644 --- a/packages/jsii-calc-lib/test/assembly.jsii +++ b/packages/jsii-calc-lib/test/assembly.jsii @@ -92,6 +92,25 @@ ], "name": "EnumFromScopedModule" }, + "@scope/jsii-calc-lib.IDoublable": { + "assembly": "@scope/jsii-calc-lib", + "docs": { + "comment": "The general contract for a concrete number." + }, + "fqn": "@scope/jsii-calc-lib.IDoublable", + "kind": "interface", + "name": "IDoublable", + "properties": [ + { + "abstract": true, + "immutable": true, + "name": "doubleValue", + "type": { + "primitive": "number" + } + } + ] + }, "@scope/jsii-calc-lib.IFriendly": { "assembly": "@scope/jsii-calc-lib", "docs": { @@ -184,6 +203,11 @@ } ] }, + "interfaces": [ + { + "fqn": "@scope/jsii-calc-lib.IDoublable" + } + ], "kind": "class", "name": "Number", "properties": [ @@ -193,6 +217,9 @@ }, "immutable": true, "name": "doubleValue", + "overrides": { + "fqn": "@scope/jsii-calc-lib.IDoublable" + }, "type": { "primitive": "number" } @@ -324,5 +351,5 @@ } }, "version": "0.7.8", - "fingerprint": "16sTfW7oHGAWfPOj50gWvXsI1REjbNbpk7VUpG1JVVI=" + "fingerprint": "HzcyHys0b9gFmP4dogeIJmGE6GVtrSo/P0S54Vd/X8U=" } diff --git a/packages/jsii-calc/lib/compliance.ts b/packages/jsii-calc/lib/compliance.ts index c8ab84a415..783a5a94cf 100644 --- a/packages/jsii-calc/lib/compliance.ts +++ b/packages/jsii-calc/lib/compliance.ts @@ -1,5 +1,5 @@ // tslint:disable -import { Value, Number, IFriendly, MyFirstStruct, StructWithOnlyOptionals, EnumFromScopedModule } from '@scope/jsii-calc-lib'; +import { Value, Number, IFriendly, IDoublable, MyFirstStruct, StructWithOnlyOptionals, EnumFromScopedModule } from '@scope/jsii-calc-lib'; import * as fs from 'fs'; import * as path from 'path'; import * as os from 'os'; @@ -574,7 +574,7 @@ export class AllowedMethodNames { } export interface IReturnsNumber { - obtainNumber(): Number; + obtainNumber(): IDoublable; readonly numberProp: Number; } @@ -938,4 +938,4 @@ export interface IInterfaceWithMethods { */ export interface IInterfaceThatShouldNotBeADataType extends IInterfaceWithMethods { readonly otherValue: string; -} \ No newline at end of file +} diff --git a/packages/jsii-calc/test/assembly.jsii b/packages/jsii-calc/test/assembly.jsii index 2aa5115a4b..c6ffb76b77 100644 --- a/packages/jsii-calc/test/assembly.jsii +++ b/packages/jsii-calc/test/assembly.jsii @@ -436,7 +436,7 @@ "type": { "collection": { "elementtype": { - "primitive": "number" + "fqn": "@scope/jsii-calc-lib.Number" }, "kind": "map" } @@ -486,6 +486,9 @@ }, { "primitive": "number" + }, + { + "fqn": "@scope/jsii-calc-lib.Number" } ] } @@ -507,6 +510,9 @@ }, { "fqn": "jsii-calc.Multiply" + }, + { + "fqn": "@scope/jsii-calc-lib.Number" } ] } @@ -1559,7 +1565,7 @@ "abstract": true, "name": "obtainNumber", "returns": { - "primitive": "number" + "fqn": "@scope/jsii-calc-lib.IDoublable" } } ], @@ -1570,7 +1576,7 @@ "immutable": true, "name": "numberProp", "type": { - "primitive": "number" + "fqn": "@scope/jsii-calc-lib.Number" } } ] @@ -3401,5 +3407,5 @@ } }, "version": "0.7.8", - "fingerprint": "fhzPkiQLwsWAnEdA5+YEotaWom2Av1au0q2FzpexXaQ=" + "fingerprint": "jHSXTzCSZbwYMvLKpeZB6SE8hNgYgt9/2JF1ihM41SI=" } diff --git a/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ComplianceTests.cs b/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ComplianceTests.cs index 9b287e9483..ff6747a7be 100644 --- a/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ComplianceTests.cs +++ b/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ComplianceTests.cs @@ -83,10 +83,10 @@ public void CollectionTypes() Assert.Equal("World", types.ArrayProperty[1]); // map - IDictionary map = new Dictionary(); - map["Foo"] = 123; + IDictionary map = new Dictionary(); + map["Foo"] = new Number(123); types.MapProperty = map; - Assert.Equal((double) 123, types.MapProperty["Foo"]); + Assert.Equal((double) 123, types.MapProperty["Foo"].Value); } [Fact(DisplayName = Prefix + nameof(DynamicTypes))] @@ -818,6 +818,43 @@ public void TestClassWithPrivateConstructorAndAutomaticProperties() Assert.Equal("Hello", obj.ReadOnlyString); } + [Fact(DisplayName = Prefix + nameof(TestReturnInterfaceFromOverride))] + public void TestReturnInterfaceFromOverride() + { + var n = 1337; + var obj = new OverrideReturnsObject(); + var arg = new NumberReturner(n); + Assert.Equal(4 * n, obj.Test(arg)); + } + + class NumberReturner : DeputyBase, IIReturnsNumber + { + public NumberReturner(double number) + { + NumberProp = new Number(number); + } + + [JsiiProperty("numberProp", "{\"fqn\":\"@scope/jsii-calc-lib.Number\"}", true)] + public Number NumberProp { get; } + + [JsiiMethod("obtainNumber", "{\"fqn\":\"@scope/jsii-calc-lib.IDoublable\"}", "[]",true)] + public IIDoublable ObtainNumber() + { + return new Doublable(this.NumberProp); + } + + class Doublable : DeputyBase, IIDoublable + { + public Doublable(Number number) + { + this.DoubleValue = number.DoubleValue; + } + + [JsiiProperty("doubleValue","{\"primitive\":\"number\"}",true)] + public Double DoubleValue { get; } + } + } + class MulTen : Multiply { public MulTen(int value) diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/CallbackExtensions.cs b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/CallbackExtensions.cs index ca1c259831..28b93c68b1 100644 --- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/CallbackExtensions.cs +++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/CallbackExtensions.cs @@ -15,10 +15,11 @@ public static object InvokeCallback(this Callback callback, IReferenceMap refere { try { - object frameworkResult = callback.InvokeCallbackCore(referenceMap); + TypeReference returnType; + object frameworkResult = callback.InvokeCallbackCore(referenceMap, out returnType); converter.TryConvert( - new TypeReference(primitive: PrimitiveType.Any), + returnType ?? new TypeReference(primitive: PrimitiveType.Any), referenceMap, frameworkResult, out object result @@ -41,28 +42,29 @@ out object result } } - static object InvokeCallbackCore(this Callback callback, IReferenceMap referenceMap) + static object InvokeCallbackCore(this Callback callback, IReferenceMap referenceMap, out TypeReference returnType) { if (callback.Invoke != null) { - return InvokeMethod(callback.Invoke, referenceMap); + return InvokeMethod(callback.Invoke, referenceMap, out returnType); } if (callback.Get != null) { - return InvokeGetter(callback.Get, referenceMap); + return InvokeGetter(callback.Get, referenceMap, out returnType); } if (callback.Set != null) { InvokeSetter(callback.Set, referenceMap); + returnType = null; return null; } throw new ArgumentException("Callback does not specificy a method, getter, or setter to invoke"); } - static object InvokeMethod(InvokeRequest request, IReferenceMap referenceMap) + static object InvokeMethod(InvokeRequest request, IReferenceMap referenceMap, out TypeReference returnType) { request = request ?? throw new ArgumentNullException(nameof(request)); DeputyBase deputy = referenceMap.GetOrCreateNativeReference(request.ObjectReference); @@ -74,10 +76,13 @@ static object InvokeMethod(InvokeRequest request, IReferenceMap referenceMap) throw new InvalidOperationException($"Received callback for {deputy.GetType().Name}.{request.Method} getter, but this method does not exist"); } + JsiiMethodAttribute attribute = methodInfo.GetCustomAttribute(); + returnType = attribute?.Returns; + return methodInfo.Invoke(deputy, request.Arguments); } - static object InvokeGetter(GetRequest request, IReferenceMap referenceMap) + static object InvokeGetter(GetRequest request, IReferenceMap referenceMap, out TypeReference returnType) { request = request ?? throw new ArgumentNullException(nameof(request)); DeputyBase deputy = referenceMap.GetOrCreateNativeReference(request.ObjectReference); @@ -88,6 +93,9 @@ static object InvokeGetter(GetRequest request, IReferenceMap referenceMap) throw new InvalidOperationException($"Received callback for {deputy.GetType().Name}.{request.Property} getter, but this property does not exist"); } + JsiiPropertyAttribute attribute = propertyInfo.GetCustomAttribute(); + returnType = attribute?.Type; + MethodInfo methodInfo = propertyInfo.GetGetMethod(); if (methodInfo == null) { diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/Converters/FrameworkToJsiiConverter.cs b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/Converters/FrameworkToJsiiConverter.cs index 9dabadcb95..f4cdbc674e 100644 --- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/Converters/FrameworkToJsiiConverter.cs +++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/Converters/FrameworkToJsiiConverter.cs @@ -251,6 +251,10 @@ protected override bool TryConvertMap(IReferenceMap referenceMap, TypeReference return false; } + if (convertedElement != null && !(convertedElement is String) && !convertedElement.GetType().IsPrimitive) + { + convertedElement = JObject.FromObject(convertedElement); + } resultObject.Add(new JProperty(key, convertedElement)); } diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/.jsii b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/.jsii index e351e0ce08..dc6ac23805 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/.jsii +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/.jsii @@ -92,6 +92,25 @@ ], "name": "EnumFromScopedModule" }, + "@scope/jsii-calc-lib.IDoublable": { + "assembly": "@scope/jsii-calc-lib", + "docs": { + "comment": "The general contract for a concrete number." + }, + "fqn": "@scope/jsii-calc-lib.IDoublable", + "kind": "interface", + "name": "IDoublable", + "properties": [ + { + "abstract": true, + "immutable": true, + "name": "doubleValue", + "type": { + "primitive": "number" + } + } + ] + }, "@scope/jsii-calc-lib.IFriendly": { "assembly": "@scope/jsii-calc-lib", "docs": { @@ -184,6 +203,11 @@ } ] }, + "interfaces": [ + { + "fqn": "@scope/jsii-calc-lib.IDoublable" + } + ], "kind": "class", "name": "Number", "properties": [ @@ -193,6 +217,9 @@ }, "immutable": true, "name": "doubleValue", + "overrides": { + "fqn": "@scope/jsii-calc-lib.IDoublable" + }, "type": { "primitive": "number" } @@ -324,5 +351,5 @@ } }, "version": "0.7.8", - "fingerprint": "16sTfW7oHGAWfPOj50gWvXsI1REjbNbpk7VUpG1JVVI=" + "fingerprint": "HzcyHys0b9gFmP4dogeIJmGE6GVtrSo/P0S54Vd/X8U=" } diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/IDoublableProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/IDoublableProxy.cs new file mode 100644 index 0000000000..2d5c772875 --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/IDoublableProxy.cs @@ -0,0 +1,19 @@ +using Amazon.JSII.Runtime.Deputy; + +namespace Amazon.JSII.Tests.CalculatorNamespace.LibNamespace +{ + /// The general contract for a concrete number. + [JsiiTypeProxy(typeof(IIDoublable), "@scope/jsii-calc-lib.IDoublable")] + internal sealed class IDoublableProxy : DeputyBase, IIDoublable + { + private IDoublableProxy(ByRefValue reference): base(reference) + { + } + + [JsiiProperty("doubleValue", "{\"primitive\":\"number\"}")] + public double DoubleValue + { + get => GetInstanceProperty(); + } + } +} \ No newline at end of file diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/IIDoublable.cs b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/IIDoublable.cs new file mode 100644 index 0000000000..d7260984a8 --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/IIDoublable.cs @@ -0,0 +1,15 @@ +using Amazon.JSII.Runtime.Deputy; + +namespace Amazon.JSII.Tests.CalculatorNamespace.LibNamespace +{ + /// The general contract for a concrete number. + [JsiiInterface(typeof(IIDoublable), "@scope/jsii-calc-lib.IDoublable")] + public interface IIDoublable + { + [JsiiProperty("doubleValue", "{\"primitive\":\"number\"}")] + double DoubleValue + { + get; + } + } +} \ No newline at end of file diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/Number.cs b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/Number.cs index f86323d0cc..e19ce0ad51 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/Number.cs +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon/JSII/Tests/CalculatorNamespace/LibNamespace/Number.cs @@ -4,7 +4,7 @@ namespace Amazon.JSII.Tests.CalculatorNamespace.LibNamespace { /// Represents a concrete number. [JsiiClass(typeof(Number), "@scope/jsii-calc-lib.Number", "[{\"name\":\"value\",\"type\":{\"primitive\":\"number\"}}]")] - public class Number : Value_ + public class Number : Value_, IIDoublable { public Number(double value): base(new DeputyProps(new object[]{value})) { diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/$Module.java b/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/$Module.java index 5b1453d5d0..52c6de750a 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/$Module.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/$Module.java @@ -19,6 +19,7 @@ public List> getDependencies() { protected Class resolveClass(final String fqn) throws ClassNotFoundException { switch (fqn) { case "@scope/jsii-calc-lib.EnumFromScopedModule": return software.amazon.jsii.tests.calculator.lib.EnumFromScopedModule.class; + case "@scope/jsii-calc-lib.IDoublable": return software.amazon.jsii.tests.calculator.lib.IDoublable.class; case "@scope/jsii-calc-lib.IFriendly": return software.amazon.jsii.tests.calculator.lib.IFriendly.class; case "@scope/jsii-calc-lib.MyFirstStruct": return software.amazon.jsii.tests.calculator.lib.MyFirstStruct.class; case "@scope/jsii-calc-lib.Number": return software.amazon.jsii.tests.calculator.lib.Number.class; diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/IDoublable.java b/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/IDoublable.java new file mode 100644 index 0000000000..a7cf2325fe --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/IDoublable.java @@ -0,0 +1,23 @@ +package software.amazon.jsii.tests.calculator.lib; + +/** + * The general contract for a concrete number. + */ +@javax.annotation.Generated(value = "jsii-pacmak") +public interface IDoublable extends software.amazon.jsii.JsiiSerializable { + java.lang.Number getDoubleValue(); + + /** + * A proxy class which represents a concrete javascript instance of this type. + */ + final static class Jsii$Proxy extends software.amazon.jsii.JsiiObject implements software.amazon.jsii.tests.calculator.lib.IDoublable { + protected Jsii$Proxy(final software.amazon.jsii.JsiiObject.InitializationMode mode) { + super(mode); + } + + @Override + public java.lang.Number getDoubleValue() { + return this.jsiiGet("doubleValue", java.lang.Number.class); + } + } +} diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/Number.java b/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/Number.java index a14b6fe024..0f023695d2 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/Number.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/Number.java @@ -5,7 +5,7 @@ */ @javax.annotation.Generated(value = "jsii-pacmak") @software.amazon.jsii.Jsii(module = software.amazon.jsii.tests.calculator.lib.$Module.class, fqn = "@scope/jsii-calc-lib.Number") -public class Number extends software.amazon.jsii.tests.calculator.lib.Value { +public class Number extends software.amazon.jsii.tests.calculator.lib.Value implements software.amazon.jsii.tests.calculator.lib.IDoublable { protected Number(final software.amazon.jsii.JsiiObject.InitializationMode mode) { super(mode); } @@ -21,6 +21,7 @@ public Number(final java.lang.Number value) { /** * The number multiplied by 2. */ + @Override public java.lang.Number getDoubleValue() { return this.jsiiGet("doubleValue", java.lang.Number.class); } diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/sphinx/_scope_jsii-calc-lib.rst b/packages/jsii-pacmak/test/expected.jsii-calc-lib/sphinx/_scope_jsii-calc-lib.rst index 9cac7a500a..0121d0e144 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/sphinx/_scope_jsii-calc-lib.rst +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/sphinx/_scope_jsii-calc-lib.rst @@ -158,6 +158,43 @@ EnumFromScopedModule (enum) .. py:data:: Value2 +IDoublable (interface) +^^^^^^^^^^^^^^^^^^^^^^ + +.. py:class:: IDoublable + + **Language-specific names:** + + .. tabs:: + + .. code-tab:: c# + + using Amazon.JSII.Tests.CalculatorNamespace.LibNamespace; + + .. code-tab:: java + + import software.amazon.jsii.tests.calculator.lib.IDoublable; + + .. code-tab:: javascript + + // IDoublable is an interface + + .. code-tab:: typescript + + import { IDoublable } from '@scope/jsii-calc-lib'; + + + + The general contract for a concrete number. + + + + + .. py:attribute:: doubleValue + + :type: number *(readonly)* *(abstract)* + + IFriendly (interface) ^^^^^^^^^^^^^^^^^^^^^ @@ -283,11 +320,14 @@ Number :extends: :py:class:`~@scope/jsii-calc-lib.Value`\ + :implements: :py:class:`~@scope/jsii-calc-lib.IDoublable`\ :param value: The number. :type value: number .. py:attribute:: doubleValue + *Implements* :py:meth:`@scope/jsii-calc-lib.IDoublable.doubleValue` + The number multiplied by 2. diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii index 2aa5115a4b..c6ffb76b77 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii @@ -436,7 +436,7 @@ "type": { "collection": { "elementtype": { - "primitive": "number" + "fqn": "@scope/jsii-calc-lib.Number" }, "kind": "map" } @@ -486,6 +486,9 @@ }, { "primitive": "number" + }, + { + "fqn": "@scope/jsii-calc-lib.Number" } ] } @@ -507,6 +510,9 @@ }, { "fqn": "jsii-calc.Multiply" + }, + { + "fqn": "@scope/jsii-calc-lib.Number" } ] } @@ -1559,7 +1565,7 @@ "abstract": true, "name": "obtainNumber", "returns": { - "primitive": "number" + "fqn": "@scope/jsii-calc-lib.IDoublable" } } ], @@ -1570,7 +1576,7 @@ "immutable": true, "name": "numberProp", "type": { - "primitive": "number" + "fqn": "@scope/jsii-calc-lib.Number" } } ] @@ -3401,5 +3407,5 @@ } }, "version": "0.7.8", - "fingerprint": "fhzPkiQLwsWAnEdA5+YEotaWom2Av1au0q2FzpexXaQ=" + "fingerprint": "jHSXTzCSZbwYMvLKpeZB6SE8hNgYgt9/2JF1ihM41SI=" } diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/AllTypes.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/AllTypes.cs index b4a4896b31..489e96e84c 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/AllTypes.cs +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/AllTypes.cs @@ -1,5 +1,6 @@ using Amazon.JSII.Runtime.Deputy; using Amazon.JSII.Tests.CalculatorNamespace.composition; +using Amazon.JSII.Tests.CalculatorNamespace.LibNamespace; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; @@ -80,10 +81,10 @@ public virtual JObject JsonProperty set => SetInstanceProperty(value); } - [JsiiProperty("mapProperty", "{\"collection\":{\"kind\":\"map\",\"elementtype\":{\"primitive\":\"number\"}}}")] - public virtual IDictionary MapProperty + [JsiiProperty("mapProperty", "{\"collection\":{\"kind\":\"map\",\"elementtype\":{\"fqn\":\"@scope/jsii-calc-lib.Number\"}}}")] + public virtual IDictionary MapProperty { - get => GetInstanceProperty>(); + get => GetInstanceProperty>(); set => SetInstanceProperty(value); } @@ -108,14 +109,14 @@ public virtual object[] UnionArrayProperty set => SetInstanceProperty(value); } - [JsiiProperty("unionMapProperty", "{\"collection\":{\"kind\":\"map\",\"elementtype\":{\"union\":{\"types\":[{\"primitive\":\"string\"},{\"primitive\":\"number\"}]}}}}")] + [JsiiProperty("unionMapProperty", "{\"collection\":{\"kind\":\"map\",\"elementtype\":{\"union\":{\"types\":[{\"primitive\":\"string\"},{\"primitive\":\"number\"},{\"fqn\":\"@scope/jsii-calc-lib.Number\"}]}}}}")] public virtual IDictionary UnionMapProperty { get => GetInstanceProperty>(); set => SetInstanceProperty(value); } - [JsiiProperty("unionProperty", "{\"union\":{\"types\":[{\"primitive\":\"string\"},{\"primitive\":\"number\"},{\"fqn\":\"jsii-calc.Multiply\"}]}}")] + [JsiiProperty("unionProperty", "{\"union\":{\"types\":[{\"primitive\":\"string\"},{\"primitive\":\"number\"},{\"fqn\":\"jsii-calc.Multiply\"},{\"fqn\":\"@scope/jsii-calc-lib.Number\"}]}}")] public virtual object UnionProperty { get => GetInstanceProperty(); diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IIReturnsNumber.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IIReturnsNumber.cs index 4c3ab80cc1..e62565eb16 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IIReturnsNumber.cs +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IIReturnsNumber.cs @@ -1,17 +1,18 @@ using Amazon.JSII.Runtime.Deputy; +using Amazon.JSII.Tests.CalculatorNamespace.LibNamespace; namespace Amazon.JSII.Tests.CalculatorNamespace { [JsiiInterface(typeof(IIReturnsNumber), "jsii-calc.IReturnsNumber")] public interface IIReturnsNumber { - [JsiiProperty("numberProp", "{\"primitive\":\"number\"}")] - double NumberProp + [JsiiProperty("numberProp", "{\"fqn\":\"@scope/jsii-calc-lib.Number\"}")] + Number NumberProp { get; } - [JsiiMethod("obtainNumber", "{\"primitive\":\"number\"}", "[]")] - double ObtainNumber(); + [JsiiMethod("obtainNumber", "{\"fqn\":\"@scope/jsii-calc-lib.IDoublable\"}", "[]")] + IIDoublable ObtainNumber(); } } \ No newline at end of file diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IReturnsNumberProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IReturnsNumberProxy.cs index e77ef70356..bc689a1bc8 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IReturnsNumberProxy.cs +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IReturnsNumberProxy.cs @@ -1,4 +1,5 @@ using Amazon.JSII.Runtime.Deputy; +using Amazon.JSII.Tests.CalculatorNamespace.LibNamespace; namespace Amazon.JSII.Tests.CalculatorNamespace { @@ -9,16 +10,16 @@ private IReturnsNumberProxy(ByRefValue reference): base(reference) { } - [JsiiProperty("numberProp", "{\"primitive\":\"number\"}")] - public double NumberProp + [JsiiProperty("numberProp", "{\"fqn\":\"@scope/jsii-calc-lib.Number\"}")] + public Number NumberProp { - get => GetInstanceProperty(); + get => GetInstanceProperty(); } - [JsiiMethod("obtainNumber", "{\"primitive\":\"number\"}", "[]")] - public double ObtainNumber() + [JsiiMethod("obtainNumber", "{\"fqn\":\"@scope/jsii-calc-lib.IDoublable\"}", "[]")] + public IIDoublable ObtainNumber() { - return InvokeInstanceMethod(new object[]{}); + return InvokeInstanceMethod(new object[]{}); } } } \ No newline at end of file diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/AllTypes.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/AllTypes.java index b57eb209d9..c6e710a699 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/AllTypes.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/AllTypes.java @@ -79,11 +79,11 @@ public void setJsonProperty(final com.fasterxml.jackson.databind.node.ObjectNode this.jsiiSet("jsonProperty", java.util.Objects.requireNonNull(value, "jsonProperty is required")); } - public java.util.Map getMapProperty() { + public java.util.Map getMapProperty() { return this.jsiiGet("mapProperty", java.util.Map.class); } - public void setMapProperty(final java.util.Map value) { + public void setMapProperty(final java.util.Map value) { this.jsiiSet("mapProperty", java.util.Objects.requireNonNull(value, "mapProperty is required")); } @@ -135,6 +135,10 @@ public void setUnionProperty(final software.amazon.jsii.tests.calculator.Multipl this.jsiiSet("unionProperty", java.util.Objects.requireNonNull(value, "unionProperty is required")); } + public void setUnionProperty(final software.amazon.jsii.tests.calculator.lib.Number value) { + this.jsiiSet("unionProperty", java.util.Objects.requireNonNull(value, "unionProperty is required")); + } + public java.util.List getUnknownArrayProperty() { return this.jsiiGet("unknownArrayProperty", java.util.List.class); } diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/IReturnsNumber.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/IReturnsNumber.java index 352f2ef930..1b81b6f07b 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/IReturnsNumber.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/IReturnsNumber.java @@ -2,8 +2,8 @@ @javax.annotation.Generated(value = "jsii-pacmak") public interface IReturnsNumber extends software.amazon.jsii.JsiiSerializable { - java.lang.Number getNumberProp(); - java.lang.Number obtainNumber(); + software.amazon.jsii.tests.calculator.lib.Number getNumberProp(); + software.amazon.jsii.tests.calculator.lib.IDoublable obtainNumber(); /** * A proxy class which represents a concrete javascript instance of this type. @@ -14,13 +14,13 @@ final static class Jsii$Proxy extends software.amazon.jsii.JsiiObject implements } @Override - public java.lang.Number getNumberProp() { - return this.jsiiGet("numberProp", java.lang.Number.class); + public software.amazon.jsii.tests.calculator.lib.Number getNumberProp() { + return this.jsiiGet("numberProp", software.amazon.jsii.tests.calculator.lib.Number.class); } @Override - public java.lang.Number obtainNumber() { - return this.jsiiCall("obtainNumber", java.lang.Number.class); + public software.amazon.jsii.tests.calculator.lib.IDoublable obtainNumber() { + return this.jsiiCall("obtainNumber", software.amazon.jsii.tests.calculator.lib.IDoublable.class); } } } diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/sphinx/jsii-calc.rst b/packages/jsii-pacmak/test/expected.jsii-calc/sphinx/jsii-calc.rst index cbc903a8c6..f7aa575961 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/sphinx/jsii-calc.rst +++ b/packages/jsii-pacmak/test/expected.jsii-calc/sphinx/jsii-calc.rst @@ -434,7 +434,7 @@ AllTypes .. py:attribute:: mapProperty - :type: string => number + :type: string => :py:class:`@scope/jsii-calc-lib.Number`\ .. py:attribute:: numberProperty @@ -454,12 +454,12 @@ AllTypes .. py:attribute:: unionMapProperty - :type: string => (string or number) + :type: string => (string or number or :py:class:`@scope/jsii-calc-lib.Number`\ ) .. py:attribute:: unionProperty - :type: string or number or :py:class:`~jsii-calc.Multiply`\ + :type: string or number or :py:class:`~jsii-calc.Multiply`\ or :py:class:`@scope/jsii-calc-lib.Number`\ .. py:attribute:: unknownArrayProperty @@ -1761,12 +1761,12 @@ IReturnsNumber (interface) .. py:attribute:: numberProp - :type: number *(readonly)* *(abstract)* + :type: :py:class:`@scope/jsii-calc-lib.Number`\ *(readonly)* *(abstract)* - .. py:method:: obtainNumber() -> number + .. py:method:: obtainNumber() -> @scope/jsii-calc-lib.IDoublable - :rtype: number + :rtype: :py:class:`@scope/jsii-calc-lib.IDoublable`\ :abstract: Yes diff --git a/packages/jsii/lib/assembler.ts b/packages/jsii/lib/assembler.ts index d46dc342ac..4d2ae4ea06 100644 --- a/packages/jsii/lib/assembler.ts +++ b/packages/jsii/lib/assembler.ts @@ -11,7 +11,6 @@ import literate = require('./literate'); import { ProjectInfo } from './project-info'; import utils = require('./utils'); import { Validator } from './validator'; -import { NamedTypeReference, isInterfaceType } from 'jsii-spec'; // tslint:disable:no-var-requires Modules without TypeScript definitions const sortJson = require('sort-json'); @@ -30,9 +29,11 @@ export class Assembler implements Emitter { /** * @param projectInfo information about the package being assembled * @param program the TypeScript program to be assembled from + * @param stdlib the directory where the TypeScript stdlib is rooted */ public constructor(public readonly projectInfo: ProjectInfo, - public readonly program: ts.Program) {} + public readonly program: ts.Program, + public readonly stdlib: string) {} private get _typeChecker(): ts.TypeChecker { return this.program.getTypeChecker(); @@ -152,7 +153,7 @@ export class Assembler implements Emitter { * that case anyway. */ // tslint:disable-next-line:max-line-length - private _deferUntilTypesAvailable(fqn: string, baseTypes: NamedTypeReference[], referencingNode: ts.Node, cb: (...xs: spec.Type[]) => void) { + private _deferUntilTypesAvailable(fqn: string, baseTypes: spec.NamedTypeReference[], referencingNode: ts.Node, cb: (...xs: spec.Type[]) => void) { // We can do this one eagerly if (baseTypes.length === 0) { cb(); @@ -581,7 +582,7 @@ export class Assembler implements Emitter { jsiiType.datatype = true; } for (const base of bases) { - if (isInterfaceType(base) && !base.datatype) { + if (spec.isInterfaceType(base) && !base.datatype) { jsiiType.datatype = undefined; } } @@ -731,7 +732,7 @@ export class Assembler implements Emitter { type = this._typeChecker.getApparentType(type); } - const primitiveType = _tryMakePrimitiveType(); + const primitiveType = _tryMakePrimitiveType.call(this); if (primitiveType) { return primitiveType; } if (type.isUnion() && !_isEnumLike(type)) { @@ -809,7 +810,7 @@ export class Assembler implements Emitter { }; } - function _tryMakePrimitiveType(): spec.PrimitiveTypeReference | undefined { + function _tryMakePrimitiveType(this: Assembler): spec.PrimitiveTypeReference | undefined { if (!type.symbol) { // tslint:disable-next-line:no-bitwise if (type.flags & ts.TypeFlags.Object) { @@ -819,7 +820,7 @@ export class Assembler implements Emitter { if (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { return { primitive: spec.PrimitiveType.Any, optional: true }; } - } else { + } else if (type.symbol.valueDeclaration && isUnder(type.symbol.valueDeclaration.getSourceFile().fileName, this.stdlib)) { switch (type.symbol.name) { case 'Boolean': return { primitive: spec.PrimitiveType.Boolean }; @@ -833,6 +834,11 @@ export class Assembler implements Emitter { } // Not a primitive type! return undefined; + + function isUnder(file: string, dir: string): boolean { + const relative = path.relative(dir, file); + return !relative.startsWith(path.sep) && !relative.startsWith('..'); + } } async function _unionType(this: Assembler): Promise { diff --git a/packages/jsii/lib/compiler.ts b/packages/jsii/lib/compiler.ts index 7fc7528745..1c8e4b780c 100644 --- a/packages/jsii/lib/compiler.ts +++ b/packages/jsii/lib/compiler.ts @@ -67,13 +67,16 @@ export class Compiler implements Emitter { private async _buildOnce(files: string[]): Promise { await this._writeTypeScriptConfig(); const host = ts.createCompilerHost(COMPILER_OPTIONS); + if (!host.getDefaultLibLocation) { + throw new Error('No default library location was found on the TypeScript compiler host!'); + } host.getCurrentDirectory = () => this.options.projectInfo.projectRoot; const prog = ts.createProgram( files.concat(_pathOfLibraries(host)), COMPILER_OPTIONS, host ); - return await this._consumeProgram(prog); + return await this._consumeProgram(prog, host.getDefaultLibLocation()); } private async _startWatch(): Promise { @@ -84,9 +87,12 @@ export class Compiler implements Emitter { { ...COMPILER_OPTIONS, noEmitOnError: false }, { ...ts.sys, getCurrentDirectory() { return projectRoot; } } ); + if (!host.getDefaultLibLocation) { + throw new Error('No default library location was found on the TypeScript compiler host!'); + } const orig = host.afterProgramCreate; host.afterProgramCreate = async builderProgram => { - await this._consumeProgram(builderProgram.getProgram()); + await this._consumeProgram(builderProgram.getProgram(), host.getDefaultLibLocation!()); if (orig) { orig.call(host, builderProgram); } }; ts.createWatchProgram(host); @@ -94,13 +100,13 @@ export class Compiler implements Emitter { }); } - private async _consumeProgram(program: ts.Program): Promise { + private async _consumeProgram(program: ts.Program, stdlib: string): Promise { const emit = program.emit(); if (emit.emitSkipped) { LOG.error('Compilation errors prevented the JSII assembly from being created'); return emit; } - const assembler = new Assembler(this.options.projectInfo, program); + const assembler = new Assembler(this.options.projectInfo, program, stdlib); const assmEmit = await assembler.emit(); if (assmEmit.emitSkipped) { LOG.error('Type model errors prevented the JSII assembly from being created'); From c127be4dbb2de4c363ad4c8ef1a754737cce2956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Tue, 6 Nov 2018 09:18:38 +0100 Subject: [PATCH 2/3] Use a concrete CallbackResult type --- .../Amazon.JSII.Runtime/CallbackExtensions.cs | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/CallbackExtensions.cs b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/CallbackExtensions.cs index 28b93c68b1..2b55f587f9 100644 --- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/CallbackExtensions.cs +++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/CallbackExtensions.cs @@ -15,13 +15,12 @@ public static object InvokeCallback(this Callback callback, IReferenceMap refere { try { - TypeReference returnType; - object frameworkResult = callback.InvokeCallbackCore(referenceMap, out returnType); + CallbackResult frameworkResult = callback.InvokeCallbackCore(referenceMap); converter.TryConvert( - returnType ?? new TypeReference(primitive: PrimitiveType.Any), + frameworkResult.Type, referenceMap, - frameworkResult, + frameworkResult.Value, out object result ); @@ -42,29 +41,28 @@ out object result } } - static object InvokeCallbackCore(this Callback callback, IReferenceMap referenceMap, out TypeReference returnType) + static CallbackResult InvokeCallbackCore(this Callback callback, IReferenceMap referenceMap) { if (callback.Invoke != null) { - return InvokeMethod(callback.Invoke, referenceMap, out returnType); + return InvokeMethod(callback.Invoke, referenceMap); } if (callback.Get != null) { - return InvokeGetter(callback.Get, referenceMap, out returnType); + return InvokeGetter(callback.Get, referenceMap); } if (callback.Set != null) { InvokeSetter(callback.Set, referenceMap); - returnType = null; return null; } throw new ArgumentException("Callback does not specificy a method, getter, or setter to invoke"); } - static object InvokeMethod(InvokeRequest request, IReferenceMap referenceMap, out TypeReference returnType) + static CallbackResult InvokeMethod(InvokeRequest request, IReferenceMap referenceMap) { request = request ?? throw new ArgumentNullException(nameof(request)); DeputyBase deputy = referenceMap.GetOrCreateNativeReference(request.ObjectReference); @@ -77,12 +75,10 @@ static object InvokeMethod(InvokeRequest request, IReferenceMap referenceMap, ou } JsiiMethodAttribute attribute = methodInfo.GetCustomAttribute(); - returnType = attribute?.Returns; - - return methodInfo.Invoke(deputy, request.Arguments); + return new CallbackResult(attribute?.Returns, methodInfo.Invoke(deputy, request.Arguments)); } - static object InvokeGetter(GetRequest request, IReferenceMap referenceMap, out TypeReference returnType) + static CallbackResult InvokeGetter(GetRequest request, IReferenceMap referenceMap) { request = request ?? throw new ArgumentNullException(nameof(request)); DeputyBase deputy = referenceMap.GetOrCreateNativeReference(request.ObjectReference); @@ -94,7 +90,6 @@ static object InvokeGetter(GetRequest request, IReferenceMap referenceMap, out T } JsiiPropertyAttribute attribute = propertyInfo.GetCustomAttribute(); - returnType = attribute?.Type; MethodInfo methodInfo = propertyInfo.GetGetMethod(); if (methodInfo == null) @@ -102,7 +97,7 @@ static object InvokeGetter(GetRequest request, IReferenceMap referenceMap, out T throw new InvalidOperationException($"Received callback for {deputy.GetType().Name}.{request.Property} getter, but this property does not have a getter"); } - return methodInfo.Invoke(deputy, new object[] { }); + return new CallbackResult(attribute?.Type, methodInfo.Invoke(deputy, new object[] { })); } static void InvokeSetter(SetRequest request, IReferenceMap referenceMap) @@ -125,4 +120,16 @@ static void InvokeSetter(SetRequest request, IReferenceMap referenceMap) methodInfo.Invoke(deputy, new object[] { request.Value }); } } + + internal class CallbackResult + { + public CallbackResult(TypeReference type, object value) + { + Type = type ?? new TypeReference(primitive: PrimitiveType.Any); + Value = value; + } + + public TypeReference Type { get; } + public object Value { get; } + } } From 483309b3f1a71272c7d5b392d90a23fe05a9977f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Tue, 6 Nov 2018 09:55:49 +0100 Subject: [PATCH 3/3] Fix broken tests --- .../src/Amazon.JSII.Runtime/CallbackExtensions.cs | 6 +++--- .../java/software/amazon/jsii/testing/ComplianceTest.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/CallbackExtensions.cs b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/CallbackExtensions.cs index 2b55f587f9..8fe9067aae 100644 --- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/CallbackExtensions.cs +++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/CallbackExtensions.cs @@ -18,9 +18,9 @@ public static object InvokeCallback(this Callback callback, IReferenceMap refere CallbackResult frameworkResult = callback.InvokeCallbackCore(referenceMap); converter.TryConvert( - frameworkResult.Type, + frameworkResult?.Type ?? new TypeReference(primitive: PrimitiveType.Any), referenceMap, - frameworkResult.Value, + frameworkResult?.Value, out object result ); @@ -125,7 +125,7 @@ internal class CallbackResult { public CallbackResult(TypeReference type, object value) { - Type = type ?? new TypeReference(primitive: PrimitiveType.Any); + Type = type; Value = value; } diff --git a/packages/jsii-java-runtime-test/project/src/test/java/software/amazon/jsii/testing/ComplianceTest.java b/packages/jsii-java-runtime-test/project/src/test/java/software/amazon/jsii/testing/ComplianceTest.java index 43aef436d1..f2c437819b 100644 --- a/packages/jsii-java-runtime-test/project/src/test/java/software/amazon/jsii/testing/ComplianceTest.java +++ b/packages/jsii-java-runtime-test/project/src/test/java/software/amazon/jsii/testing/ComplianceTest.java @@ -109,8 +109,8 @@ public void collectionTypes() { assertEquals("World", types.getArrayProperty().get(1)); // map - Map map = new HashMap<>(); - map.put("Foo", 123); + Map map = new HashMap<>(); + map.put("Foo", new Number(123)); types.setMapProperty(map); }