diff --git a/packages/jsii-pacmak/lib/targets/python.ts b/packages/jsii-pacmak/lib/targets/python.ts index 193bfa7879..4ec6c0c278 100644 --- a/packages/jsii-pacmak/lib/targets/python.ts +++ b/packages/jsii-pacmak/lib/targets/python.ts @@ -513,8 +513,8 @@ abstract class BaseMethod implements PythonBase { // resolved, so build up a list of all of the prop names so we can check against // them later. const liftedPropNames = new Set(); - if (this.liftedProp?.properties?.length ?? 0 >= 1) { - for (const prop of this.liftedProp!.properties!) { + if (this.liftedProp?.properties != null) { + for (const prop of this.liftedProp.properties) { liftedPropNames.add(toPythonParameterName(prop.name)); } } @@ -751,24 +751,36 @@ abstract class BaseMethod implements PythonBase { const liftedProperties: spec.Property[] = []; const stack = [this.liftedProp]; - let current = stack.shift(); - while (current !== undefined) { + const knownIfaces = new Set(); + const knownProps = new Set(); + for ( + let current = stack.shift(); + current != null; + current = stack.shift() + ) { + knownIfaces.add(current.fqn); + // Add any interfaces that this interface depends on, to the list. if (current.interfaces !== undefined) { - stack.push( - ...current.interfaces.map( - (ifc) => resolver.dereference(ifc) as spec.InterfaceType, - ), - ); + for (const iface of current.interfaces) { + if (knownIfaces.has(iface)) { + continue; + } + stack.push(resolver.dereference(iface) as spec.InterfaceType); + knownIfaces.add(iface); + } } // Add all of the properties of this interface to our list of properties. if (current.properties !== undefined) { - liftedProperties.push(...current.properties); + for (const prop of current.properties) { + if (knownProps.has(prop.name)) { + continue; + } + liftedProperties.push(prop); + knownProps.add(prop.name); + } } - - // Finally, grab our next item. - current = stack.shift(); } return liftedProperties; diff --git a/packages/jsii-pacmak/test/generated-code/__snapshots__/examples.test.ts.snap b/packages/jsii-pacmak/test/generated-code/__snapshots__/examples.test.ts.snap index 0ef0d7f1a7..c4cf02498a 100644 --- a/packages/jsii-pacmak/test/generated-code/__snapshots__/examples.test.ts.snap +++ b/packages/jsii-pacmak/test/generated-code/__snapshots__/examples.test.ts.snap @@ -1,5 +1,1426 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`diamond-struct-parameter.ts: / 1`] = ` + + ┣━ 📁 dotnet + ┃ ┗━ 📁 Example.Test.Demo + ┃ ┣━ 📄 AssemblyInfo.cs + ┃ ┣━ 📁 Example + ┃ ┃ ┗━ 📁 Test + ┃ ┃ ┗━ 📁 Demo + ┃ ┃ ┣━ 📄 Baz_.cs + ┃ ┃ ┣━ 📄 Consumer.cs + ┃ ┃ ┣━ 📄 Foo_.cs + ┃ ┃ ┣━ 📄 FooBar.cs + ┃ ┃ ┣━ 📄 IBaz.cs + ┃ ┃ ┣━ 📄 IFoo.cs + ┃ ┃ ┣━ 📄 IFooBar.cs + ┃ ┃ ┗━ 📁 Internal + ┃ ┃ ┗━ 📁 DependencyResolution + ┃ ┃ ┗━ 📄 Anchor.cs + ┃ ┗━ 📄 Example.Test.Demo.csproj + ┣━ 📁 go + ┃ ┗━ 📁 testpkg + ┃ ┣━ 📄 go.mod + ┃ ┣━ 📁 jsii + ┃ ┃ ┗━ 📄 jsii.go + ┃ ┣━ 📄 testpkg.go + ┃ ┗━ 📄 testpkg.init.go + ┣━ 📁 java + ┃ ┣━ 📄 pom.xml + ┃ ┗━ 📁 src + ┃ ┗━ 📁 main + ┃ ┣━ 📁 java + ┃ ┃ ┗━ 📁 example + ┃ ┃ ┗━ 📁 test + ┃ ┃ ┗━ 📁 demo + ┃ ┃ ┣━ 📄 $Module.java + ┃ ┃ ┣━ 📄 Baz.java + ┃ ┃ ┣━ 📄 Consumer.java + ┃ ┃ ┣━ 📄 Foo.java + ┃ ┃ ┗━ 📄 FooBar.java + ┃ ┗━ 📁 resources + ┃ ┗━ 📁 example + ┃ ┗━ 📁 test + ┃ ┗━ 📁 demo + ┃ ┗━ 📄 $Module.txt + ┗━ 📁 python + ┣━ 📄 pyproject.toml + ┣━ 📄 setup.py + ┗━ 📁 src + ┗━ 📁 example_test_demo + ┣━ 📄 __init__.py + ┣━ 📁 _jsii + ┃ ┗━ 📄 __init__.py + ┗━ 📄 py.typed +`; + +exports[`diamond-struct-parameter.ts: /dotnet/Example.Test.Demo/AssemblyInfo.cs 1`] = ` +using Amazon.JSII.Runtime.Deputy; + +[assembly: JsiiAssembly("testpkg", "0.0.1", "testpkg-0.0.1.tgz")] + +`; + +exports[`diamond-struct-parameter.ts: /dotnet/Example.Test.Demo/Example.Test.Demo.csproj 1`] = ` + + + + testpkg + Example.Test.Demo + Apache-2.0 + 0.0.1 + + John Doe + en-US + https://github.com/aws/jsii.git + https://github.com/aws/jsii.git + git + + true + true + true + true + enable + snupkg + netcoreapp3.1 + + + + + + + + + + 0612,0618 + + 0108,0109 + + + + +`; + +exports[`diamond-struct-parameter.ts: /dotnet/Example.Test.Demo/Example/Test/Demo/Baz_.cs 1`] = ` +using Amazon.JSII.Runtime.Deputy; + +#pragma warning disable CS0672,CS0809,CS1591 + +namespace Example.Test.Demo +{ + #pragma warning disable CS8618 + + [JsiiByValue(fqn: "testpkg.Baz")] + public class Baz_ : Example.Test.Demo.IBaz + { + [JsiiProperty(name: "baz", typeJson: "{\\"primitive\\":\\"boolean\\"}", isOverride: true)] + public bool Baz + { + get; + set; + } + + [JsiiProperty(name: "foo", typeJson: "{\\"primitive\\":\\"number\\"}", isOverride: true)] + public double Foo + { + get; + set; + } + + [JsiiOptional] + [JsiiProperty(name: "bar", typeJson: "{\\"primitive\\":\\"string\\"}", isOptional: true, isOverride: true)] + public string? Bar + { + get; + set; + } + } +} + +`; + +exports[`diamond-struct-parameter.ts: /dotnet/Example.Test.Demo/Example/Test/Demo/Consumer.cs 1`] = ` +using Amazon.JSII.Runtime.Deputy; + +#pragma warning disable CS0672,CS0809,CS1591 + +namespace Example.Test.Demo +{ + [JsiiClass(nativeType: typeof(Example.Test.Demo.Consumer), fullyQualifiedName: "testpkg.Consumer")] + public class Consumer : DeputyBase + { + /// Used by jsii to construct an instance of this class from a Javascript-owned object reference + /// The Javascript-owned object reference + [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] + protected Consumer(ByRefValue reference): base(reference) + { + } + + /// Used by jsii to construct an instance of this class from DeputyProps + /// The deputy props + [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] + protected Consumer(DeputyProps props): base(props) + { + } + + [JsiiMethod(name: "consumeBaz", parametersJson: "[{\\"name\\":\\"baz\\",\\"type\\":{\\"fqn\\":\\"testpkg.Baz\\"}}]")] + public static void ConsumeBaz(Example.Test.Demo.IBaz baz) + { + InvokeStaticVoidMethod(typeof(Example.Test.Demo.Consumer), new System.Type[]{typeof(Example.Test.Demo.IBaz)}, new object[]{baz}); + } + } +} + +`; + +exports[`diamond-struct-parameter.ts: /dotnet/Example.Test.Demo/Example/Test/Demo/Foo_.cs 1`] = ` +using Amazon.JSII.Runtime.Deputy; + +#pragma warning disable CS0672,CS0809,CS1591 + +namespace Example.Test.Demo +{ + #pragma warning disable CS8618 + + [JsiiByValue(fqn: "testpkg.Foo")] + public class Foo_ : Example.Test.Demo.IFoo + { + [JsiiProperty(name: "foo", typeJson: "{\\"primitive\\":\\"number\\"}", isOverride: true)] + public double Foo + { + get; + set; + } + } +} + +`; + +exports[`diamond-struct-parameter.ts: /dotnet/Example.Test.Demo/Example/Test/Demo/FooBar.cs 1`] = ` +using Amazon.JSII.Runtime.Deputy; + +#pragma warning disable CS0672,CS0809,CS1591 + +namespace Example.Test.Demo +{ + #pragma warning disable CS8618 + + [JsiiByValue(fqn: "testpkg.FooBar")] + public class FooBar : Example.Test.Demo.IFooBar + { + [JsiiProperty(name: "foo", typeJson: "{\\"primitive\\":\\"number\\"}", isOverride: true)] + public double Foo + { + get; + set; + } + + [JsiiOptional] + [JsiiProperty(name: "bar", typeJson: "{\\"primitive\\":\\"string\\"}", isOptional: true, isOverride: true)] + public string? Bar + { + get; + set; + } + } +} + +`; + +exports[`diamond-struct-parameter.ts: /dotnet/Example.Test.Demo/Example/Test/Demo/IBaz.cs 1`] = ` +using Amazon.JSII.Runtime.Deputy; + +#pragma warning disable CS0672,CS0809,CS1591 + +namespace Example.Test.Demo +{ + [JsiiInterface(nativeType: typeof(IBaz), fullyQualifiedName: "testpkg.Baz")] + public interface IBaz : Example.Test.Demo.IFoo, Example.Test.Demo.IFooBar + { + [JsiiProperty(name: "baz", typeJson: "{\\"primitive\\":\\"boolean\\"}")] + bool Baz + { + get; + } + + [JsiiTypeProxy(nativeType: typeof(IBaz), fullyQualifiedName: "testpkg.Baz")] + new internal sealed class _Proxy : DeputyBase, Example.Test.Demo.IBaz + { + private _Proxy(ByRefValue reference): base(reference) + { + } + + [JsiiProperty(name: "baz", typeJson: "{\\"primitive\\":\\"boolean\\"}")] + public bool Baz + { + get => GetInstanceProperty()!; + } + + [JsiiProperty(name: "foo", typeJson: "{\\"primitive\\":\\"number\\"}")] + public double Foo + { + get => GetInstanceProperty()!; + } + + [JsiiOptional] + [JsiiProperty(name: "bar", typeJson: "{\\"primitive\\":\\"string\\"}", isOptional: true)] + public string? Bar + { + get => GetInstanceProperty(); + } + } + } +} + +`; + +exports[`diamond-struct-parameter.ts: /dotnet/Example.Test.Demo/Example/Test/Demo/IFoo.cs 1`] = ` +using Amazon.JSII.Runtime.Deputy; + +#pragma warning disable CS0672,CS0809,CS1591 + +namespace Example.Test.Demo +{ + [JsiiInterface(nativeType: typeof(IFoo), fullyQualifiedName: "testpkg.Foo")] + public interface IFoo + { + [JsiiProperty(name: "foo", typeJson: "{\\"primitive\\":\\"number\\"}")] + double Foo + { + get; + } + + [JsiiTypeProxy(nativeType: typeof(IFoo), fullyQualifiedName: "testpkg.Foo")] + internal sealed class _Proxy : DeputyBase, Example.Test.Demo.IFoo + { + private _Proxy(ByRefValue reference): base(reference) + { + } + + [JsiiProperty(name: "foo", typeJson: "{\\"primitive\\":\\"number\\"}")] + public double Foo + { + get => GetInstanceProperty()!; + } + } + } +} + +`; + +exports[`diamond-struct-parameter.ts: /dotnet/Example.Test.Demo/Example/Test/Demo/IFooBar.cs 1`] = ` +using Amazon.JSII.Runtime.Deputy; + +#pragma warning disable CS0672,CS0809,CS1591 + +namespace Example.Test.Demo +{ + [JsiiInterface(nativeType: typeof(IFooBar), fullyQualifiedName: "testpkg.FooBar")] + public interface IFooBar + { + [JsiiProperty(name: "foo", typeJson: "{\\"primitive\\":\\"number\\"}")] + double Foo + { + get; + } + + [JsiiProperty(name: "bar", typeJson: "{\\"primitive\\":\\"string\\"}", isOptional: true)] + [Amazon.JSII.Runtime.Deputy.JsiiOptional] + string? Bar + { + get + { + return null; + } + } + + [JsiiTypeProxy(nativeType: typeof(IFooBar), fullyQualifiedName: "testpkg.FooBar")] + internal sealed class _Proxy : DeputyBase, Example.Test.Demo.IFooBar + { + private _Proxy(ByRefValue reference): base(reference) + { + } + + [JsiiProperty(name: "foo", typeJson: "{\\"primitive\\":\\"number\\"}")] + public double Foo + { + get => GetInstanceProperty()!; + } + + [JsiiOptional] + [JsiiProperty(name: "bar", typeJson: "{\\"primitive\\":\\"string\\"}", isOptional: true)] + public string? Bar + { + get => GetInstanceProperty(); + } + } + } +} + +`; + +exports[`diamond-struct-parameter.ts: /dotnet/Example.Test.Demo/Example/Test/Demo/Internal/DependencyResolution/Anchor.cs 1`] = ` +#pragma warning disable CS0672,CS0809,CS1591 + +namespace Example.Test.Demo.Internal.DependencyResolution +{ + public sealed class Anchor + { + public Anchor() + { + } + } +} + +`; + +exports[`diamond-struct-parameter.ts: /go/testpkg/go.mod 1`] = ` +module example.test/demo/testpkg + +go 1.16 + +require ( + github.com/aws/jsii-runtime-go v0.0.0 +) + +`; + +exports[`diamond-struct-parameter.ts: /go/testpkg/jsii/jsii.go 1`] = ` +// Package jsii contains the functionaility needed for jsii packages to +// initialize their dependencies and themselves. Users should never need to use this package +// directly. If you find you need to - please report a bug at +// https://github.com/aws/jsii/issues/new/choose +package jsii + +import ( + _ "embed" + + _jsii_ "github.com/aws/jsii-runtime-go" +) + +//go:embed testpkg-0.0.1.tgz +var tarball []byte + +// Initialize loads the necessary packages in the @jsii/kernel to support the enclosing module. +// The implementation is idempotent (and hence safe to be called over and over). +func Initialize() { + // Load this library into the kernel + _jsii_.Load("testpkg", "0.0.1", tarball) +} + +`; + +exports[`diamond-struct-parameter.ts: /go/testpkg/testpkg.go 1`] = ` +// testpkg +package testpkg + +import ( + _init_ "example.test/demo/testpkg/jsii" + _jsii_ "github.com/aws/jsii-runtime-go" +) + +type Baz struct { + Foo float64 \`json:"foo"\` + Bar string \`json:"bar"\` + Baz bool \`json:"baz"\` +} + +type Consumer interface { +} + +// The jsii proxy struct for Consumer +type jsiiProxy_Consumer struct { + _ byte // padding +} + +func Consumer_ConsumeBaz(baz Baz) { + _init_.Initialize() + + _jsii_.StaticInvokeVoid( + "testpkg.Consumer", + "consumeBaz", + []interface{}{baz}, + ) +} + +type Foo struct { + Foo float64 \`json:"foo"\` +} + +type FooBar struct { + Foo float64 \`json:"foo"\` + Bar string \`json:"bar"\` +} + + +`; + +exports[`diamond-struct-parameter.ts: /go/testpkg/testpkg.init.go 1`] = ` +package testpkg + +import ( + "reflect" + + _jsii_ "github.com/aws/jsii-runtime-go" +) + +func init() { + _jsii_.RegisterStruct( + "testpkg.Baz", + reflect.TypeOf((*Baz)(nil)).Elem(), + ) + _jsii_.RegisterClass( + "testpkg.Consumer", + reflect.TypeOf((*Consumer)(nil)).Elem(), + nil, // no members + func() interface{} { + return &jsiiProxy_Consumer{} + }, + ) + _jsii_.RegisterStruct( + "testpkg.Foo", + reflect.TypeOf((*Foo)(nil)).Elem(), + ) + _jsii_.RegisterStruct( + "testpkg.FooBar", + reflect.TypeOf((*FooBar)(nil)).Elem(), + ) +} + +`; + +exports[`diamond-struct-parameter.ts: /java/pom.xml 1`] = ` + + + 4.0.0 + \${project.groupId}:\${project.artifactId} + testpkg + https://github.com/aws/jsii.git + + + Apache License 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + repo + An OSI-approved license + + + + + John Doe + + author + + + + + scm:git:https://github.com/aws/jsii.git + https://github.com/aws/jsii.git + + example.test + demo + 0.0.1 + jar + + UTF-8 + + + + software.amazon.jsii + jsii-runtime + (,0.0.1) + + + org.jetbrains + annotations + [16.0.3,20.0.0) + + + + javax.annotation + javax.annotation-api + [1.3.2,1.4.0) + compile + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + true + + true + true + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + + attach-javadocs + + jar + + + + + false + protected + + **/$Module.java + + -J-XX:+TieredCompilation + -J-XX:TieredStopAtLevel=1 + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M3 + + + enforce-maven + + enforce + + + + + 3.6 + + + + + + + + org.codehaus.mojo + versions-maven-plugin + 2.8.1 + + false + + + + + + +`; + +exports[`diamond-struct-parameter.ts: /java/src/main/java/example/test/demo/$Module.java 1`] = ` +package example.test.demo; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.io.Reader; +import java.io.UncheckedIOException; + +import java.nio.charset.StandardCharsets; + +import java.util.HashMap; +import java.util.Map; + +import software.amazon.jsii.JsiiModule; + +@software.amazon.jsii.Internal +public final class $Module extends JsiiModule { + private static final Map MODULE_TYPES = load(); + + private static Map load() { + final Map result = new HashMap<>(); + final ClassLoader cl = $Module.class.getClassLoader(); + try (final InputStream is = cl.getResourceAsStream("example/test/demo/$Module.txt"); + final Reader rd = new InputStreamReader(is, StandardCharsets.UTF_8); + final BufferedReader br = new BufferedReader(rd)) { + br.lines() + .filter(line -> !line.trim().isEmpty()) + .forEach(line -> { + final String[] parts = line.split("=", 2); + final String fqn = parts[0]; + final String className = parts[1]; + result.put(fqn, className); + }); + } + catch (final IOException exception) { + throw new UncheckedIOException(exception); + } + return result; + } + + private final Map> cache = new HashMap<>(); + + public $Module() { + super("testpkg", "0.0.1", $Module.class, "testpkg@0.0.1.jsii.tgz"); + } + + @Override + protected Class resolveClass(final String fqn) throws ClassNotFoundException { + if (!MODULE_TYPES.containsKey(fqn)) { + throw new ClassNotFoundException("Unknown JSII type: " + fqn); + } + String className = MODULE_TYPES.get(fqn); + if (!this.cache.containsKey(className)) { + this.cache.put(className, this.findClass(className)); + } + return this.cache.get(className); + } + + private Class findClass(final String binaryName) { + try { + return Class.forName(binaryName); + } + catch (final ClassNotFoundException exception) { + throw new RuntimeException(exception); + } + } +} + +`; + +exports[`diamond-struct-parameter.ts: /java/src/main/java/example/test/demo/Baz.java 1`] = ` +package example.test.demo; + +@javax.annotation.Generated(value = "jsii-pacmak") +@software.amazon.jsii.Jsii(module = example.test.demo.$Module.class, fqn = "testpkg.Baz") +@software.amazon.jsii.Jsii.Proxy(Baz.Jsii$Proxy.class) +public interface Baz extends software.amazon.jsii.JsiiSerializable, example.test.demo.Foo, example.test.demo.FooBar { + + @org.jetbrains.annotations.NotNull java.lang.Boolean getBaz(); + + @org.jetbrains.annotations.NotNull java.lang.Number getFoo(); + + /** + * @return a {@link Builder} of {@link Baz} + */ + static Builder builder() { + return new Builder(); + } + /** + * A builder for {@link Baz} + */ + public static final class Builder implements software.amazon.jsii.Builder { + private java.lang.Boolean baz; + private java.lang.Number foo; + private java.lang.String bar; + + /** + * Sets the value of {@link Baz#getBaz} + * @param baz the value to be set. This parameter is required. + * @return {@code this} + */ + public Builder baz(java.lang.Boolean baz) { + this.baz = baz; + return this; + } + + /** + * Sets the value of {@link Baz#getFoo} + * @param foo the value to be set. This parameter is required. + * @return {@code this} + */ + public Builder foo(java.lang.Number foo) { + this.foo = foo; + return this; + } + + /** + * Sets the value of {@link Baz#getBar} + * @param bar the value to be set. + * @return {@code this} + */ + public Builder bar(java.lang.String bar) { + this.bar = bar; + return this; + } + + /** + * Builds the configured instance. + * @return a new instance of {@link Baz} + * @throws NullPointerException if any required attribute was not provided + */ + @Override + public Baz build() { + return new Jsii$Proxy(baz, foo, bar); + } + } + + /** + * An implementation for {@link Baz} + */ + @software.amazon.jsii.Internal + final class Jsii$Proxy extends software.amazon.jsii.JsiiObject implements Baz { + private final java.lang.Boolean baz; + private final java.lang.Number foo; + private final java.lang.String bar; + + /** + * Constructor that initializes the object based on values retrieved from the JsiiObject. + * @param objRef Reference to the JSII managed object. + */ + protected Jsii$Proxy(final software.amazon.jsii.JsiiObjectRef objRef) { + super(objRef); + this.baz = software.amazon.jsii.Kernel.get(this, "baz", software.amazon.jsii.NativeType.forClass(java.lang.Boolean.class)); + this.foo = software.amazon.jsii.Kernel.get(this, "foo", software.amazon.jsii.NativeType.forClass(java.lang.Number.class)); + this.bar = software.amazon.jsii.Kernel.get(this, "bar", software.amazon.jsii.NativeType.forClass(java.lang.String.class)); + } + + /** + * Constructor that initializes the object based on literal property values passed by the {@link Builder}. + */ + protected Jsii$Proxy(final java.lang.Boolean baz, final java.lang.Number foo, final java.lang.String bar) { + super(software.amazon.jsii.JsiiObject.InitializationMode.JSII); + this.baz = java.util.Objects.requireNonNull(baz, "baz is required"); + this.foo = java.util.Objects.requireNonNull(foo, "foo is required"); + this.bar = bar; + } + + @Override + public final java.lang.Boolean getBaz() { + return this.baz; + } + + @Override + public final java.lang.Number getFoo() { + return this.foo; + } + + @Override + public final java.lang.String getBar() { + return this.bar; + } + + @Override + @software.amazon.jsii.Internal + public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { + final com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; + final com.fasterxml.jackson.databind.node.ObjectNode data = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); + + data.set("baz", om.valueToTree(this.getBaz())); + data.set("foo", om.valueToTree(this.getFoo())); + if (this.getBar() != null) { + data.set("bar", om.valueToTree(this.getBar())); + } + + final com.fasterxml.jackson.databind.node.ObjectNode struct = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); + struct.set("fqn", om.valueToTree("testpkg.Baz")); + struct.set("data", data); + + final com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); + obj.set("$jsii.struct", struct); + + return obj; + } + + @Override + public final boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Baz.Jsii$Proxy that = (Baz.Jsii$Proxy) o; + + if (!baz.equals(that.baz)) return false; + if (!foo.equals(that.foo)) return false; + return this.bar != null ? this.bar.equals(that.bar) : that.bar == null; + } + + @Override + public final int hashCode() { + int result = this.baz.hashCode(); + result = 31 * result + (this.foo.hashCode()); + result = 31 * result + (this.bar != null ? this.bar.hashCode() : 0); + return result; + } + } +} + +`; + +exports[`diamond-struct-parameter.ts: /java/src/main/java/example/test/demo/Consumer.java 1`] = ` +package example.test.demo; + +@javax.annotation.Generated(value = "jsii-pacmak") +@software.amazon.jsii.Jsii(module = example.test.demo.$Module.class, fqn = "testpkg.Consumer") +public class Consumer extends software.amazon.jsii.JsiiObject { + + protected Consumer(final software.amazon.jsii.JsiiObjectRef objRef) { + super(objRef); + } + + protected Consumer(final software.amazon.jsii.JsiiObject.InitializationMode initializationMode) { + super(initializationMode); + } + + public static void consumeBaz(final @org.jetbrains.annotations.NotNull example.test.demo.Baz baz) { + software.amazon.jsii.JsiiObject.jsiiStaticCall(example.test.demo.Consumer.class, "consumeBaz", software.amazon.jsii.NativeType.VOID, new Object[] { java.util.Objects.requireNonNull(baz, "baz is required") }); + } +} + +`; + +exports[`diamond-struct-parameter.ts: /java/src/main/java/example/test/demo/Foo.java 1`] = ` +package example.test.demo; + +@javax.annotation.Generated(value = "jsii-pacmak") +@software.amazon.jsii.Jsii(module = example.test.demo.$Module.class, fqn = "testpkg.Foo") +@software.amazon.jsii.Jsii.Proxy(Foo.Jsii$Proxy.class) +public interface Foo extends software.amazon.jsii.JsiiSerializable { + + @org.jetbrains.annotations.NotNull java.lang.Number getFoo(); + + /** + * @return a {@link Builder} of {@link Foo} + */ + static Builder builder() { + return new Builder(); + } + /** + * A builder for {@link Foo} + */ + public static final class Builder implements software.amazon.jsii.Builder { + private java.lang.Number foo; + + /** + * Sets the value of {@link Foo#getFoo} + * @param foo the value to be set. This parameter is required. + * @return {@code this} + */ + public Builder foo(java.lang.Number foo) { + this.foo = foo; + return this; + } + + /** + * Builds the configured instance. + * @return a new instance of {@link Foo} + * @throws NullPointerException if any required attribute was not provided + */ + @Override + public Foo build() { + return new Jsii$Proxy(foo); + } + } + + /** + * An implementation for {@link Foo} + */ + @software.amazon.jsii.Internal + final class Jsii$Proxy extends software.amazon.jsii.JsiiObject implements Foo { + private final java.lang.Number foo; + + /** + * Constructor that initializes the object based on values retrieved from the JsiiObject. + * @param objRef Reference to the JSII managed object. + */ + protected Jsii$Proxy(final software.amazon.jsii.JsiiObjectRef objRef) { + super(objRef); + this.foo = software.amazon.jsii.Kernel.get(this, "foo", software.amazon.jsii.NativeType.forClass(java.lang.Number.class)); + } + + /** + * Constructor that initializes the object based on literal property values passed by the {@link Builder}. + */ + protected Jsii$Proxy(final java.lang.Number foo) { + super(software.amazon.jsii.JsiiObject.InitializationMode.JSII); + this.foo = java.util.Objects.requireNonNull(foo, "foo is required"); + } + + @Override + public final java.lang.Number getFoo() { + return this.foo; + } + + @Override + @software.amazon.jsii.Internal + public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { + final com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; + final com.fasterxml.jackson.databind.node.ObjectNode data = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); + + data.set("foo", om.valueToTree(this.getFoo())); + + final com.fasterxml.jackson.databind.node.ObjectNode struct = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); + struct.set("fqn", om.valueToTree("testpkg.Foo")); + struct.set("data", data); + + final com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); + obj.set("$jsii.struct", struct); + + return obj; + } + + @Override + public final boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Foo.Jsii$Proxy that = (Foo.Jsii$Proxy) o; + + return this.foo.equals(that.foo); + } + + @Override + public final int hashCode() { + int result = this.foo.hashCode(); + return result; + } + } +} + +`; + +exports[`diamond-struct-parameter.ts: /java/src/main/java/example/test/demo/FooBar.java 1`] = ` +package example.test.demo; + +@javax.annotation.Generated(value = "jsii-pacmak") +@software.amazon.jsii.Jsii(module = example.test.demo.$Module.class, fqn = "testpkg.FooBar") +@software.amazon.jsii.Jsii.Proxy(FooBar.Jsii$Proxy.class) +public interface FooBar extends software.amazon.jsii.JsiiSerializable { + + @org.jetbrains.annotations.NotNull java.lang.Number getFoo(); + + default @org.jetbrains.annotations.Nullable java.lang.String getBar() { + return null; + } + + /** + * @return a {@link Builder} of {@link FooBar} + */ + static Builder builder() { + return new Builder(); + } + /** + * A builder for {@link FooBar} + */ + public static final class Builder implements software.amazon.jsii.Builder { + private java.lang.Number foo; + private java.lang.String bar; + + /** + * Sets the value of {@link FooBar#getFoo} + * @param foo the value to be set. This parameter is required. + * @return {@code this} + */ + public Builder foo(java.lang.Number foo) { + this.foo = foo; + return this; + } + + /** + * Sets the value of {@link FooBar#getBar} + * @param bar the value to be set. + * @return {@code this} + */ + public Builder bar(java.lang.String bar) { + this.bar = bar; + return this; + } + + /** + * Builds the configured instance. + * @return a new instance of {@link FooBar} + * @throws NullPointerException if any required attribute was not provided + */ + @Override + public FooBar build() { + return new Jsii$Proxy(foo, bar); + } + } + + /** + * An implementation for {@link FooBar} + */ + @software.amazon.jsii.Internal + final class Jsii$Proxy extends software.amazon.jsii.JsiiObject implements FooBar { + private final java.lang.Number foo; + private final java.lang.String bar; + + /** + * Constructor that initializes the object based on values retrieved from the JsiiObject. + * @param objRef Reference to the JSII managed object. + */ + protected Jsii$Proxy(final software.amazon.jsii.JsiiObjectRef objRef) { + super(objRef); + this.foo = software.amazon.jsii.Kernel.get(this, "foo", software.amazon.jsii.NativeType.forClass(java.lang.Number.class)); + this.bar = software.amazon.jsii.Kernel.get(this, "bar", software.amazon.jsii.NativeType.forClass(java.lang.String.class)); + } + + /** + * Constructor that initializes the object based on literal property values passed by the {@link Builder}. + */ + protected Jsii$Proxy(final java.lang.Number foo, final java.lang.String bar) { + super(software.amazon.jsii.JsiiObject.InitializationMode.JSII); + this.foo = java.util.Objects.requireNonNull(foo, "foo is required"); + this.bar = bar; + } + + @Override + public final java.lang.Number getFoo() { + return this.foo; + } + + @Override + public final java.lang.String getBar() { + return this.bar; + } + + @Override + @software.amazon.jsii.Internal + public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { + final com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; + final com.fasterxml.jackson.databind.node.ObjectNode data = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); + + data.set("foo", om.valueToTree(this.getFoo())); + if (this.getBar() != null) { + data.set("bar", om.valueToTree(this.getBar())); + } + + final com.fasterxml.jackson.databind.node.ObjectNode struct = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); + struct.set("fqn", om.valueToTree("testpkg.FooBar")); + struct.set("data", data); + + final com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); + obj.set("$jsii.struct", struct); + + return obj; + } + + @Override + public final boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + FooBar.Jsii$Proxy that = (FooBar.Jsii$Proxy) o; + + if (!foo.equals(that.foo)) return false; + return this.bar != null ? this.bar.equals(that.bar) : that.bar == null; + } + + @Override + public final int hashCode() { + int result = this.foo.hashCode(); + result = 31 * result + (this.bar != null ? this.bar.hashCode() : 0); + return result; + } + } +} + +`; + +exports[`diamond-struct-parameter.ts: /java/src/main/resources/example/test/demo/$Module.txt 1`] = ` +testpkg.Baz=example.test.demo.Baz +testpkg.Consumer=example.test.demo.Consumer +testpkg.Foo=example.test.demo.Foo +testpkg.FooBar=example.test.demo.FooBar + +`; + +exports[`diamond-struct-parameter.ts: /python/pyproject.toml 1`] = ` +[build-system] +requires = ["setuptools~=54.1.2", "wheel~=0.36.2"] +build-backend = "setuptools.build_meta" + +`; + +exports[`diamond-struct-parameter.ts: /python/setup.py 1`] = ` +import json +import setuptools + +kwargs = json.loads( + """ +{ + "name": "example-test.demo", + "version": "0.0.1", + "description": "testpkg", + "license": "Apache-2.0", + "url": "https://github.com/aws/jsii.git", + "long_description_content_type": "text/markdown", + "author": "John Doe", + "bdist_wheel": { + "universal": true + }, + "project_urls": { + "Source": "https://github.com/aws/jsii.git" + }, + "package_dir": { + "": "src" + }, + "packages": [ + "example_test_demo", + "example_test_demo._jsii" + ], + "package_data": { + "example_test_demo._jsii": [ + "testpkg@0.0.1.jsii.tgz" + ], + "example_test_demo": [ + "py.typed" + ] + }, + "python_requires": ">=3.6", + "install_requires": [ + "jsii<0.0.1", + "publication>=0.0.3" + ], + "classifiers": [ + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: JavaScript", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Typing :: Typed", + "License :: OSI Approved" + ], + "scripts": [] +} +""" +) + +with open("README.md", encoding="utf8") as fp: + kwargs["long_description"] = fp.read() + + +setuptools.setup(**kwargs) + +`; + +exports[`diamond-struct-parameter.ts: /python/src/example_test_demo/__init__.py 1`] = ` +import abc +import builtins +import datetime +import enum +import typing + +import jsii +import publication +import typing_extensions + +from ._jsii import * + + +class Consumer(metaclass=jsii.JSIIMeta, jsii_type="testpkg.Consumer"): + @jsii.member(jsii_name="consumeBaz") # type: ignore[misc] + @builtins.classmethod + def consume_baz( + cls, + *, + baz: builtins.bool, + foo: jsii.Number, + bar: typing.Optional[builtins.str] = None, + ) -> None: + ''' + :param baz: - + :param foo: - + :param bar: - + ''' + baz_ = Baz(baz=baz, foo=foo, bar=bar) + + return typing.cast(None, jsii.sinvoke(cls, "consumeBaz", [baz_])) + + +@jsii.data_type( + jsii_type="testpkg.Foo", + jsii_struct_bases=[], + name_mapping={"foo": "foo"}, +) +class Foo: + def __init__(self, *, foo: jsii.Number) -> None: + ''' + :param foo: - + ''' + self._values: typing.Dict[str, typing.Any] = { + "foo": foo, + } + + @builtins.property + def foo(self) -> jsii.Number: + result = self._values.get("foo") + assert result is not None, "Required property 'foo' is missing" + return typing.cast(jsii.Number, result) + + def __eq__(self, rhs: typing.Any) -> builtins.bool: + return isinstance(rhs, self.__class__) and rhs._values == self._values + + def __ne__(self, rhs: typing.Any) -> builtins.bool: + return not (rhs == self) + + def __repr__(self) -> str: + return "Foo(%s)" % ", ".join( + k + "=" + repr(v) for k, v in self._values.items() + ) + + +@jsii.data_type( + jsii_type="testpkg.FooBar", + jsii_struct_bases=[], + name_mapping={"foo": "foo", "bar": "bar"}, +) +class FooBar: + def __init__( + self, + *, + foo: jsii.Number, + bar: typing.Optional[builtins.str] = None, + ) -> None: + ''' + :param foo: - + :param bar: - + ''' + self._values: typing.Dict[str, typing.Any] = { + "foo": foo, + } + if bar is not None: + self._values["bar"] = bar + + @builtins.property + def foo(self) -> jsii.Number: + result = self._values.get("foo") + assert result is not None, "Required property 'foo' is missing" + return typing.cast(jsii.Number, result) + + @builtins.property + def bar(self) -> typing.Optional[builtins.str]: + result = self._values.get("bar") + return typing.cast(typing.Optional[builtins.str], result) + + def __eq__(self, rhs: typing.Any) -> builtins.bool: + return isinstance(rhs, self.__class__) and rhs._values == self._values + + def __ne__(self, rhs: typing.Any) -> builtins.bool: + return not (rhs == self) + + def __repr__(self) -> str: + return "FooBar(%s)" % ", ".join( + k + "=" + repr(v) for k, v in self._values.items() + ) + + +@jsii.data_type( + jsii_type="testpkg.Baz", + jsii_struct_bases=[Foo, FooBar], + name_mapping={"foo": "foo", "bar": "bar", "baz": "baz"}, +) +class Baz(Foo, FooBar): + def __init__( + self, + *, + foo: jsii.Number, + bar: typing.Optional[builtins.str] = None, + baz: builtins.bool, + ) -> None: + ''' + :param foo: - + :param bar: - + :param baz: - + ''' + self._values: typing.Dict[str, typing.Any] = { + "foo": foo, + "baz": baz, + } + if bar is not None: + self._values["bar"] = bar + + @builtins.property + def foo(self) -> jsii.Number: + result = self._values.get("foo") + assert result is not None, "Required property 'foo' is missing" + return typing.cast(jsii.Number, result) + + @builtins.property + def bar(self) -> typing.Optional[builtins.str]: + result = self._values.get("bar") + return typing.cast(typing.Optional[builtins.str], result) + + @builtins.property + def baz(self) -> builtins.bool: + result = self._values.get("baz") + assert result is not None, "Required property 'baz' is missing" + return typing.cast(builtins.bool, result) + + def __eq__(self, rhs: typing.Any) -> builtins.bool: + return isinstance(rhs, self.__class__) and rhs._values == self._values + + def __ne__(self, rhs: typing.Any) -> builtins.bool: + return not (rhs == self) + + def __repr__(self) -> str: + return "Baz(%s)" % ", ".join( + k + "=" + repr(v) for k, v in self._values.items() + ) + + +__all__ = [ + "Baz", + "Consumer", + "Foo", + "FooBar", +] + +publication.publish() + +`; + +exports[`diamond-struct-parameter.ts: /python/src/example_test_demo/_jsii/__init__.py 1`] = ` +import abc +import builtins +import datetime +import enum +import typing + +import jsii +import publication +import typing_extensions + +__jsii_assembly__ = jsii.JSIIAssembly.load( + "testpkg", "0.0.1", __name__[0:-6], "testpkg@0.0.1.jsii.tgz" +) + +__all__ = [ + "__jsii_assembly__", +] + +publication.publish() + +`; + +exports[`diamond-struct-parameter.ts: /python/src/example_test_demo/py.typed 1`] = ` + + +`; + exports[`nested-types.ts: / 1`] = ` ┣━ 📁 dotnet diff --git a/packages/jsii-pacmak/test/generated-code/examples/diamond-struct-parameter.ts b/packages/jsii-pacmak/test/generated-code/examples/diamond-struct-parameter.ts new file mode 100644 index 0000000000..76a521e911 --- /dev/null +++ b/packages/jsii-pacmak/test/generated-code/examples/diamond-struct-parameter.ts @@ -0,0 +1,22 @@ +// See: https://github.com/aws/jsii/issues/2653 + +export interface Foo { + readonly foo: number; +} + +export interface FooBar { + readonly foo: number; + readonly bar?: string; +} + +export interface Baz extends Foo, FooBar { + readonly baz: boolean; +} + +export class Consumer { + public static consumeBaz(baz: Baz): void { + new Consumer(baz); + } + + private constructor(_: any) {} +}