jsii-pacmak 1.113.0 → 1.115.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/bin/jsii-pacmak.js +1 -1
  2. package/lib/index.js +2 -0
  3. package/lib/npm-modules.d.ts +1 -1
  4. package/lib/npm-modules.js +1 -3
  5. package/lib/packaging.d.ts +1 -5
  6. package/lib/packaging.js +12 -6
  7. package/lib/rosetta-assembly.d.ts +20 -0
  8. package/lib/rosetta-assembly.js +29 -0
  9. package/lib/targets/dotnet/dotnetdocgenerator.d.ts +4 -1
  10. package/lib/targets/dotnet/dotnetdocgenerator.js +69 -13
  11. package/lib/targets/dotnet/dotnetgenerator.d.ts +0 -4
  12. package/lib/targets/dotnet/dotnetgenerator.js +24 -14
  13. package/lib/targets/dotnet/dotnetruntimegenerator.js +11 -2
  14. package/lib/targets/dotnet/dotnettyperesolver.d.ts +13 -0
  15. package/lib/targets/dotnet/dotnettyperesolver.js +42 -4
  16. package/lib/targets/dotnet.d.ts +1 -1
  17. package/lib/targets/dotnet.js +6 -4
  18. package/lib/targets/go/runtime/runtime-type-checking.js +1 -0
  19. package/lib/targets/go/types/go-type-reference.d.ts +3 -0
  20. package/lib/targets/go/types/go-type-reference.js +20 -0
  21. package/lib/targets/go.js +1 -1
  22. package/lib/targets/java.d.ts +28 -4
  23. package/lib/targets/java.js +411 -219
  24. package/lib/targets/python/requirements-dev.txt +2 -2
  25. package/lib/targets/python/type-name.d.ts +18 -0
  26. package/lib/targets/python/type-name.js +59 -1
  27. package/lib/targets/python.d.ts +2 -1
  28. package/lib/targets/python.js +53 -18
  29. package/lib/targets/type-literals.d.ts +22 -0
  30. package/lib/targets/type-literals.js +39 -0
  31. package/lib/type-utils.d.ts +3 -0
  32. package/lib/type-utils.js +10 -0
  33. package/lib/type-visitor.d.ts +19 -0
  34. package/lib/type-visitor.js +47 -0
  35. package/lib/util.d.ts +18 -5
  36. package/lib/util.js +80 -13
  37. package/lib/version.d.ts +1 -1
  38. package/lib/version.js +3 -3
  39. package/package.json +15 -14
@@ -18,6 +18,10 @@ const util_1 = require("../util");
18
18
  const version_1 = require("../version");
19
19
  const _utils_1 = require("./_utils");
20
20
  const version_utils_1 = require("./version-utils");
21
+ const rosetta_assembly_1 = require("../rosetta-assembly");
22
+ const type_utils_1 = require("../type-utils");
23
+ const type_visitor_1 = require("../type-visitor");
24
+ const type_literals_1 = require("./type-literals");
21
25
  const index_1 = require("./index");
22
26
  // eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-require-imports
23
27
  const spdxLicenseList = require('spdx-license-list');
@@ -305,7 +309,7 @@ class Java extends target_1.Target {
305
309
  mvnArguments.push(`--${arg.slice(4)}`);
306
310
  mvnArguments.push(this.arguments[arg].toString());
307
311
  }
308
- await (0, util_1.shell)('mvn', [
312
+ await (0, util_1.subprocess)('mvn', [
309
313
  // If we don't run in verbose mode, turn on quiet mode
310
314
  ...(this.arguments.verbose ? [] : ['--quiet']),
311
315
  '--batch-mode',
@@ -394,7 +398,9 @@ class JavaGenerator extends generator_1.Generator {
394
398
  this.openFileIfNeeded(cls);
395
399
  this.addJavaDocs(cls, { api: 'type', fqn: cls.fqn });
396
400
  const classBase = this.getClassBase(cls);
397
- const extendsExpression = classBase ? ` extends ${classBase}` : '';
401
+ const extendsExpression = classBase
402
+ ? ` extends ${displayStatic(classBase)}`
403
+ : '';
398
404
  let implementsExpr = '';
399
405
  if (cls.interfaces?.length ?? 0 > 0) {
400
406
  implementsExpr = ` implements ${cls
@@ -433,9 +439,14 @@ class JavaGenerator extends generator_1.Generator {
433
439
  const initializerAccessLevel = cls.abstract
434
440
  ? 'protected'
435
441
  : this.renderAccessLevel(method);
436
- this.code.openBlock(`${initializerAccessLevel} ${cls.name}(${this.renderMethodParameters(method)})`);
442
+ const types = this.convertTypes(method.parameters);
443
+ if (types.some((t) => t.type === 'param')) {
444
+ throw new Error('Cannot have generic type arguments to a constructor');
445
+ }
446
+ // NOTE: even though a constructor is technically final and we COULD render covariant types, historically we didn't and I'm not changing it.
447
+ this.code.openBlock(`${initializerAccessLevel} ${cls.name}(${this.renderParameters(method.parameters, types, 'final-but-not-cov')})`);
437
448
  this.code.line('super(software.amazon.jsii.JsiiObject.InitializationMode.JSII);');
438
- this.emitUnionParameterValdation(method.parameters);
449
+ this.emitUnionParameterValidation(method.parameters);
439
450
  this.code.line(`software.amazon.jsii.JsiiEngine.getInstance().createNewObject(this${this.renderMethodCallArguments(method)});`);
440
451
  this.code.closeBlock();
441
452
  }
@@ -550,22 +561,33 @@ class JavaGenerator extends generator_1.Generator {
550
561
  onInterfaceMethod(ifc, method) {
551
562
  this.code.line();
552
563
  const returnType = method.returns
553
- ? this.toDecoratedJavaType(method.returns)
554
- : 'void';
564
+ ? forceSingleType(this.toDecoratedJavaTypes(method.returns))
565
+ : mkStatic('void');
555
566
  const methodName = JavaGenerator.safeJavaMethodName(method.name);
556
567
  this.addJavaDocs(method, {
557
568
  api: 'member',
558
569
  fqn: ifc.fqn,
559
570
  memberName: methodName,
571
+ }, {
572
+ returnsUnion: method.returns?.type,
560
573
  });
561
574
  this.emitStabilityAnnotations(method);
562
- this.code.line(`${returnType} ${methodName}(${this.renderMethodParameters(method)});`);
575
+ const types = this.convertTypes(method.parameters);
576
+ this.code.line(`${typeVarDeclarations(types)}${displayStatic(returnType)} ${methodName}(${this.renderParameters(method.parameters, types, 'overridable')});`);
563
577
  }
564
578
  onInterfaceMethodOverload(ifc, overload, _originalMethod) {
565
579
  this.onInterfaceMethod(ifc, overload);
566
580
  }
567
581
  onInterfaceProperty(ifc, prop) {
568
- const getterType = this.toDecoratedJavaType(prop);
582
+ let apparentGetterType = prop;
583
+ // We can only ever return one type, so take the first one
584
+ if (spec.isIntersectionTypeReference(prop.type)) {
585
+ apparentGetterType = {
586
+ optional: prop.optional,
587
+ type: prop.type.intersection.types[0],
588
+ };
589
+ }
590
+ const getterType = forceSingleType(this.toDecoratedJavaTypes(apparentGetterType));
569
591
  const propName = (0, naming_util_1.jsiiToPascalCase)(JavaGenerator.safeJavaPropertyName(prop.name));
570
592
  // for unions we only generate overloads for setters, not getters.
571
593
  this.code.line();
@@ -573,18 +595,20 @@ class JavaGenerator extends generator_1.Generator {
573
595
  api: 'member',
574
596
  fqn: ifc.fqn,
575
597
  memberName: prop.name,
598
+ }, {
599
+ returnsUnion: prop.type,
576
600
  });
577
601
  this.emitStabilityAnnotations(prop);
578
602
  if (prop.optional) {
579
603
  if (prop.overrides) {
580
604
  this.code.line('@Override');
581
605
  }
582
- this.code.openBlock(`default ${getterType} get${propName}()`);
606
+ this.code.openBlock(`default ${displayStatic(getterType)} get${propName}()`);
583
607
  this.code.line('return null;');
584
608
  this.code.closeBlock();
585
609
  }
586
610
  else {
587
- this.code.line(`${getterType} get${propName}();`);
611
+ this.code.line(`${displayStatic(getterType)} get${propName}();`);
588
612
  }
589
613
  if (!prop.immutable) {
590
614
  const setterTypes = this.toDecoratedJavaTypes(prop);
@@ -594,18 +618,19 @@ class JavaGenerator extends generator_1.Generator {
594
618
  api: 'member',
595
619
  fqn: ifc.fqn,
596
620
  memberName: prop.name,
621
+ // Setter doesn't need a union type hint because we're generating overloads
597
622
  });
598
623
  if (prop.optional) {
599
624
  if (prop.overrides) {
600
625
  this.code.line('@Override');
601
626
  }
602
627
  this.code.line('@software.amazon.jsii.Optional');
603
- this.code.openBlock(`default void set${propName}(final ${type} value)`);
604
- this.code.line(`throw new UnsupportedOperationException("'void " + getClass().getCanonicalName() + "#set${propName}(${type})' is not implemented!");`);
628
+ this.code.openBlock(`default void set${propName}(final ${displayStatic(type)} value)`);
629
+ this.code.line(`throw new UnsupportedOperationException("'void " + getClass().getCanonicalName() + "#set${propName}(${displayStatic(type)})' is not implemented!");`);
605
630
  this.code.closeBlock();
606
631
  }
607
632
  else {
608
- this.code.line(`void set${propName}(final ${type} value);`);
633
+ this.code.line(`void set${propName}(final ${displayStatic(type)} value);`);
609
634
  }
610
635
  }
611
636
  }
@@ -937,13 +962,13 @@ class JavaGenerator extends generator_1.Generator {
937
962
  if (consts.length === 0) {
938
963
  return;
939
964
  }
940
- const javaClass = this.toJavaType(cls);
965
+ const javaClass = forceSingleType(this.toJavaTypes(cls));
941
966
  this.code.line();
942
967
  this.code.openBlock('static');
943
968
  for (const prop of consts) {
944
969
  const constName = this.renderConstName(prop);
945
- const propType = this.toNativeType(prop.type, { forMarshalling: true });
946
- const statement = `software.amazon.jsii.JsiiObject.jsiiStaticGet(${javaClass}.class, "${prop.name}", ${propType})`;
970
+ const propType = this.toNativeType(forceSingleType(this.toJavaTypes(prop.type)));
971
+ const statement = `software.amazon.jsii.JsiiObject.jsiiStaticGet(${displayStatic(javaClass)}.class, "${prop.name}", ${propType})`;
947
972
  this.code.line(`${constName} = ${this.wrapCollection(statement, prop.type, prop.optional)};`);
948
973
  }
949
974
  this.code.closeBlock();
@@ -952,7 +977,7 @@ class JavaGenerator extends generator_1.Generator {
952
977
  return this.code.toSnakeCase(prop.name).toLocaleUpperCase(); // java consts are SNAKE_UPPER_CASE
953
978
  }
954
979
  emitConstProperty(parentType, prop) {
955
- const propType = this.toJavaType(prop.type);
980
+ const propType = forceSingleType(this.toJavaTypes(prop.type));
956
981
  const propName = this.renderConstName(prop);
957
982
  const access = this.renderAccessLevel(prop);
958
983
  this.code.line();
@@ -960,15 +985,15 @@ class JavaGenerator extends generator_1.Generator {
960
985
  api: 'member',
961
986
  fqn: parentType.fqn,
962
987
  memberName: prop.name,
988
+ }, {
989
+ returnsUnion: prop.type,
963
990
  });
964
991
  this.emitStabilityAnnotations(prop);
965
- this.code.line(`${access} final static ${propType} ${propName};`);
992
+ this.code.line(`${access} final static ${displayStatic(propType)} ${propName};`);
966
993
  }
967
994
  emitProperty(cls, prop, definingType, { defaultImpl = false, final = false, includeGetter = true, overrides = !!prop.overrides, } = {}) {
968
- const getterType = this.toDecoratedJavaType(prop);
969
- const setterTypes = this.toDecoratedJavaTypes(prop, {
970
- covariant: prop.static,
971
- });
995
+ const setterTypes = this.toDecoratedJavaTypes(prop);
996
+ const getterType = forceSingleType(setterTypes);
972
997
  const propName = (0, naming_util_1.jsiiToPascalCase)(JavaGenerator.safeJavaPropertyName(prop.name));
973
998
  const modifiers = [defaultImpl ? 'default' : this.renderAccessLevel(prop)];
974
999
  if (prop.static)
@@ -977,7 +1002,7 @@ class JavaGenerator extends generator_1.Generator {
977
1002
  modifiers.push('abstract');
978
1003
  if (final && !prop.abstract && !defaultImpl)
979
1004
  modifiers.push('final');
980
- const javaClass = this.toJavaType(cls);
1005
+ const javaClass = forceSingleType(this.toJavaTypes(cls));
981
1006
  // for unions we only generate overloads for setters, not getters.
982
1007
  if (includeGetter) {
983
1008
  this.code.line();
@@ -985,12 +1010,14 @@ class JavaGenerator extends generator_1.Generator {
985
1010
  api: 'member',
986
1011
  fqn: definingType.fqn,
987
1012
  memberName: prop.name,
1013
+ }, {
1014
+ returnsUnion: prop.type,
988
1015
  });
989
1016
  if (overrides && !prop.static) {
990
1017
  this.code.line('@Override');
991
1018
  }
992
1019
  this.emitStabilityAnnotations(prop);
993
- const signature = `${modifiers.join(' ')} ${getterType} get${propName}()`;
1020
+ const signature = `${modifiers.join(' ')} ${displayStatic(getterType)} get${propName}()`;
994
1021
  if (prop.abstract && !defaultImpl) {
995
1022
  this.code.line(`${signature};`);
996
1023
  }
@@ -998,14 +1025,12 @@ class JavaGenerator extends generator_1.Generator {
998
1025
  this.code.openBlock(signature);
999
1026
  let statement;
1000
1027
  if (prop.static) {
1001
- statement = `software.amazon.jsii.JsiiObject.jsiiStaticGet(${this.toJavaType(cls)}.class, `;
1028
+ statement = `software.amazon.jsii.JsiiObject.jsiiStaticGet(${displayStatic(forceSingleType(this.toJavaTypes(cls)))}.class, `;
1002
1029
  }
1003
1030
  else {
1004
1031
  statement = 'software.amazon.jsii.Kernel.get(this, ';
1005
1032
  }
1006
- statement += `"${prop.name}", ${this.toNativeType(prop.type, {
1007
- forMarshalling: true,
1008
- })})`;
1033
+ statement += `"${prop.name}", ${this.toNativeType(forceSingleType(this.toJavaTypes(prop.type)))})`;
1009
1034
  this.code.line(`return ${this.wrapCollection(statement, prop.type, prop.optional)};`);
1010
1035
  this.code.closeBlock();
1011
1036
  }
@@ -1017,12 +1042,14 @@ class JavaGenerator extends generator_1.Generator {
1017
1042
  api: 'member',
1018
1043
  fqn: cls.fqn,
1019
1044
  memberName: prop.name,
1045
+ // No union type hint for setters
1020
1046
  });
1021
1047
  if (overrides && !prop.static) {
1022
1048
  this.code.line('@Override');
1023
1049
  }
1024
1050
  this.emitStabilityAnnotations(prop);
1025
- const signature = `${modifiers.join(' ')} void set${propName}(final ${type} value)`;
1051
+ // We could have emitted a covariant argument type here, but we didn't historically and I'm not changing that now.
1052
+ const signature = `${modifiers.join(' ')} void set${propName}(final ${displayStatic(type)} value)`;
1026
1053
  if (prop.abstract && !defaultImpl) {
1027
1054
  this.code.line(`${signature};`);
1028
1055
  }
@@ -1035,19 +1062,20 @@ class JavaGenerator extends generator_1.Generator {
1035
1062
  // This allows the compiler to do this type checking for us,
1036
1063
  // so we should not emit these checks for primitive-only unions.
1037
1064
  // Also, Java does not allow us to perform these checks if the types
1038
- // have no overlap (eg if a String instanceof Number).
1039
- if (type.includes('java.lang.Object') &&
1065
+ // have no overlap (eg if we emit code for `String instanceof Number`,
1066
+ // which will always return `false`, the compiler would reject the code).
1067
+ if (displayStatic(type).includes('java.lang.Object') &&
1040
1068
  (!spec.isPrimitiveTypeReference(prop.type) ||
1041
1069
  prop.type.primitive === spec.PrimitiveType.Any)) {
1042
- this.emitUnionParameterValdation([
1070
+ this.emitUnionParameterValidation([
1043
1071
  {
1044
1072
  name: 'value',
1045
- type: this.filterType(prop.type, { covariant: prop.static, optional: prop.optional }, type),
1073
+ type: this.filterType(prop, type),
1046
1074
  },
1047
1075
  ]);
1048
1076
  }
1049
1077
  if (prop.static) {
1050
- statement += `software.amazon.jsii.JsiiObject.jsiiStaticSet(${javaClass}.class, `;
1078
+ statement += `software.amazon.jsii.JsiiObject.jsiiStaticSet(${displayStatic(javaClass)}.class, `;
1051
1079
  }
1052
1080
  else {
1053
1081
  statement += 'software.amazon.jsii.Kernel.set(this, ';
@@ -1073,20 +1101,19 @@ class JavaGenerator extends generator_1.Generator {
1073
1101
  *
1074
1102
  * @returns a type reference that matches the provided javaType.
1075
1103
  */
1076
- filterType(ref, { covariant, optional }, javaType) {
1077
- if (!spec.isUnionTypeReference(ref)) {
1104
+ filterType(prop, javaType) {
1105
+ if (!spec.isUnionTypeReference(prop.type)) {
1078
1106
  // No filterning needed -- this isn't a type union!
1079
- return ref;
1107
+ return prop.type;
1080
1108
  }
1081
- const types = ref.union.types.filter((t) => this.toDecoratedJavaType({ optional, type: t }, { covariant }) ===
1082
- javaType);
1083
- assert(types.length > 0, `No type found in ${spec.describeTypeReference(ref)} has Java type ${javaType}`);
1109
+ const types = prop.type.union.types.filter((t) => typesEqual(forceSingleType(annotateOptional(prop, this.toJavaTypes(t))), javaType));
1110
+ assert(types.length > 0, `No type found in ${spec.describeTypeReference(prop.type)} has Java type ${displayStatic(javaType)}`);
1084
1111
  return { union: { types } };
1085
1112
  }
1086
1113
  emitMethod(cls, method, { defaultImpl = false, final = false, overrides = !!method.overrides, } = {}) {
1087
1114
  const returnType = method.returns
1088
- ? this.toDecoratedJavaType(method.returns)
1089
- : 'void';
1115
+ ? forceSingleType(this.toDecoratedJavaTypes(method.returns))
1116
+ : mkStatic('void');
1090
1117
  const modifiers = [
1091
1118
  defaultImpl ? 'default' : this.renderAccessLevel(method),
1092
1119
  ];
@@ -1098,12 +1125,15 @@ class JavaGenerator extends generator_1.Generator {
1098
1125
  modifiers.push('final');
1099
1126
  const async = !!method.async;
1100
1127
  const methodName = JavaGenerator.safeJavaMethodName(method.name);
1101
- const signature = `${returnType} ${methodName}(${this.renderMethodParameters(method)})`;
1128
+ const types = this.convertTypes(method.parameters);
1129
+ const signature = `${typeVarDeclarations(types)}${displayStatic(returnType)} ${methodName}(${this.renderParameters(method.parameters, types, method.static ? 'final' : 'overridable')})`;
1102
1130
  this.code.line();
1103
1131
  this.addJavaDocs(method, {
1104
1132
  api: 'member',
1105
1133
  fqn: cls.fqn,
1106
1134
  memberName: method.name,
1135
+ }, {
1136
+ returnsUnion: method.returns?.type,
1107
1137
  });
1108
1138
  this.emitStabilityAnnotations(method);
1109
1139
  if (overrides && !method.static) {
@@ -1114,7 +1144,7 @@ class JavaGenerator extends generator_1.Generator {
1114
1144
  }
1115
1145
  else {
1116
1146
  this.code.openBlock(`${modifiers.join(' ')} ${signature}`);
1117
- this.emitUnionParameterValdation(method.parameters);
1147
+ this.emitUnionParameterValidation(method.parameters);
1118
1148
  this.code.line(this.renderMethodCall(cls, method, async));
1119
1149
  this.code.closeBlock();
1120
1150
  }
@@ -1124,21 +1154,21 @@ class JavaGenerator extends generator_1.Generator {
1124
1154
  *
1125
1155
  * @param parameters the list of parameters received by the function.
1126
1156
  */
1127
- emitUnionParameterValdation(parameters) {
1157
+ emitUnionParameterValidation(parameters) {
1128
1158
  if (!this.runtimeTypeChecking) {
1129
1159
  // We were configured not to emit those, so bail out now.
1130
1160
  return;
1131
1161
  }
1132
- const unionParameters = parameters?.filter(({ type }) => containsUnionType(type));
1162
+ const unionParameters = parameters?.filter(({ type }) => (0, type_utils_1.containsUnionType)(type));
1133
1163
  if (unionParameters == null || unionParameters.length === 0) {
1134
1164
  return;
1135
1165
  }
1136
1166
  this.code.openBlock('if (software.amazon.jsii.Configuration.getRuntimeTypeChecking())');
1137
1167
  for (const param of unionParameters) {
1138
1168
  if (param.variadic) {
1139
- const javaType = this.toJavaType(param.type);
1169
+ const javaType = this.toSingleJavaType(param.type);
1140
1170
  const asListName = `__${param.name}__asList`;
1141
- this.code.line(`final java.util.List<${javaType}> ${asListName} = java.util.Arrays.asList(${param.name});`);
1171
+ this.code.line(`final java.util.List<${displayStatic(javaType)}> ${asListName} = java.util.Arrays.asList(${param.name});`);
1142
1172
  validate.call(this, asListName, `.append("${param.name}")`, {
1143
1173
  collection: {
1144
1174
  kind: spec.CollectionKind.Array,
@@ -1174,8 +1204,8 @@ class JavaGenerator extends generator_1.Generator {
1174
1204
  const idxName = `__idx_${suffix}`;
1175
1205
  const valName = `__val_${suffix}`;
1176
1206
  this.code.openBlock(`for (int ${idxName} = 0; ${idxName} < ${value}.size(); ${idxName}++)`);
1177
- const eltType = this.toJavaType(elementType);
1178
- this.code.line(`final ${eltType} ${valName} = ${value}.get(${idxName});`);
1207
+ const eltType = this.toSingleJavaType(elementType);
1208
+ this.code.line(`final ${displayStatic(eltType)} ${valName} = ${value}.get(${idxName});`);
1179
1209
  validate.call(this, valName, isRawArray
1180
1210
  ? `${descr}.append("[").append(${idxName}).append("]")`
1181
1211
  : `${descr}.append(".get(").append(${idxName}).append(")")`, elementType, parameterName);
@@ -1200,9 +1230,9 @@ class JavaGenerator extends generator_1.Generator {
1200
1230
  .slice(0, 6);
1201
1231
  const varName = `__item_${suffix}`;
1202
1232
  const valName = `__val_${suffix}`;
1203
- const javaElemType = this.toJavaType(elementType);
1204
- this.code.openBlock(`for (final java.util.Map.Entry<String, ${javaElemType}> ${varName}: ${value}.entrySet())`);
1205
- this.code.line(`final ${javaElemType} ${valName} = ${varName}.getValue();`);
1233
+ const javaElemType = this.toSingleJavaType(elementType);
1234
+ this.code.openBlock(`for (final java.util.Map.Entry<String, ${displayStatic(javaElemType)}> ${varName}: ${value}.entrySet())`);
1235
+ this.code.line(`final ${displayStatic(javaElemType)} ${valName} = ${varName}.getValue();`);
1206
1236
  validate.call(this, valName, `${descr}.append(".get(\\"").append((${varName}.getKey())).append("\\")")`, elementType, parameterName);
1207
1237
  this.code.closeBlock();
1208
1238
  }
@@ -1223,9 +1253,9 @@ class JavaGenerator extends generator_1.Generator {
1223
1253
  else {
1224
1254
  checked.add(javaRawType);
1225
1255
  }
1226
- const javaType = this.toJavaType(typeRef);
1227
- if (javaRawType !== javaType) {
1228
- nestedCollectionUnionTypes.set(javaType, typeRef);
1256
+ const javaType = this.toSingleJavaType(typeRef);
1257
+ if (javaRawType !== displayStatic(javaType)) {
1258
+ nestedCollectionUnionTypes.set(displayStatic(javaType), typeRef);
1229
1259
  }
1230
1260
  const test = `${value} instanceof ${javaRawType}`;
1231
1261
  if (typeRefs.length > 1) {
@@ -1244,7 +1274,7 @@ class JavaGenerator extends generator_1.Generator {
1244
1274
  this.code.openBlock(')');
1245
1275
  const placeholders = typeRefs
1246
1276
  .map((typeRef) => {
1247
- return `${this.toJavaType(typeRef)}`;
1277
+ return `${displayStatic(this.toSingleJavaType(typeRef))}`;
1248
1278
  })
1249
1279
  .join(', ');
1250
1280
  this.code.indent(`throw new IllegalArgumentException(`);
@@ -1402,6 +1432,8 @@ class JavaGenerator extends generator_1.Generator {
1402
1432
  toJavaProp(property, definingType, inherited) {
1403
1433
  const safeName = JavaGenerator.safeJavaPropertyName(property.name);
1404
1434
  const propName = (0, naming_util_1.jsiiToPascalCase)(safeName);
1435
+ const noIntersectionJavaTypes = this.toJavaTypes(removeIntersections(property.type));
1436
+ const singleJavaType = forceSingleType(noIntersectionJavaTypes);
1405
1437
  return {
1406
1438
  docs: property.docs,
1407
1439
  spec: property,
@@ -1410,13 +1442,10 @@ class JavaGenerator extends generator_1.Generator {
1410
1442
  jsiiName: property.name,
1411
1443
  nullable: !!property.optional,
1412
1444
  fieldName: this.code.toCamelCase(safeName),
1413
- fieldJavaType: this.toJavaType(property.type),
1414
- paramJavaType: this.toJavaType(property.type, { covariant: true }),
1415
- fieldNativeType: this.toNativeType(property.type),
1416
- fieldJavaClass: `${this.toJavaType(property.type, {
1417
- forMarshalling: true,
1418
- })}.class`,
1419
- javaTypes: this.toJavaTypes(property.type, { covariant: true }),
1445
+ renderedFieldType: displayStatic(singleJavaType),
1446
+ renderedParamType: displayType(singleJavaType, 'covariant'),
1447
+ renderedNativeFieldType: this.toNativeType(singleJavaType),
1448
+ javaTypes: this.toJavaTypes(property.type),
1420
1449
  immutable: property.immutable ?? false,
1421
1450
  inherited,
1422
1451
  };
@@ -1449,22 +1478,22 @@ class JavaGenerator extends generator_1.Generator {
1449
1478
  }
1450
1479
  const structType = this.reflectAssembly.findType(firstStruct.type.fqn);
1451
1480
  const structParamName = this.code.toCamelCase(JavaGenerator.safeJavaPropertyName(firstStruct.name));
1452
- const structBuilder = `${this.toJavaType(firstStruct.type)}.${BUILDER_CLASS_NAME}`;
1481
+ const structBuilder = `${displayStatic(this.toSingleJavaType(firstStruct.type))}.${BUILDER_CLASS_NAME}`;
1453
1482
  const positionalParams = cls.initializer.parameters
1454
1483
  .filter((p) => p !== firstStruct)
1455
1484
  .map((param) => ({
1456
1485
  param,
1457
1486
  fieldName: this.code.toCamelCase(JavaGenerator.safeJavaPropertyName(param.name)),
1458
- javaType: this.toJavaType(param.type),
1487
+ javaType: this.toSingleJavaType(param.type),
1459
1488
  }));
1460
- const builtType = this.toJavaType(cls);
1489
+ const builtType = this.toSingleJavaType(cls);
1461
1490
  this.code.line();
1462
1491
  this.code.line('/**');
1463
1492
  // eslint-disable-next-line prettier/prettier
1464
- this.code.line(` * ${(0, _utils_1.stabilityPrefixFor)(cls.initializer)}A fluent builder for {@link ${builtType}}.`);
1493
+ this.code.line(` * ${(0, _utils_1.stabilityPrefixFor)(cls.initializer)}A fluent builder for {@link ${displayStatic(builtType)}}.`);
1465
1494
  this.code.line(' */');
1466
1495
  this.emitStabilityAnnotations(cls.initializer);
1467
- this.code.openBlock(`public static final class ${BUILDER_CLASS_NAME} implements software.amazon.jsii.Builder<${builtType}>`);
1496
+ this.code.openBlock(`public static final class ${BUILDER_CLASS_NAME} implements software.amazon.jsii.Builder<${displayStatic(builtType)}>`);
1468
1497
  // Static factory method(s)
1469
1498
  for (const params of computeOverrides(positionalParams)) {
1470
1499
  const dummyMethod = {
@@ -1482,7 +1511,7 @@ class JavaGenerator extends generator_1.Generator {
1482
1511
  });
1483
1512
  this.emitStabilityAnnotations(cls.initializer);
1484
1513
  this.code.openBlock(`public static ${BUILDER_CLASS_NAME} create(${params
1485
- .map((param) => `final ${param.javaType}${param.param.variadic ? '...' : ''} ${param.fieldName}`)
1514
+ .map((param) => `final ${displayStatic(param.javaType)}${param.param.variadic ? '...' : ''} ${param.fieldName}`)
1486
1515
  .join(', ')})`);
1487
1516
  this.code.line(`return new ${BUILDER_CLASS_NAME}(${positionalParams
1488
1517
  .map((param, idx) => (idx < params.length ? param.fieldName : 'null'))
@@ -1492,13 +1521,13 @@ class JavaGenerator extends generator_1.Generator {
1492
1521
  // Private properties
1493
1522
  this.code.line();
1494
1523
  for (const param of positionalParams) {
1495
- this.code.line(`private final ${param.javaType}${param.param.variadic ? '[]' : ''} ${param.fieldName};`);
1524
+ this.code.line(`private final ${displayStatic(param.javaType)}${param.param.variadic ? '[]' : ''} ${param.fieldName};`);
1496
1525
  }
1497
1526
  this.code.line(`private ${firstStruct.optional ? '' : 'final '}${structBuilder} ${structParamName};`);
1498
1527
  // Private constructor
1499
1528
  this.code.line();
1500
1529
  this.code.openBlock(`private ${BUILDER_CLASS_NAME}(${positionalParams
1501
- .map((param) => `final ${param.javaType}${param.param.variadic ? '...' : ''} ${param.fieldName}`)
1530
+ .map((param) => `final ${displayStatic(param.javaType)}${param.param.variadic ? '...' : ''} ${param.fieldName}`)
1502
1531
  .join(', ')})`);
1503
1532
  for (const param of positionalParams) {
1504
1533
  this.code.line(`this.${param.fieldName} = ${param.fieldName};`);
@@ -1526,16 +1555,14 @@ class JavaGenerator extends generator_1.Generator {
1526
1555
  },
1527
1556
  ],
1528
1557
  };
1529
- for (const javaType of this.toJavaTypes(prop.type.spec, {
1530
- covariant: true,
1531
- })) {
1558
+ for (const javaType of this.toJavaTypes(prop.type.spec)) {
1532
1559
  this.addJavaDocs(setter, {
1533
1560
  api: 'member',
1534
1561
  fqn: prop.definingType.fqn, // Could be inherited
1535
1562
  memberName: prop.name,
1536
1563
  });
1537
1564
  this.emitStabilityAnnotations(prop.spec);
1538
- this.code.openBlock(`public ${BUILDER_CLASS_NAME} ${fieldName}(final ${javaType} ${fieldName})`);
1565
+ this.code.openBlock(`public ${BUILDER_CLASS_NAME} ${fieldName}(final ${displayType(javaType, 'covariant')} ${fieldName})`);
1539
1566
  this.code.line(`this.${structParamName}${firstStruct.optional ? '()' : ''}.${fieldName}(${fieldName});`);
1540
1567
  this.code.line('return this;');
1541
1568
  this.code.closeBlock();
@@ -1544,11 +1571,11 @@ class JavaGenerator extends generator_1.Generator {
1544
1571
  // Final build method
1545
1572
  this.code.line();
1546
1573
  this.code.line('/**');
1547
- this.code.line(` * @return a newly built instance of {@link ${builtType}}.`);
1574
+ this.code.line(` * @return a newly built instance of {@link ${displayStatic(builtType)}}.`);
1548
1575
  this.code.line(' */');
1549
1576
  this.emitStabilityAnnotations(cls.initializer);
1550
1577
  this.code.line('@Override');
1551
- this.code.openBlock(`public ${builtType} build()`);
1578
+ this.code.openBlock(`public ${displayStatic(builtType)} build()`);
1552
1579
  const params = cls.initializer.parameters.map((param) => {
1553
1580
  if (param === firstStruct) {
1554
1581
  return firstStruct.optional
@@ -1557,7 +1584,7 @@ class JavaGenerator extends generator_1.Generator {
1557
1584
  }
1558
1585
  return `this.${positionalParams.find((p) => param === p.param).fieldName}`;
1559
1586
  });
1560
- this.code.indent(`return new ${builtType}(`);
1587
+ this.code.indent(`return new ${displayStatic(builtType)}(`);
1561
1588
  params.forEach((param, idx) => this.code.line(`${param}${idx < params.length - 1 ? ',' : ''}`));
1562
1589
  this.code.unindent(');');
1563
1590
  this.code.closeBlock();
@@ -1579,7 +1606,7 @@ class JavaGenerator extends generator_1.Generator {
1579
1606
  this.code.line('/**');
1580
1607
  this.code.line(` * Sets the value of {@link ${parentType.name}#${getterFor(prop.fieldName)}}`);
1581
1608
  const summary = prop.docs?.summary ?? 'the value to be set';
1582
- this.code.line(` * ${paramJavadoc(prop.fieldName, prop.nullable, summary)}`);
1609
+ this.code.line(` * ${this.paramJavadoc(prop.fieldName, prop.nullable, summary)}`);
1583
1610
  if (prop.docs?.remarks != null) {
1584
1611
  const indent = ' '.repeat(7 + prop.fieldName.length);
1585
1612
  const remarks = myMarkDownToJavaDoc(this.convertSamplesInMarkdown(prop.docs.remarks, {
@@ -1597,17 +1624,18 @@ class JavaGenerator extends generator_1.Generator {
1597
1624
  }
1598
1625
  this.code.line(' */');
1599
1626
  this.emitStabilityAnnotations(prop.spec);
1627
+ const renderedType = displayType(type, 'covariant');
1600
1628
  // We add an explicit cast if both types are generic but they are not identical (one is covariant, the other isn't)
1601
- const explicitCast = type.includes('<') &&
1602
- prop.fieldJavaType.includes('<') &&
1603
- type !== prop.fieldJavaType
1604
- ? `(${prop.fieldJavaType})`
1629
+ const explicitCast = renderedType.includes('<') &&
1630
+ prop.renderedFieldType.includes('<') &&
1631
+ renderedType !== prop.renderedFieldType
1632
+ ? `(${prop.renderedFieldType})`
1605
1633
  : '';
1606
1634
  if (explicitCast !== '') {
1607
1635
  // We'll be doing a safe, but unchecked cast, so suppress that warning
1608
1636
  this.code.line('@SuppressWarnings("unchecked")');
1609
1637
  }
1610
- this.code.openBlock(`public ${builderName} ${prop.fieldName}(${type} ${prop.fieldName})`);
1638
+ this.code.openBlock(`public ${typeVarDeclarations([type])}${builderName} ${prop.fieldName}(${renderedType} ${prop.fieldName})`);
1611
1639
  this.code.line(`this.${prop.fieldName} = ${explicitCast}${prop.fieldName};`);
1612
1640
  this.code.line('return this;');
1613
1641
  this.code.closeBlock();
@@ -1634,7 +1662,7 @@ class JavaGenerator extends generator_1.Generator {
1634
1662
  this.code.line(' */');
1635
1663
  this.emitStabilityAnnotations(classSpec);
1636
1664
  this.code.openBlock(`public static final class ${BUILDER_CLASS_NAME} implements software.amazon.jsii.Builder<${classSpec.name}>`);
1637
- props.forEach((prop) => this.code.line(`${prop.fieldJavaType} ${prop.fieldName};`));
1665
+ props.forEach((prop) => this.code.line(`${prop.renderedFieldType} ${prop.fieldName};`));
1638
1666
  props.forEach((prop) => this.emitBuilderSetter(prop, BUILDER_CLASS_NAME, classSpec));
1639
1667
  // Start build()
1640
1668
  this.code.line();
@@ -1679,7 +1707,7 @@ class JavaGenerator extends generator_1.Generator {
1679
1707
  this.code.line(ANN_INTERNAL);
1680
1708
  this.code.openBlock(`final class ${INTERFACE_PROXY_CLASS_NAME} extends software.amazon.jsii.JsiiObject implements ${ifc.name}`);
1681
1709
  // Immutable properties
1682
- props.forEach((prop) => this.code.line(`private final ${prop.fieldJavaType} ${prop.fieldName};`));
1710
+ props.forEach((prop) => this.code.line(`private final ${prop.renderedFieldType} ${prop.fieldName};`));
1683
1711
  // Start JSII reference constructor
1684
1712
  this.code.line();
1685
1713
  this.code.line('/**');
@@ -1688,7 +1716,7 @@ class JavaGenerator extends generator_1.Generator {
1688
1716
  this.code.line(' */');
1689
1717
  this.code.openBlock(`protected ${INTERFACE_PROXY_CLASS_NAME}(final software.amazon.jsii.JsiiObjectRef objRef)`);
1690
1718
  this.code.line('super(objRef);');
1691
- props.forEach((prop) => this.code.line(`this.${prop.fieldName} = software.amazon.jsii.Kernel.get(this, "${prop.jsiiName}", ${prop.fieldNativeType});`));
1719
+ props.forEach((prop) => this.code.line(`this.${prop.fieldName} = software.amazon.jsii.Kernel.get(this, "${prop.jsiiName}", ${prop.renderedNativeFieldType});`));
1692
1720
  this.code.closeBlock();
1693
1721
  // End JSII reference constructor
1694
1722
  // Start builder constructor
@@ -1696,14 +1724,14 @@ class JavaGenerator extends generator_1.Generator {
1696
1724
  this.code.line('/**');
1697
1725
  this.code.line(' * Constructor that initializes the object based on literal property values passed by the {@link Builder}.');
1698
1726
  this.code.line(' */');
1699
- if (props.some((prop) => prop.fieldJavaType !== prop.paramJavaType)) {
1727
+ if (props.some((prop) => prop.renderedFieldType !== prop.renderedParamType)) {
1700
1728
  this.code.line('@SuppressWarnings("unchecked")');
1701
1729
  }
1702
1730
  this.code.openBlock(`protected ${INTERFACE_PROXY_CLASS_NAME}(final ${BUILDER_CLASS_NAME} builder)`);
1703
1731
  this.code.line('super(software.amazon.jsii.JsiiObject.InitializationMode.JSII);');
1704
1732
  props.forEach((prop) => {
1705
- const explicitCast = prop.fieldJavaType !== prop.paramJavaType
1706
- ? `(${prop.fieldJavaType})`
1733
+ const explicitCast = prop.renderedFieldType !== prop.renderedParamType
1734
+ ? `(${prop.renderedFieldType})`
1707
1735
  : '';
1708
1736
  this.code.line(`this.${prop.fieldName} = ${explicitCast}${_validateIfNonOptional(`builder.${prop.fieldName}`, prop)};`);
1709
1737
  });
@@ -1713,7 +1741,7 @@ class JavaGenerator extends generator_1.Generator {
1713
1741
  props.forEach((prop) => {
1714
1742
  this.code.line();
1715
1743
  this.code.line('@Override');
1716
- this.code.openBlock(`public final ${prop.fieldJavaType} get${prop.propName}()`);
1744
+ this.code.openBlock(`public final ${prop.renderedFieldType} get${prop.propName}()`);
1717
1745
  this.code.line(`return this.${prop.fieldName};`);
1718
1746
  this.code.closeBlock();
1719
1747
  });
@@ -1854,8 +1882,11 @@ class JavaGenerator extends generator_1.Generator {
1854
1882
  return { filePath, name };
1855
1883
  }
1856
1884
  // eslint-disable-next-line complexity
1857
- addJavaDocs(doc, apiLoc, defaultText) {
1858
- if (!defaultText &&
1885
+ addJavaDocs(doc, apiLoc, unionHint) {
1886
+ const returnsUnion = unionHint?.returnsUnion && (0, type_utils_1.containsUnionType)(unionHint.returnsUnion)
1887
+ ? this.renderTypeReference(unionHint.returnsUnion)
1888
+ : undefined;
1889
+ if (!returnsUnion &&
1859
1890
  Object.keys(doc.docs ?? {}).length === 0 &&
1860
1891
  !(doc.parameters ?? []).some((p) => Object.keys(p.docs ?? {}).length !== 0)) {
1861
1892
  return;
@@ -1865,12 +1896,12 @@ class JavaGenerator extends generator_1.Generator {
1865
1896
  if (docs.summary) {
1866
1897
  paras.push(stripNewLines(myMarkDownToJavaDoc((0, _utils_1.renderSummary)(docs))));
1867
1898
  }
1868
- else if (defaultText) {
1869
- paras.push(myMarkDownToJavaDoc(defaultText));
1870
- }
1871
1899
  if (docs.remarks) {
1872
1900
  paras.push(myMarkDownToJavaDoc(this.convertSamplesInMarkdown(docs.remarks, apiLoc)).trimRight());
1873
1901
  }
1902
+ if (returnsUnion) {
1903
+ paras.push(`Returns union: ${returnsUnion}`);
1904
+ }
1874
1905
  if (docs.default) {
1875
1906
  paras.push(`Default: ${docs.default}`); // NOTE: there is no annotation in JavaDoc for this
1876
1907
  }
@@ -1906,7 +1937,7 @@ class JavaGenerator extends generator_1.Generator {
1906
1937
  if (method.parameters) {
1907
1938
  for (const param of method.parameters) {
1908
1939
  const summary = param.docs?.summary;
1909
- tagLines.push(paramJavadoc(param.name, param.optional, summary));
1940
+ tagLines.push(this.paramJavadoc(param.name, param.optional, summary, param.type));
1910
1941
  }
1911
1942
  }
1912
1943
  }
@@ -1926,134 +1957,150 @@ class JavaGenerator extends generator_1.Generator {
1926
1957
  }
1927
1958
  this.code.line(' */');
1928
1959
  }
1960
+ paramJavadoc(name, optional, summary, unionTypeHint) {
1961
+ const parts = ['@param', name];
1962
+ if (summary) {
1963
+ parts.push(stripNewLines(myMarkDownToJavaDoc(endWithPeriod(summary))));
1964
+ }
1965
+ if (unionTypeHint && (0, type_utils_1.containsUnionType)(unionTypeHint)) {
1966
+ parts.push(`Takes union: ${this.renderTypeReference(unionTypeHint)}.`);
1967
+ }
1968
+ if (!optional) {
1969
+ parts.push('This parameter is required.');
1970
+ }
1971
+ return parts.join(' ');
1972
+ }
1929
1973
  getClassBase(cls) {
1930
1974
  if (!cls.base) {
1931
- return 'software.amazon.jsii.JsiiObject';
1975
+ return mkStatic('software.amazon.jsii.JsiiObject');
1932
1976
  }
1933
- return this.toJavaType({ fqn: cls.base });
1977
+ return this.toJavaTypes({ fqn: cls.base })[0];
1934
1978
  }
1935
- toDecoratedJavaType(optionalValue, { covariant = false } = {}) {
1936
- const result = this.toDecoratedJavaTypes(optionalValue, { covariant });
1937
- if (result.length > 1) {
1938
- return `${optionalValue.optional ? ANN_NULLABLE : ANN_NOT_NULL} java.lang.Object`;
1939
- }
1940
- return result[0];
1979
+ /**
1980
+ * Convert an OptionalValue, adding the `NotNull` or `Nullable` declarations as appropriate
1981
+ */
1982
+ toDecoratedJavaTypes(optionalValue) {
1983
+ return annotateOptional(optionalValue, this.toJavaTypes(optionalValue.type));
1941
1984
  }
1942
- toDecoratedJavaTypes(optionalValue, { covariant = false } = {}) {
1943
- return this.toJavaTypes(optionalValue.type, { covariant }).map((nakedType) => `${optionalValue.optional ? ANN_NULLABLE : ANN_NOT_NULL} ${nakedType}`);
1985
+ /**
1986
+ * Renders a type without generic arguments
1987
+ *
1988
+ * Necessary because of type erasure; the compiler
1989
+ * will not let you check `foo instanceof Map<String, Foo>`,
1990
+ * and you must instead check `foo instanceof Map`.
1991
+ */
1992
+ toJavaTypeNoGenerics(type) {
1993
+ return forceSingleType(this.toJavaTypes(type)).typeSymbol;
1944
1994
  }
1945
- // Strips <*> from the type name.
1946
- // necessary, because of type erasure; the compiler
1947
- // will not let you check `foo instanceof Map<String, Foo>`,
1948
- // and you must instead check `foo instanceof Map`.
1949
- toJavaTypeNoGenerics(type, opts) {
1950
- const typeStr = this.toJavaType(type, opts);
1951
- const leftAngleBracketIdx = typeStr.indexOf('<');
1952
- const rightAngleBracketIdx = typeStr.indexOf('>');
1953
- if ((leftAngleBracketIdx < 0 && rightAngleBracketIdx >= 0) ||
1954
- (leftAngleBracketIdx >= 0 && rightAngleBracketIdx < 0)) {
1955
- throw new Error(`Invalid generic type: found ${typeStr}`);
1995
+ /**
1996
+ * Return the jsii object that represents this native type
1997
+ */
1998
+ toNativeType(type) {
1999
+ if (type.type === 'static' && type.typeSymbol === 'java.util.List') {
2000
+ const nativeElementType = this.toNativeType(type.typeArguments[0]);
2001
+ return `software.amazon.jsii.NativeType.listOf(${nativeElementType})`;
1956
2002
  }
1957
- return leftAngleBracketIdx > 0 && rightAngleBracketIdx > 0
1958
- ? typeStr.slice(0, leftAngleBracketIdx)
1959
- : typeStr;
1960
- }
1961
- toJavaType(type, opts) {
1962
- const types = this.toJavaTypes(type, opts);
1963
- if (types.length > 1) {
1964
- return 'java.lang.Object';
2003
+ if (type.type === 'static' && type.typeSymbol === 'java.util.Map') {
2004
+ const nativeElementType = this.toNativeType(type.typeArguments[1]);
2005
+ return `software.amazon.jsii.NativeType.mapOf(${nativeElementType})`;
1965
2006
  }
1966
- return types[0];
2007
+ return `software.amazon.jsii.NativeType.forClass(${marshallingType(type)})`;
1967
2008
  }
1968
- toNativeType(type, { forMarshalling = false, covariant = false } = {}) {
1969
- if (spec.isCollectionTypeReference(type)) {
1970
- const nativeElementType = this.toNativeType(type.collection.elementtype, {
1971
- forMarshalling,
1972
- covariant,
1973
- });
1974
- switch (type.collection.kind) {
1975
- case spec.CollectionKind.Array:
1976
- return `software.amazon.jsii.NativeType.listOf(${nativeElementType})`;
1977
- case spec.CollectionKind.Map:
1978
- return `software.amazon.jsii.NativeType.mapOf(${nativeElementType})`;
1979
- default:
1980
- throw new Error(`Unsupported collection kind: ${type.collection.kind}`);
1981
- }
1982
- }
1983
- return `software.amazon.jsii.NativeType.forClass(${this.toJavaType(type, {
1984
- forMarshalling,
1985
- covariant,
1986
- })}.class)`;
2009
+ /**
2010
+ * Convert a jsii type to a single Java type, collapsing to object if necessary
2011
+ */
2012
+ toSingleJavaType(typeref, { typeSymGen = undefined } = {}) {
2013
+ return forceSingleType(this.toJavaTypes(typeref, { typeSymGen }));
1987
2014
  }
1988
- toJavaTypes(typeref, { forMarshalling = false, covariant = false } = {}) {
2015
+ /**
2016
+ * Convert a jsii type to a union of Java types
2017
+ */
2018
+ toJavaTypes(typeref, { typeSymGen = undefined } = {}) {
2019
+ typeSymGen = typeSymGen ?? newTypeSymGen();
1989
2020
  if (spec.isPrimitiveTypeReference(typeref)) {
1990
2021
  return [this.toJavaPrimitive(typeref.primitive)];
1991
2022
  }
1992
2023
  else if (spec.isCollectionTypeReference(typeref)) {
1993
- return [this.toJavaCollection(typeref, { forMarshalling, covariant })];
2024
+ return [
2025
+ this.toJavaCollection(typeref, {
2026
+ typeSymGen,
2027
+ }),
2028
+ ];
1994
2029
  }
1995
2030
  else if (spec.isNamedTypeReference(typeref)) {
1996
- return [this.toNativeFqn(typeref.fqn)];
1997
- }
1998
- else if (typeref.union) {
1999
- const types = new Array();
2000
- for (const subtype of typeref.union.types) {
2001
- for (const t of this.toJavaTypes(subtype, {
2002
- forMarshalling,
2003
- covariant,
2004
- })) {
2005
- types.push(t);
2006
- }
2007
- }
2008
- return types;
2009
- }
2010
- throw new Error(`Invalid type reference: ${JSON.stringify(typeref)}`);
2011
- }
2012
- toJavaCollection(ref, { forMarshalling, covariant, }) {
2013
- const elementJavaType = this.toJavaType(ref.collection.elementtype, {
2014
- covariant,
2031
+ const literal = (0, type_literals_1.literalTypeReference)(typeref);
2032
+ return literal
2033
+ ? [mkStatic(literal)]
2034
+ : [mkStatic(this.toNativeFqn(typeref.fqn))];
2035
+ }
2036
+ else if (spec.isUnionTypeReference(typeref)) {
2037
+ return typeref.union.types.flatMap((subtype) => this.toJavaTypes(subtype, { typeSymGen }));
2038
+ }
2039
+ else if (spec.isIntersectionTypeReference(typeref)) {
2040
+ const typeVariable = typeSymGen();
2041
+ return [
2042
+ mkParam(typeVariable, `${typeVariable} extends ${typeref.intersection.types
2043
+ // Take the first type of any given union (an intersect-of-union
2044
+ // would have been rejected by jsii-compiler anyway)
2045
+ .map((t) => displayStatic(this.toJavaTypes(t)[0]))
2046
+ .join(' & ')}`),
2047
+ ];
2048
+ }
2049
+ throw new Error(`Unrenderable type reference: ${JSON.stringify(typeref)}`);
2050
+ }
2051
+ toJavaCollection(ref, { typeSymGen }) {
2052
+ const elementJavaType = this.toSingleJavaType(ref.collection.elementtype, {
2053
+ typeSymGen,
2015
2054
  });
2016
- const typeConstraint = covariant
2017
- ? makeCovariant(elementJavaType)
2018
- : elementJavaType;
2019
2055
  switch (ref.collection.kind) {
2020
2056
  case spec.CollectionKind.Array:
2021
- return forMarshalling
2022
- ? 'java.util.List'
2023
- : `java.util.List<${typeConstraint}>`;
2057
+ return mkStatic('java.util.List', [elementJavaType]);
2024
2058
  case spec.CollectionKind.Map:
2025
- return forMarshalling
2026
- ? 'java.util.Map'
2027
- : `java.util.Map<java.lang.String, ${typeConstraint}>`;
2059
+ return mkStatic('java.util.Map', [
2060
+ mkStatic('java.lang.String'),
2061
+ elementJavaType,
2062
+ ]);
2028
2063
  default:
2029
2064
  throw new Error(`Unsupported collection kind: ${ref.collection.kind}`);
2030
2065
  }
2031
- function makeCovariant(javaType) {
2032
- // Don't emit a covariant expression for String (it's `final` in Java)
2033
- if (javaType === 'java.lang.String') {
2034
- return javaType;
2035
- }
2036
- return `? extends ${javaType}`;
2037
- }
2038
2066
  }
2039
2067
  toJavaPrimitive(primitive) {
2040
2068
  switch (primitive) {
2041
2069
  case spec.PrimitiveType.Boolean:
2042
- return 'java.lang.Boolean';
2070
+ return mkStatic('java.lang.Boolean');
2043
2071
  case spec.PrimitiveType.Date:
2044
- return 'java.time.Instant';
2072
+ return mkStatic('java.time.Instant');
2045
2073
  case spec.PrimitiveType.Json:
2046
- return 'com.fasterxml.jackson.databind.node.ObjectNode';
2074
+ return mkStatic('com.fasterxml.jackson.databind.node.ObjectNode');
2047
2075
  case spec.PrimitiveType.Number:
2048
- return 'java.lang.Number';
2076
+ return mkStatic('java.lang.Number');
2049
2077
  case spec.PrimitiveType.String:
2050
- return 'java.lang.String';
2078
+ return mkStatic('java.lang.String');
2051
2079
  case spec.PrimitiveType.Any:
2052
- return 'java.lang.Object';
2080
+ return mkStatic('java.lang.Object');
2053
2081
  default:
2054
2082
  throw new Error(`Unknown primitive type: ${primitive}`);
2055
2083
  }
2056
2084
  }
2085
+ /**
2086
+ * Render a type reference to something human readable for use in JavaDocs
2087
+ */
2088
+ renderTypeReference(x) {
2089
+ return (0, type_visitor_1.visitTypeReference)(x, {
2090
+ primitive: (x) => `{@link ${this.toJavaPrimitive(x.primitive).typeSymbol}}`,
2091
+ named: (x) => `{@link ${this.toNativeFqn(x.fqn)}}`,
2092
+ collection: (x) => {
2093
+ switch (x.collection.kind) {
2094
+ case spec.CollectionKind.Array:
2095
+ return `List<${this.renderTypeReference(x.collection.elementtype)}>`;
2096
+ case spec.CollectionKind.Map:
2097
+ return `Map<String, ${this.renderTypeReference(x.collection.elementtype)}>`;
2098
+ }
2099
+ },
2100
+ union: (x) => `either ${x.union.types.map((x) => this.renderTypeReference(x)).join(' or ')}`,
2101
+ intersection: (x) => `${x.intersection.types.map((x) => this.renderTypeReference(x)).join(' + ')}`,
2102
+ });
2103
+ }
2057
2104
  renderMethodCallArguments(method) {
2058
2105
  if (!method.parameters || method.parameters.length === 0) {
2059
2106
  return '';
@@ -2081,17 +2128,16 @@ class JavaGenerator extends generator_1.Generator {
2081
2128
  renderMethodCall(cls, method, async) {
2082
2129
  let statement = '';
2083
2130
  if (method.static) {
2084
- const javaClass = this.toJavaType(cls);
2085
- statement += `software.amazon.jsii.JsiiObject.jsiiStaticCall(${javaClass}.class, `;
2131
+ const javaClass = this.toSingleJavaType(cls);
2132
+ statement += `software.amazon.jsii.JsiiObject.jsiiStaticCall(${displayStatic(javaClass)}.class, `;
2086
2133
  }
2087
2134
  else {
2088
2135
  statement += `software.amazon.jsii.Kernel.${async ? 'asyncCall' : 'call'}(this, `;
2089
2136
  }
2090
2137
  statement += `"${method.name}"`;
2091
2138
  if (method.returns) {
2092
- statement += `, ${this.toNativeType(method.returns.type, {
2093
- forMarshalling: true,
2094
- })}`;
2139
+ const returnsType = forceSingleType(this.toJavaTypes(method.returns.type));
2140
+ statement += `, ${this.toNativeType(returnsType)}`;
2095
2141
  }
2096
2142
  else {
2097
2143
  statement += ', software.amazon.jsii.NativeType.VOID';
@@ -2127,20 +2173,28 @@ class JavaGenerator extends generator_1.Generator {
2127
2173
  }
2128
2174
  // In the case of "optional", the value needs ot be explicitly cast to allow for cases where the raw type was returned.
2129
2175
  return optional
2130
- ? `java.util.Optional.ofNullable((${this.toJavaType(type)})(${statement})).map(java.util.Collections::${wrapper}).orElse(null)`
2176
+ ? `java.util.Optional.ofNullable((${displayStatic(this.toSingleJavaType(type))})(${statement})).map(java.util.Collections::${wrapper}).orElse(null)`
2131
2177
  : `java.util.Collections.${wrapper}(${statement})`;
2132
2178
  }
2133
2179
  return statement;
2134
2180
  }
2135
- renderMethodParameters(method) {
2181
+ convertTypes(parameters) {
2182
+ return (parameters ?? []).map((p) => {
2183
+ return forceSingleType(this.toDecoratedJavaTypes(p));
2184
+ });
2185
+ }
2186
+ renderParameters(parameters, types, overridable) {
2187
+ parameters = parameters ?? [];
2188
+ if (parameters.length !== types.length) {
2189
+ throw new Error(`Arrays not same length: ${parameters.length} !== ${types.length}`);
2190
+ }
2191
+ // We can render covariant parameters only for methods that aren't overridable... so only for static methods currently.
2192
+ // (There are some more places where we could do this, like properties and constructors, but historically we didn't
2193
+ // and I don't want to mess with this too much because the risk/reward isn't there.)
2194
+ const cov = overridable === 'final' ? 'covariant' : undefined;
2136
2195
  const params = [];
2137
- if (method.parameters) {
2138
- for (const p of method.parameters) {
2139
- // We can render covariant parameters only for methods that aren't overridable... so only for static methods currently.
2140
- params.push(`final ${this.toDecoratedJavaType(p, {
2141
- covariant: method.static,
2142
- })}${p.variadic ? '...' : ''} ${JavaGenerator.safeJavaPropertyName(p.name)}`);
2143
- }
2196
+ for (const [p, type] of (0, util_1.zip)(parameters, types)) {
2197
+ params.push(`final ${displayType(type, cov)}${p.variadic ? '...' : ''} ${JavaGenerator.safeJavaPropertyName(p.name)}`);
2144
2198
  }
2145
2199
  return params.join(', ');
2146
2200
  }
@@ -2321,10 +2375,12 @@ class JavaGenerator extends generator_1.Generator {
2321
2375
  this.code.line(`@javax.annotation.Generated(value = "${generator}"${date})`);
2322
2376
  }
2323
2377
  convertExample(example, api) {
2378
+ (0, rosetta_assembly_1.assertSpecIsRosettaCompatible)(this.assembly);
2324
2379
  const translated = this.rosetta.translateExample(api, example, jsii_rosetta_1.TargetLanguage.JAVA, (0, jsii_rosetta_1.enforcesStrictMode)(this.assembly));
2325
2380
  return translated.source;
2326
2381
  }
2327
2382
  convertSamplesInMarkdown(markdown, api) {
2383
+ (0, rosetta_assembly_1.assertSpecIsRosettaCompatible)(this.assembly);
2328
2384
  return this.rosetta.translateSnippetsInMarkdown(api, markdown, jsii_rosetta_1.TargetLanguage.JAVA, (0, jsii_rosetta_1.enforcesStrictMode)(this.assembly));
2329
2385
  }
2330
2386
  /**
@@ -2448,16 +2504,6 @@ function isNullable(optionalValue) {
2448
2504
  (spec.isPrimitiveTypeReference(optionalValue.type) &&
2449
2505
  optionalValue.type.primitive === spec.PrimitiveType.Any));
2450
2506
  }
2451
- function paramJavadoc(name, optional, summary) {
2452
- const parts = ['@param', name];
2453
- if (summary) {
2454
- parts.push(stripNewLines(myMarkDownToJavaDoc(endWithPeriod(summary))));
2455
- }
2456
- if (!optional) {
2457
- parts.push('This parameter is required.');
2458
- }
2459
- return parts.join(' ');
2460
- }
2461
2507
  function endWithPeriod(s) {
2462
2508
  s = s.trimRight();
2463
2509
  if (!s.endsWith('.')) {
@@ -2599,11 +2645,6 @@ function splitNamespace(ns) {
2599
2645
  function escape(s) {
2600
2646
  return s.replace(/["\\<>&]/g, (c) => `&#${c.charCodeAt(0)};`);
2601
2647
  }
2602
- function containsUnionType(typeRef) {
2603
- return (spec.isUnionTypeReference(typeRef) ||
2604
- (spec.isCollectionTypeReference(typeRef) &&
2605
- containsUnionType(typeRef.collection.elementtype)));
2606
- }
2607
2648
  function myMarkDownToJavaDoc(source) {
2608
2649
  if (source.includes('{@link') || source.includes('{@code')) {
2609
2650
  // Slightly dirty hack: if we are seeing this, it means the docstring was provided literally
@@ -2622,4 +2663,155 @@ function stripNewLines(x) {
2622
2663
  function escapeEndingComment(x) {
2623
2664
  return x.replace(/\*\//g, '*\\/');
2624
2665
  }
2666
+ function newTypeSymGen() {
2667
+ let cnt = 1;
2668
+ return () => {
2669
+ return `T${cnt++}`;
2670
+ };
2671
+ }
2672
+ function mkStatic(typeSymbol, typeArguments = []) {
2673
+ return { typeSymbol, annotation: '', type: 'static', typeArguments };
2674
+ }
2675
+ function mkParam(typeVariable, typeVarDeclaration) {
2676
+ return {
2677
+ type: 'param',
2678
+ annotation: '',
2679
+ typeSymbol: typeVariable,
2680
+ typeVariable,
2681
+ typeVarDeclaration,
2682
+ };
2683
+ }
2684
+ function displayStatic(x, options) {
2685
+ if (x.type !== 'static') {
2686
+ throw new Error(`Expected static type here, got ${JSON.stringify(x)}`);
2687
+ }
2688
+ return displayType(x, options);
2689
+ }
2690
+ function displayType(x, options) {
2691
+ switch (x.type) {
2692
+ case 'param':
2693
+ return `${x.annotation}${x.typeSymbol}`;
2694
+ case 'static':
2695
+ return [
2696
+ `${x.annotation}${x.typeSymbol}`,
2697
+ (x.typeArguments ?? []).length > 0
2698
+ ? `<${x
2699
+ .typeArguments.map((t, i) => {
2700
+ const subT = displayType(t, options);
2701
+ // For Map<K, V> we only want to make V covariant.
2702
+ // Since that's and List<T> are the only types we have generics
2703
+ // for anyway, we hack it here (as opposed to storing a field on
2704
+ // the type object itself). This is simpler and Good Enough For Now(tm).
2705
+ const isLastParameter = i === (x.typeArguments ?? []).length - 1;
2706
+ // Don't emit a covariant expression for String (it's `final` in Java)
2707
+ const isString = subT === 'java.lang.String';
2708
+ return options === 'covariant' && isLastParameter && !isString
2709
+ ? `? extends ${subT}`
2710
+ : subT;
2711
+ })
2712
+ .join(', ')}>`
2713
+ : '',
2714
+ ].join('');
2715
+ }
2716
+ }
2717
+ function typeVarDeclarations(types) {
2718
+ const ret = [];
2719
+ for (const t of types) {
2720
+ recurse(t);
2721
+ }
2722
+ return ret.length > 0 ? `<${ret.join(', ')}> ` : '';
2723
+ function recurse(t) {
2724
+ switch (t.type) {
2725
+ case 'param':
2726
+ ret.push(t.typeVarDeclaration);
2727
+ break;
2728
+ case 'static':
2729
+ for (const arg of t.typeArguments ?? []) {
2730
+ recurse(arg);
2731
+ }
2732
+ break;
2733
+ }
2734
+ }
2735
+ }
2736
+ function typesEqual(a, b, opts) {
2737
+ if (a.type !== b.type) {
2738
+ return false;
2739
+ }
2740
+ if (a.typeSymbol !== b.typeSymbol) {
2741
+ return false;
2742
+ }
2743
+ if (a.type === 'static' && b.type === 'static' && opts === 'deep') {
2744
+ if (a.typeArguments?.length !== b.typeArguments?.length) {
2745
+ return false;
2746
+ }
2747
+ if (a.typeArguments) {
2748
+ for (let i = 0; i < a.typeArguments.length; i++) {
2749
+ if (!typesEqual(a.typeArguments[i], b.typeArguments[i])) {
2750
+ return false;
2751
+ }
2752
+ }
2753
+ }
2754
+ }
2755
+ return true;
2756
+ }
2757
+ // endregion
2758
+ /**
2759
+ * Return a reference for the marshalling class object
2760
+ *
2761
+ * Basically returns `Type.class`, disregarding any generic
2762
+ * type arguments.
2763
+ */
2764
+ function marshallingType(x) {
2765
+ switch (x.type) {
2766
+ case 'static':
2767
+ return `${x.typeSymbol}.class`;
2768
+ case 'param':
2769
+ throw new Error(`Cannot marshall a type parameter: ${JSON.stringify(x)}`);
2770
+ }
2771
+ }
2772
+ /**
2773
+ * Return the one type from a union, or collapse to Object if there's more than one type in the union
2774
+ */
2775
+ function forceSingleType(types) {
2776
+ if (types.length > 1) {
2777
+ return {
2778
+ ...mkStatic('java.lang.Object'),
2779
+ // Copy the annotation
2780
+ annotation: types[0].annotation,
2781
+ };
2782
+ }
2783
+ return types[0];
2784
+ }
2785
+ function annotateOptional(optionalValue, types) {
2786
+ return types.map((t) => ({
2787
+ ...t,
2788
+ annotation: `${optionalValue.optional ? ANN_NULLABLE : ANN_NOT_NULL} `,
2789
+ }));
2790
+ }
2791
+ /**
2792
+ * Resolve any type intersections to the first type
2793
+ */
2794
+ function removeIntersections(x) {
2795
+ if (spec.isIntersectionTypeReference(x)) {
2796
+ return x.intersection.types[0];
2797
+ }
2798
+ if (spec.isUnionTypeReference(x)) {
2799
+ return {
2800
+ ...x,
2801
+ union: {
2802
+ types: x.union.types.map(removeIntersections),
2803
+ },
2804
+ };
2805
+ }
2806
+ if (spec.isCollectionTypeReference(x)) {
2807
+ return {
2808
+ ...x,
2809
+ collection: {
2810
+ kind: x.collection.kind,
2811
+ elementtype: removeIntersections(x.collection.elementtype),
2812
+ },
2813
+ };
2814
+ }
2815
+ return x;
2816
+ }
2625
2817
  //# sourceMappingURL=java.js.map