From bdac52b77e095693a5cefbf3c3fc24cc239d6eb2 Mon Sep 17 00:00:00 2001 From: Romain Marcadier Date: Wed, 13 May 2020 18:49:10 +0200 Subject: [PATCH 1/6] feat(java): use covariant types for collection elements (#1653) Using covariant expressions instead of just the type name enables a better experience when using libraries such as Guava to build up collections (`List` or `Map`) to use with the libraries. In particular, collections of `any` are particularly annoying to use without covariant typing because they'd force the user to manually specify generic parameters in their code that add nothing to the safety of the program. Fixes #1517 --- packages/jsii-pacmak/lib/targets/java.ts | 140 +++++++++++++----- .../__snapshots__/jsii-pacmak.test.ts.snap | 22 +-- 2 files changed, 115 insertions(+), 47 deletions(-) diff --git a/packages/jsii-pacmak/lib/targets/java.ts b/packages/jsii-pacmak/lib/targets/java.ts index ca722f187a..1848e86646 100644 --- a/packages/jsii-pacmak/lib/targets/java.ts +++ b/packages/jsii-pacmak/lib/targets/java.ts @@ -477,6 +477,9 @@ interface JavaProp { // The java type for the property (eg: 'List') fieldJavaType: string; + // The java type for the parameter (e.g: 'List') + paramJavaType: string; + // The NativeType representation of the property's type fieldNativeType: string; @@ -849,7 +852,6 @@ class JavaGenerator extends Generator { protected onInterfaceProperty(_ifc: spec.InterfaceType, prop: spec.Property) { const getterType = this.toDecoratedJavaType(prop); - const setterTypes = this.toDecoratedJavaTypes(prop); const propName = this.code.toPascalCase( JavaGenerator.safeJavaPropertyName(prop.name), ); @@ -867,6 +869,7 @@ class JavaGenerator extends Generator { } if (!prop.immutable) { + const setterTypes = this.toDecoratedJavaTypes(prop); for (const type of setterTypes) { this.code.line(); this.addJavaDocs(prop); @@ -1186,7 +1189,7 @@ class JavaGenerator extends Generator { for (const prop of consts) { const constName = this.renderConstName(prop); - const propType = this.toNativeType(prop.type, true); + const propType = this.toNativeType(prop.type, { forMarshalling: true }); const statement = `software.amazon.jsii.JsiiObject.jsiiStaticGet(${javaClass}.class, "${prop.name}", ${propType})`; this.code.line( `${constName} = ${this.wrapCollection( @@ -1222,7 +1225,9 @@ class JavaGenerator extends Generator { overrides = !!prop.overrides, ) { const getterType = this.toDecoratedJavaType(prop); - const setterTypes = this.toDecoratedJavaTypes(prop); + const setterTypes = this.toDecoratedJavaTypes(prop, { + covariant: prop.static, + }); const propName = this.code.toPascalCase( JavaGenerator.safeJavaPropertyName(prop.name), ); @@ -1251,7 +1256,9 @@ class JavaGenerator extends Generator { statement = 'this.jsiiGet('; } - statement += `"${prop.name}", ${this.toNativeType(prop.type, true)})`; + statement += `"${prop.name}", ${this.toNativeType(prop.type, { + forMarshalling: true, + })})`; this.code.line( `return ${this.wrapCollection(statement, prop.type, prop.optional)};`, @@ -1469,9 +1476,12 @@ class JavaGenerator extends Generator { nullable: !!property.optional, fieldName: this.code.toCamelCase(safeName), fieldJavaType: this.toJavaType(property.type), + paramJavaType: this.toJavaType(property.type, { covariant: true }), fieldNativeType: this.toNativeType(property.type), - fieldJavaClass: `${this.toJavaType(property.type, true)}.class`, - javaTypes: this.toJavaTypes(property.type), + fieldJavaClass: `${this.toJavaType(property.type, { + forMarshalling: true, + })}.class`, + javaTypes: this.toJavaTypes(property.type, { covariant: true }), immutable: property.immutable || false, inherited, }; @@ -1525,7 +1535,7 @@ class JavaGenerator extends Generator { fieldName: this.code.toCamelCase( JavaGenerator.safeJavaPropertyName(param.name), ), - javaType: this.toJavaType(param.type), + javaType: this.toJavaType(param.type, { covariant: true }), })); const builtType = this.toJavaType(cls); @@ -1625,7 +1635,9 @@ class JavaGenerator extends Generator { }, ], }; - for (const javaType of this.toJavaTypes(prop.type.spec!)) { + for (const javaType of this.toJavaTypes(prop.type.spec!, { + covariant: true, + })) { this.addJavaDocs(setter); this.emitStabilityAnnotations(prop.spec); this.code.openBlock( @@ -1713,10 +1725,23 @@ class JavaGenerator extends Generator { } this.code.line(' */'); this.emitStabilityAnnotations(prop.spec); + // We add an explicit cast if both types are generic but they are not identical (one is covariant, the other isn't) + const explicitCast = + type.includes('<') && + prop.fieldJavaType.includes('<') && + type !== prop.fieldJavaType + ? `(${prop.fieldJavaType})` + : ''; + if (explicitCast !== '') { + // We'll be doing a safe, but unchecked cast, so suppress that warning + this.code.line('@SuppressWarnings("unchecked")'); + } this.code.openBlock( `public ${builderName} ${prop.fieldName}(${type} ${prop.fieldName})`, ); - this.code.line(`this.${prop.fieldName} = ${prop.fieldName};`); + this.code.line( + `this.${prop.fieldName} = ${explicitCast}${prop.fieldName};`, + ); this.code.line('return this;'); this.code.closeBlock(); } @@ -1856,8 +1881,11 @@ class JavaGenerator extends Generator { ' * Constructor that initializes the object based on literal property values passed by the {@link Builder}.', ); this.code.line(' */'); + if (props.some((prop) => prop.fieldJavaType !== prop.paramJavaType)) { + this.code.line('@SuppressWarnings("unchecked")'); + } const constructorArgs = props - .map((prop) => `final ${prop.fieldJavaType} ${prop.fieldName}`) + .map((prop) => `final ${prop.paramJavaType} ${prop.fieldName}`) .join(', '); this.code.openBlock( `private ${INTERFACE_PROXY_CLASS_NAME}(${constructorArgs})`, @@ -1866,8 +1894,12 @@ class JavaGenerator extends Generator { 'super(software.amazon.jsii.JsiiObject.InitializationMode.JSII);', ); props.forEach((prop) => { + const explicitCast = + prop.fieldJavaType !== prop.paramJavaType + ? `(${prop.fieldJavaType})` + : ''; this.code.line( - `this.${prop.fieldName} = ${_validateIfNonOptional( + `this.${prop.fieldName} = ${explicitCast}${_validateIfNonOptional( prop.fieldName, prop, )};`, @@ -2168,8 +2200,11 @@ class JavaGenerator extends Generator { return this.toJavaType({ fqn: cls.base }); } - private toDecoratedJavaType(optionalValue: spec.OptionalValue): string { - const result = this.toDecoratedJavaTypes(optionalValue); + private toDecoratedJavaType( + optionalValue: spec.OptionalValue, + { covariant = false } = {}, + ): string { + const result = this.toDecoratedJavaTypes(optionalValue, { covariant }); if (result.length > 1) { return `${ optionalValue.optional ? ANN_NULLABLE : ANN_NOT_NULL @@ -2178,15 +2213,21 @@ class JavaGenerator extends Generator { return result[0]; } - private toDecoratedJavaTypes(optionalValue: spec.OptionalValue): string[] { - return this.toJavaTypes(optionalValue.type).map( + private toDecoratedJavaTypes( + optionalValue: spec.OptionalValue, + { covariant = false } = {}, + ): string[] { + return this.toJavaTypes(optionalValue.type, { covariant }).map( (nakedType) => `${optionalValue.optional ? ANN_NULLABLE : ANN_NOT_NULL} ${nakedType}`, ); } - private toJavaType(type: spec.TypeReference, forMarshalling = false): string { - const types = this.toJavaTypes(type, forMarshalling); + private toJavaType( + type: spec.TypeReference, + opts?: { forMarshalling?: boolean; covariant?: boolean }, + ): string { + const types = this.toJavaTypes(type, opts); if (types.length > 1) { return 'java.lang.Object'; } @@ -2195,15 +2236,14 @@ class JavaGenerator extends Generator { private toNativeType( type: spec.TypeReference, - forMarshalling = false, - recursing = false, + { forMarshalling = false, covariant = false, recursing = false } = {}, ): string { if (spec.isCollectionTypeReference(type)) { - const nativeElementType = this.toNativeType( - type.collection.elementtype, + const nativeElementType = this.toNativeType(type.collection.elementtype, { forMarshalling, - true, - ); + covariant, + recursing: true, + }); switch (type.collection.kind) { case spec.CollectionKind.Array: return `software.amazon.jsii.NativeType.listOf(${nativeElementType})`; @@ -2216,27 +2256,30 @@ class JavaGenerator extends Generator { } } return recursing - ? `software.amazon.jsii.NativeType.forClass(${this.toJavaType( - type, + ? `software.amazon.jsii.NativeType.forClass(${this.toJavaType(type, { forMarshalling, - )}.class)` - : `${this.toJavaType(type, forMarshalling)}.class`; + covariant, + })}.class)` + : `${this.toJavaType(type, { forMarshalling, covariant })}.class`; } private toJavaTypes( typeref: spec.TypeReference, - forMarshalling = false, + { forMarshalling = false, covariant = false } = {}, ): string[] { if (spec.isPrimitiveTypeReference(typeref)) { return [this.toJavaPrimitive(typeref.primitive)]; } else if (spec.isCollectionTypeReference(typeref)) { - return [this.toJavaCollection(typeref, forMarshalling)]; + return [this.toJavaCollection(typeref, { forMarshalling, covariant })]; } else if (spec.isNamedTypeReference(typeref)) { return [this.toNativeFqn(typeref.fqn)]; } else if (typeref.union) { const types = new Array(); for (const subtype of typeref.union.types) { - for (const t of this.toJavaTypes(subtype, forMarshalling)) { + for (const t of this.toJavaTypes(subtype, { + forMarshalling, + covariant, + })) { types.push(t); } } @@ -2247,23 +2290,39 @@ class JavaGenerator extends Generator { private toJavaCollection( ref: spec.CollectionTypeReference, - forMarshalling: boolean, + { + forMarshalling, + covariant, + }: { forMarshalling: boolean; covariant: boolean }, ) { - const elementJavaType = this.toJavaType(ref.collection.elementtype); + const elementJavaType = this.toJavaType(ref.collection.elementtype, { + covariant, + }); + const typeConstraint = covariant + ? makeCovariant(elementJavaType) + : elementJavaType; switch (ref.collection.kind) { case spec.CollectionKind.Array: return forMarshalling ? 'java.util.List' - : `java.util.List<${elementJavaType}>`; + : `java.util.List<${typeConstraint}>`; case spec.CollectionKind.Map: return forMarshalling ? 'java.util.Map' - : `java.util.Map`; + : `java.util.Map`; default: throw new Error( `Unsupported collection kind: ${ref.collection.kind as any}`, ); } + + function makeCovariant(javaType: string): string { + // Don't emit a covariant expression for String (it's `final` in Java), or generic types (List, Map, ...) + if (javaType === 'java.lang.String' || javaType.includes('<')) { + return javaType; + } + return `? extends ${javaType}`; + } } private toJavaPrimitive(primitive: spec.PrimitiveType) { @@ -2335,7 +2394,9 @@ class JavaGenerator extends Generator { statement += `"${method.name}"`; if (method.returns) { - statement += `, ${this.toNativeType(method.returns.type, true)}`; + statement += `, ${this.toNativeType(method.returns.type, { + forMarshalling: true, + })}`; } else { statement += ', software.amazon.jsii.NativeType.VOID'; } @@ -2396,10 +2457,13 @@ class JavaGenerator extends Generator { const params = []; if (method.parameters) { for (const p of method.parameters) { + // We can render covariant parameters only for methods that aren't overridable... so only for static methods currently. params.push( - `final ${this.toDecoratedJavaType(p)}${ - p.variadic ? '...' : '' - } ${JavaGenerator.safeJavaPropertyName(p.name)}`, + `final ${this.toDecoratedJavaType(p, { + covariant: (method as spec.Method).static, + })}${p.variadic ? '...' : ''} ${JavaGenerator.safeJavaPropertyName( + p.name, + )}`, ); } } diff --git a/packages/jsii-pacmak/test/__snapshots__/jsii-pacmak.test.ts.snap b/packages/jsii-pacmak/test/__snapshots__/jsii-pacmak.test.ts.snap index f428ff92a9..1dc42ed3a3 100644 --- a/packages/jsii-pacmak/test/__snapshots__/jsii-pacmak.test.ts.snap +++ b/packages/jsii-pacmak/test/__snapshots__/jsii-pacmak.test.ts.snap @@ -40373,7 +40373,7 @@ public interface ConfusingToJacksonStruct extends software.amazon.jsii.JsiiSeria * @return {@code this} */ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental) - public Builder unionProperty(java.util.List unionProperty) { + public Builder unionProperty(java.util.List unionProperty) { this.unionProperty = unionProperty; return this; } @@ -41395,8 +41395,9 @@ public interface DerivedStruct extends software.amazon.jsii.JsiiSerializable, so * @return {@code this} */ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental) - public Builder anotherOptional(java.util.Map anotherOptional) { - this.anotherOptional = anotherOptional; + @SuppressWarnings("unchecked") + public Builder anotherOptional(java.util.Map anotherOptional) { + this.anotherOptional = (java.util.Map)anotherOptional; return this; } @@ -41505,12 +41506,13 @@ public interface DerivedStruct extends software.amazon.jsii.JsiiSerializable, so /** * Constructor that initializes the object based on literal property values passed by the {@link Builder}. */ - private Jsii$Proxy(final java.time.Instant anotherRequired, final java.lang.Boolean bool, final software.amazon.jsii.tests.calculator.DoubleTrouble nonPrimitive, final java.util.Map anotherOptional, final java.lang.Object optionalAny, final java.util.List optionalArray, final java.lang.Number anumber, final java.lang.String astring, final java.util.List firstOptional) { + @SuppressWarnings("unchecked") + private Jsii$Proxy(final java.time.Instant anotherRequired, final java.lang.Boolean bool, final software.amazon.jsii.tests.calculator.DoubleTrouble nonPrimitive, final java.util.Map anotherOptional, final java.lang.Object optionalAny, final java.util.List optionalArray, final java.lang.Number anumber, final java.lang.String astring, final java.util.List firstOptional) { super(software.amazon.jsii.JsiiObject.InitializationMode.JSII); this.anotherRequired = java.util.Objects.requireNonNull(anotherRequired, "anotherRequired is required"); this.bool = java.util.Objects.requireNonNull(bool, "bool is required"); this.nonPrimitive = java.util.Objects.requireNonNull(nonPrimitive, "nonPrimitive is required"); - this.anotherOptional = anotherOptional; + this.anotherOptional = (java.util.Map)anotherOptional; this.optionalAny = optionalAny; this.optionalArray = optionalArray; this.anumber = java.util.Objects.requireNonNull(anumber, "anumber is required"); @@ -48147,8 +48149,9 @@ public interface NullShouldBeTreatedAsUndefinedData extends software.amazon.jsii * @return {@code this} */ @software.amazon.jsii.Stability(software.amazon.jsii.Stability.Level.Experimental) - public Builder arrayWithThreeElementsAndUndefinedAsSecondArgument(java.util.List arrayWithThreeElementsAndUndefinedAsSecondArgument) { - this.arrayWithThreeElementsAndUndefinedAsSecondArgument = arrayWithThreeElementsAndUndefinedAsSecondArgument; + @SuppressWarnings("unchecked") + public Builder arrayWithThreeElementsAndUndefinedAsSecondArgument(java.util.List arrayWithThreeElementsAndUndefinedAsSecondArgument) { + this.arrayWithThreeElementsAndUndefinedAsSecondArgument = (java.util.List)arrayWithThreeElementsAndUndefinedAsSecondArgument; return this; } @@ -48196,9 +48199,10 @@ public interface NullShouldBeTreatedAsUndefinedData extends software.amazon.jsii /** * Constructor that initializes the object based on literal property values passed by the {@link Builder}. */ - private Jsii$Proxy(final java.util.List arrayWithThreeElementsAndUndefinedAsSecondArgument, final java.lang.Object thisShouldBeUndefined) { + @SuppressWarnings("unchecked") + private Jsii$Proxy(final java.util.List arrayWithThreeElementsAndUndefinedAsSecondArgument, final java.lang.Object thisShouldBeUndefined) { super(software.amazon.jsii.JsiiObject.InitializationMode.JSII); - this.arrayWithThreeElementsAndUndefinedAsSecondArgument = java.util.Objects.requireNonNull(arrayWithThreeElementsAndUndefinedAsSecondArgument, "arrayWithThreeElementsAndUndefinedAsSecondArgument is required"); + this.arrayWithThreeElementsAndUndefinedAsSecondArgument = (java.util.List)java.util.Objects.requireNonNull(arrayWithThreeElementsAndUndefinedAsSecondArgument, "arrayWithThreeElementsAndUndefinedAsSecondArgument is required"); this.thisShouldBeUndefined = thisShouldBeUndefined; } From 7508a1fabefcc57ff06183cedff564e206557e7f 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: Fri, 14 Aug 2020 16:23:46 +0200 Subject: [PATCH 2/6] try to understand why integ test blows up --- packages/jsii-pacmak/lib/targets/java.ts | 2 ++ packages/jsii-pacmak/lib/util.ts | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/jsii-pacmak/lib/targets/java.ts b/packages/jsii-pacmak/lib/targets/java.ts index 1848e86646..8156f0802c 100644 --- a/packages/jsii-pacmak/lib/targets/java.ts +++ b/packages/jsii-pacmak/lib/targets/java.ts @@ -431,6 +431,8 @@ export default class Java extends Target { await shell( 'mvn', [ + // If we don't run in verbose mode, turn on quiet mode + ...(this.arguments.verbose ? [] : ['--quiet']), ...mvnArguments, 'deploy', `-D=altDeploymentRepository=local::default::${url}`, diff --git a/packages/jsii-pacmak/lib/util.ts b/packages/jsii-pacmak/lib/util.ts index f97c115c38..27a74e6f18 100644 --- a/packages/jsii-pacmak/lib/util.ts +++ b/packages/jsii-pacmak/lib/util.ts @@ -75,8 +75,9 @@ export async function shell( new Error( [ `Command (${command}) failed with ${reason}:`, - prefix(out, '#STDOUT> '), + // STDERR first, the erro message could be truncated in logs. prefix(err, '#STDERR> '), + prefix(out, '#STDOUT> '), ].join('\n'), ), ); From 1bb328e8daf5c4cddb56f75319fcb4a0ca338139 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: Mon, 17 Aug 2020 12:44:46 +0200 Subject: [PATCH 3/6] allow more memory for maven --- .github/workflows/main.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 92a345bc9d..b82889b200 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -379,13 +379,16 @@ jobs: npx lerna run build ./pack.sh env: + # Tested tools locations: CDK_BUILD_JSII: ${{ github.workspace }}/node_modules/.bin/jsii CDK_PACKAGE_JSII_PACMAK: ${{ github.workspace }}/node_modules/.bin/jsii-pacmak CDK_PACKAGE_JSII_ROSETTA: ${{ github.workspace }}/node_modules/.bin/jsii-rosetta - # Alternative environment variables: + # Alternative environment variables for tested tools: JSII: ${{ github.workspace }}/node_modules/.bin/jsii PACMAK: ${{ github.workspace }}/node_modules/.bin/jsii-pacmak ROSETTA: ${{ github.workspace }}/node_modules/.bin/jsii-rosetta + # Build environment + MAVEN_OPTS: -Xms1024m -Xmx4096m working-directory: aws-cdk - name: Upload Result uses: actions/upload-artifact@v2 From 1f460047a344797968f09cd53657a1c7c39ac788 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, 18 Aug 2020 10:30:05 +0200 Subject: [PATCH 4/6] attempt to collect complete logs --- .github/workflows/main.yml | 11 +++++++++-- packages/jsii-pacmak/lib/targets/java.ts | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6ef3e093e0..66176eab12 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -376,8 +376,8 @@ jobs: npm install --no-save ${{ runner.temp }}/private/*.tgz --only=prod - name: Integration Test run: |- - npx lerna run build - ./pack.sh + npx lerna run build > >(tee ${{ runner.temp }}/stdout.log) 2> >(tee ${{ runner.temp }}/stderr.log >&2) + ./pack.sh > >(tee -a ${{ runner.temp }}/stdout.log) 2> >(tee -a ${{ runner.temp }}/stderr.log >&2) env: # Tested tools locations: CDK_BUILD_JSII: ${{ github.workspace }}/node_modules/.bin/jsii @@ -390,6 +390,13 @@ jobs: # Build environment MAVEN_OPTS: -Xms1024m -Xmx4096m working-directory: aws-cdk + - name: Upload Logs + # Upload logs whether successful or failed (not using always because we don't care about cancellations) + if: success() || failure() + uses: actions/upload-artifact@v2 + with: + name: integ-test-logs + path: ${{ runner.temp }}/*.log - name: Upload Result uses: actions/upload-artifact@v2 with: diff --git a/packages/jsii-pacmak/lib/targets/java.ts b/packages/jsii-pacmak/lib/targets/java.ts index 8156f0802c..6f4c395fdb 100644 --- a/packages/jsii-pacmak/lib/targets/java.ts +++ b/packages/jsii-pacmak/lib/targets/java.ts @@ -433,6 +433,7 @@ export default class Java extends Target { [ // If we don't run in verbose mode, turn on quiet mode ...(this.arguments.verbose ? [] : ['--quiet']), + '--batch-mode', ...mvnArguments, 'deploy', `-D=altDeploymentRepository=local::default::${url}`, From b60cf2968627b763191d1c7740e4c09229b85584 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, 18 Aug 2020 14:08:24 +0200 Subject: [PATCH 5/6] attempt tin increase verbosity --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 66176eab12..1bb9d8d3b5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -381,11 +381,11 @@ jobs: env: # Tested tools locations: CDK_BUILD_JSII: ${{ github.workspace }}/node_modules/.bin/jsii - CDK_PACKAGE_JSII_PACMAK: ${{ github.workspace }}/node_modules/.bin/jsii-pacmak + CDK_PACKAGE_JSII_PACMAK: ${{ github.workspace }}/node_modules/.bin/jsii-pacmak --verbose CDK_PACKAGE_JSII_ROSETTA: ${{ github.workspace }}/node_modules/.bin/jsii-rosetta # Alternative environment variables for tested tools: JSII: ${{ github.workspace }}/node_modules/.bin/jsii - PACMAK: ${{ github.workspace }}/node_modules/.bin/jsii-pacmak + PACMAK: ${{ github.workspace }}/node_modules/.bin/jsii-pacmak --verbose ROSETTA: ${{ github.workspace }}/node_modules/.bin/jsii-rosetta # Build environment MAVEN_OPTS: -Xms1024m -Xmx4096m From 7a97985d8fd01e0100849fc60381c41babb25fbf 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, 18 Aug 2020 19:07:00 +0200 Subject: [PATCH 6/6] more covarianity --- packages/jsii-pacmak/lib/targets/java.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/jsii-pacmak/lib/targets/java.ts b/packages/jsii-pacmak/lib/targets/java.ts index 6f4c395fdb..d13fe1e3b4 100644 --- a/packages/jsii-pacmak/lib/targets/java.ts +++ b/packages/jsii-pacmak/lib/targets/java.ts @@ -2320,8 +2320,8 @@ class JavaGenerator extends Generator { } function makeCovariant(javaType: string): string { - // Don't emit a covariant expression for String (it's `final` in Java), or generic types (List, Map, ...) - if (javaType === 'java.lang.String' || javaType.includes('<')) { + // Don't emit a covariant expression for String (it's `final` in Java) + if (javaType === 'java.lang.String') { return javaType; } return `? extends ${javaType}`;