jsii-pacmak 1.66.0 → 1.68.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.
package/generate.sh CHANGED
@@ -15,7 +15,8 @@ cat > lib/version.ts <<HERE
15
15
  // Generated at $(date -u +"%Y-%m-%dT%H:%M:%SZ") by generate.sh
16
16
 
17
17
  /** The short version number for this JSII compiler (e.g: \`X.Y.Z\`) */
18
- export const VERSION = '${VERSION}';
18
+ // eslint-disable-next-line @typescript-eslint/no-inferrable-types
19
+ export const VERSION: string = '${VERSION}';
19
20
 
20
21
  /** The qualified version number for this JSII compiler (e.g: \`X.Y.Z (build #######)\`) */
21
22
  export const VERSION_DESC = '${VERSION} (build ${commit:0:7}${suffix:-})';
@@ -98,6 +98,24 @@ class Validation {
98
98
  code.openBlock(`switch (${expression})`);
99
99
  for (const type of types) {
100
100
  validTypes.push(resolver.toDotNetTypeName(type.spec));
101
+ /**
102
+ * Filter to remove classes and interfaces from a set of type references that
103
+ * are implied by another entry in the set. Practically this is meant to remove
104
+ * types from a set if a parent type of it is also present in the set, keeping
105
+ * only the most generic declaration.
106
+ *
107
+ * This is useful because the TypeScript compiler and jsii do not guarantee that
108
+ * all entries in a type union are unrelated, but the C# compiler treats dead
109
+ * code as an error, and will refuse to compile (error CS8120) a pattern-matching
110
+ * switch case if it cannot be matched (for example, if it matches on a child of
111
+ * a type that was previously matched on already).
112
+ */
113
+ if ((type.type?.isClassType() || type.type?.isInterfaceType()) &&
114
+ types.some((other) => other !== type &&
115
+ other.type != null &&
116
+ type.type.extends(other.type))) {
117
+ continue;
118
+ }
101
119
  const typeNames = [resolver.toDotNetType(type.spec)];
102
120
  if (typeNames[0] === 'double') {
103
121
  // For doubles, we accept any numeric value, really...
@@ -55,6 +55,7 @@ export declare class RootPackage extends Package {
55
55
  readonly assembly: Assembly;
56
56
  readonly version: string;
57
57
  private readonly versionFile;
58
+ private readonly typeCache;
58
59
  private readonly rootPackageCache;
59
60
  constructor(assembly: Assembly, rootPackageCache?: Map<string, RootPackage>);
60
61
  emit(context: EmitContext): void;
@@ -263,6 +263,7 @@ class RootPackage extends Package {
263
263
  const moduleName = goConfig.moduleName ?? '';
264
264
  const version = `${assembly.version}${goConfig.versionSuffix ?? ''}`;
265
265
  super(assembly, packageName, filePath, moduleName, version);
266
+ this.typeCache = new Map();
266
267
  this.rootPackageCache = rootPackageCache;
267
268
  this.rootPackageCache.set(assembly.name, this);
268
269
  this.assembly = assembly;
@@ -315,12 +316,15 @@ class RootPackage extends Package {
315
316
  * This allows resolving type references from other JSII modules
316
317
  */
317
318
  findType(fqn) {
318
- return this.packageDependencies.reduce((accum, current) => {
319
- if (accum) {
320
- return accum;
321
- }
322
- return current.findType(fqn);
323
- }, super.findType(fqn));
319
+ if (!this.typeCache.has(fqn)) {
320
+ this.typeCache.set(fqn, this.packageDependencies.reduce((accum, current) => {
321
+ if (accum) {
322
+ return accum;
323
+ }
324
+ return current.findType(fqn);
325
+ }, super.findType(fqn)));
326
+ }
327
+ return this.typeCache.get(fqn);
324
328
  }
325
329
  /*
326
330
  * Get all JSII module dependencies of the package being generated
@@ -124,7 +124,25 @@ declare class JavaGenerator extends Generator {
124
124
  private renderConstName;
125
125
  private emitConstProperty;
126
126
  private emitProperty;
127
+ /**
128
+ * Filters types from a union to select only those that correspond to the
129
+ * specified javaType.
130
+ *
131
+ * @param ref the type to be filtered.
132
+ * @param javaType the java type that is expected.
133
+ * @param covariant whether collections should use the covariant form.
134
+ * @param optional whether the type at an optional location or not
135
+ *
136
+ * @returns a type reference that matches the provided javaType.
137
+ */
138
+ private filterType;
127
139
  private emitMethod;
140
+ /**
141
+ * Emits type checks for values passed for type union parameters.
142
+ *
143
+ * @param parameters the list of parameters received by the function.
144
+ */
145
+ private emitUnionParameterValdation;
128
146
  /**
129
147
  * We are now going to build a class that can be used as a proxy for untyped
130
148
  * javascript objects that implement this interface. we want java code to be
@@ -153,6 +171,7 @@ declare class JavaGenerator extends Generator {
153
171
  private getClassBase;
154
172
  private toDecoratedJavaType;
155
173
  private toDecoratedJavaTypes;
174
+ private toJavaTypeNoGenerics;
156
175
  private toJavaType;
157
176
  private toNativeType;
158
177
  private toJavaTypes;
@@ -2,8 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.JavaBuilder = void 0;
4
4
  const spec = require("@jsii/spec");
5
+ const assert = require("assert");
5
6
  const clone = require("clone");
6
7
  const case_utils_1 = require("codemaker/lib/case-utils");
8
+ const crypto_1 = require("crypto");
7
9
  const fs = require("fs-extra");
8
10
  const jsii_rosetta_1 = require("jsii-rosetta");
9
11
  const path = require("path");
@@ -425,6 +427,7 @@ class JavaGenerator extends generator_1.Generator {
425
427
  : this.renderAccessLevel(method);
426
428
  this.code.openBlock(`${initializerAccessLevel} ${cls.name}(${this.renderMethodParameters(method)})`);
427
429
  this.code.line('super(software.amazon.jsii.JsiiObject.InitializationMode.JSII);');
430
+ this.emitUnionParameterValdation(method.parameters);
428
431
  this.code.line(`software.amazon.jsii.JsiiEngine.getInstance().createNewObject(this${this.renderMethodCallArguments(method)});`);
429
432
  this.code.closeBlock();
430
433
  }
@@ -861,7 +864,10 @@ class JavaGenerator extends generator_1.Generator {
861
864
  dependencies.push({
862
865
  groupId: 'software.amazon.jsii',
863
866
  artifactId: 'jsii-runtime',
864
- version: (0, version_utils_1.toMavenVersionRange)(`^${version_1.VERSION}`),
867
+ version: version_1.VERSION === '0.0.0'
868
+ ? '[0.0.0-SNAPSHOT]'
869
+ : // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
870
+ (0, version_utils_1.toMavenVersionRange)(`^${version_1.VERSION}`),
865
871
  });
866
872
  // Provides @org.jetbrains.*
867
873
  dependencies.push({
@@ -1008,6 +1014,23 @@ class JavaGenerator extends generator_1.Generator {
1008
1014
  else {
1009
1015
  this.code.openBlock(signature);
1010
1016
  let statement = '';
1017
+ // Setters have one overload for each possible type in the union parameter.
1018
+ // If a setter can take a `String | Number`, then we render two setters;
1019
+ // one that takes a string, and one that takes a number.
1020
+ // This allows the compiler to do this type checking for us,
1021
+ // so we should not emit these checks for primitive-only unions.
1022
+ // Also, Java does not allow us to perform these checks if the types
1023
+ // have no overlap (eg if a String instanceof Number).
1024
+ if (type.includes('java.lang.Object') &&
1025
+ (!spec.isPrimitiveTypeReference(prop.type) ||
1026
+ prop.type.primitive === spec.PrimitiveType.Any)) {
1027
+ this.emitUnionParameterValdation([
1028
+ {
1029
+ name: 'value',
1030
+ type: this.filterType(prop.type, { covariant: prop.static, optional: prop.optional }, type),
1031
+ },
1032
+ ]);
1033
+ }
1011
1034
  if (prop.static) {
1012
1035
  statement += `software.amazon.jsii.JsiiObject.jsiiStaticSet(${javaClass}.class, `;
1013
1036
  }
@@ -1024,6 +1047,27 @@ class JavaGenerator extends generator_1.Generator {
1024
1047
  }
1025
1048
  }
1026
1049
  }
1050
+ /**
1051
+ * Filters types from a union to select only those that correspond to the
1052
+ * specified javaType.
1053
+ *
1054
+ * @param ref the type to be filtered.
1055
+ * @param javaType the java type that is expected.
1056
+ * @param covariant whether collections should use the covariant form.
1057
+ * @param optional whether the type at an optional location or not
1058
+ *
1059
+ * @returns a type reference that matches the provided javaType.
1060
+ */
1061
+ filterType(ref, { covariant, optional }, javaType) {
1062
+ if (!spec.isUnionTypeReference(ref)) {
1063
+ // No filterning needed -- this isn't a type union!
1064
+ return ref;
1065
+ }
1066
+ const types = ref.union.types.filter((t) => this.toDecoratedJavaType({ optional, type: t }, { covariant }) ===
1067
+ javaType);
1068
+ assert(types.length > 0, `No type found in ${spec.describeTypeReference(ref)} has Java type ${javaType}`);
1069
+ return { union: { types } };
1070
+ }
1027
1071
  emitMethod(cls, method, { defaultImpl = false, final = false, overrides = !!method.overrides, } = {}) {
1028
1072
  const returnType = method.returns
1029
1073
  ? this.toDecoratedJavaType(method.returns)
@@ -1055,10 +1099,167 @@ class JavaGenerator extends generator_1.Generator {
1055
1099
  }
1056
1100
  else {
1057
1101
  this.code.openBlock(`${modifiers.join(' ')} ${signature}`);
1102
+ this.emitUnionParameterValdation(method.parameters);
1058
1103
  this.code.line(this.renderMethodCall(cls, method, async));
1059
1104
  this.code.closeBlock();
1060
1105
  }
1061
1106
  }
1107
+ /**
1108
+ * Emits type checks for values passed for type union parameters.
1109
+ *
1110
+ * @param parameters the list of parameters received by the function.
1111
+ */
1112
+ emitUnionParameterValdation(parameters) {
1113
+ if (!this.runtimeTypeChecking) {
1114
+ // We were configured not to emit those, so bail out now.
1115
+ return;
1116
+ }
1117
+ const unionParameters = parameters?.filter(({ type }) => containsUnionType(type));
1118
+ if (unionParameters == null || unionParameters.length === 0) {
1119
+ return;
1120
+ }
1121
+ this.code.openBlock('if (software.amazon.jsii.Configuration.getRuntimeTypeChecking())');
1122
+ for (const param of unionParameters) {
1123
+ if (param.variadic) {
1124
+ const javaType = this.toJavaType(param.type);
1125
+ const asListName = `__${param.name}__asList`;
1126
+ this.code.line(`final java.util.List<${javaType}> ${asListName} = java.util.Arrays.asList(${param.name});`);
1127
+ validate.call(this, asListName, `.append("${param.name}")`, {
1128
+ collection: {
1129
+ kind: spec.CollectionKind.Array,
1130
+ elementtype: param.type,
1131
+ },
1132
+ }, param.name, true);
1133
+ }
1134
+ else {
1135
+ validate.call(this, param.name, `.append("${param.name}")`, param.type, param.name);
1136
+ }
1137
+ }
1138
+ this.code.closeBlock();
1139
+ function validate(value, descr, type, parameterName, isRawArray = false) {
1140
+ if (spec.isUnionTypeReference(type)) {
1141
+ validateTypeUnion.call(this, value, descr, type, parameterName);
1142
+ }
1143
+ else if (spec.isCollectionTypeReference(type)) {
1144
+ switch (type.collection.kind) {
1145
+ case spec.CollectionKind.Array:
1146
+ return validateArray.call(this, value, descr, type.collection.elementtype, parameterName, isRawArray);
1147
+ case spec.CollectionKind.Map:
1148
+ return validateMap.call(this, value, descr, type.collection.elementtype, parameterName);
1149
+ default:
1150
+ throw new Error(`Unhandled collection kind: ${spec.describeTypeReference(type)}`);
1151
+ }
1152
+ }
1153
+ }
1154
+ function validateArray(value, descr, elementType, parameterName, isRawArray = false) {
1155
+ const suffix = (0, crypto_1.createHash)('sha256')
1156
+ .update(descr)
1157
+ .digest('hex')
1158
+ .slice(0, 6);
1159
+ const idxName = `__idx_${suffix}`;
1160
+ const valName = `__val_${suffix}`;
1161
+ this.code.openBlock(`for (int ${idxName} = 0; ${idxName} < ${value}.size(); ${idxName}++)`);
1162
+ const eltType = this.toJavaType(elementType);
1163
+ this.code.line(`final ${eltType} ${valName} = ${value}.get(${idxName});`);
1164
+ validate.call(this, valName, isRawArray
1165
+ ? `${descr}.append("[").append(${idxName}).append("]")`
1166
+ : `${descr}.append(".get(").append(${idxName}).append(")")`, elementType, parameterName);
1167
+ this.code.closeBlock();
1168
+ }
1169
+ function validateMap(value, descr, elementType, parameterName) {
1170
+ // we have to perform this check before the loop,
1171
+ // because the loop will assume that the keys are Strings;
1172
+ // this throws a ClassCastException
1173
+ this.code.openBlock(`if (!(${value}.keySet().toArray()[0] instanceof String))`);
1174
+ this.code.indent(`throw new IllegalArgumentException(`);
1175
+ this.code.indent(`new java.lang.StringBuilder("Expected ")`);
1176
+ this.code.line(`${descr}.append(".keySet()")`);
1177
+ this.code.line(`.append(" to contain class String; received ")`);
1178
+ this.code.line(`.append(${value}.keySet().toArray()[0].getClass()).toString());`);
1179
+ this.code.unindent(false);
1180
+ this.code.unindent(false);
1181
+ this.code.closeBlock();
1182
+ const suffix = (0, crypto_1.createHash)('sha256')
1183
+ .update(descr)
1184
+ .digest('hex')
1185
+ .slice(0, 6);
1186
+ const varName = `__item_${suffix}`;
1187
+ const valName = `__val_${suffix}`;
1188
+ const javaElemType = this.toJavaType(elementType);
1189
+ this.code.openBlock(`for (final java.util.Map.Entry<String, ${javaElemType}> ${varName}: ${value}.entrySet())`);
1190
+ this.code.line(`final ${javaElemType} ${valName} = ${varName}.getValue();`);
1191
+ validate.call(this, valName, `${descr}.append(".get(\\"").append((${varName}.getKey())).append("\\")")`, elementType, parameterName);
1192
+ this.code.closeBlock();
1193
+ }
1194
+ function validateTypeUnion(value, descr, type, parameterName) {
1195
+ let emitAnd = false;
1196
+ const nestedCollectionUnionTypes = new Map();
1197
+ const typeRefs = type.union.types;
1198
+ if (typeRefs.length > 1) {
1199
+ this.code.indent('if (');
1200
+ }
1201
+ const checked = new Set();
1202
+ for (const typeRef of typeRefs) {
1203
+ const prefix = emitAnd ? '&&' : '';
1204
+ const javaRawType = this.toJavaTypeNoGenerics(typeRef);
1205
+ if (checked.has(javaRawType)) {
1206
+ continue;
1207
+ }
1208
+ else {
1209
+ checked.add(javaRawType);
1210
+ }
1211
+ const javaType = this.toJavaType(typeRef);
1212
+ if (javaRawType !== javaType) {
1213
+ nestedCollectionUnionTypes.set(javaType, typeRef);
1214
+ }
1215
+ const test = `${value} instanceof ${javaRawType}`;
1216
+ if (typeRefs.length > 1) {
1217
+ this.code.line(`${prefix} !(${test})`);
1218
+ }
1219
+ emitAnd = true;
1220
+ }
1221
+ if (typeRefs.length > 1 &&
1222
+ typeRefs.some((t) => spec.isNamedTypeReference(t) &&
1223
+ spec.isInterfaceType(this.findType(t.fqn)))) {
1224
+ // Only anonymous objects at runtime can be `JsiiObject`s.
1225
+ this.code.line(`&& !(${value}.getClass().equals(software.amazon.jsii.JsiiObject.class))`);
1226
+ }
1227
+ if (typeRefs.length > 1) {
1228
+ this.code.unindent(false);
1229
+ this.code.openBlock(')');
1230
+ const placeholders = typeRefs
1231
+ .map((typeRef) => {
1232
+ return `${this.toJavaType(typeRef)}`;
1233
+ })
1234
+ .join(', ');
1235
+ this.code.indent(`throw new IllegalArgumentException(`);
1236
+ this.code.indent(`new java.lang.StringBuilder("Expected ")`);
1237
+ this.code.line(descr);
1238
+ this.code.line(`.append(" to be one of: ${placeholders}; received ")`);
1239
+ this.code.line(`.append(${value}.getClass()).toString());`);
1240
+ this.code.unindent(false);
1241
+ this.code.unindent(false);
1242
+ this.code.closeBlock();
1243
+ }
1244
+ for (const [javaType, typeRef] of nestedCollectionUnionTypes) {
1245
+ const varName = typeRefs.length > 1
1246
+ ? `__cast_${(0, crypto_1.createHash)('sha256')
1247
+ .update(value)
1248
+ .digest('hex')
1249
+ .slice(0, 6)}`
1250
+ : value;
1251
+ if (typeRefs.length > 1) {
1252
+ this.code.openBlock(`if (${value} instanceof ${this.toJavaTypeNoGenerics(typeRef)})`);
1253
+ this.code.line(`@SuppressWarnings("unchecked")`);
1254
+ this.code.line(`final ${javaType} ${varName} = (${javaType})${value};`);
1255
+ }
1256
+ validate.call(this, varName, descr, typeRef, parameterName);
1257
+ if (typeRefs.length > 1) {
1258
+ this.code.closeBlock();
1259
+ }
1260
+ }
1261
+ }
1262
+ }
1062
1263
  /**
1063
1264
  * We are now going to build a class that can be used as a proxy for untyped
1064
1265
  * javascript objects that implement this interface. we want java code to be
@@ -1726,6 +1927,22 @@ class JavaGenerator extends generator_1.Generator {
1726
1927
  toDecoratedJavaTypes(optionalValue, { covariant = false } = {}) {
1727
1928
  return this.toJavaTypes(optionalValue.type, { covariant }).map((nakedType) => `${optionalValue.optional ? ANN_NULLABLE : ANN_NOT_NULL} ${nakedType}`);
1728
1929
  }
1930
+ // Strips <*> from the type name.
1931
+ // necessary, because of type erasure; the compiler
1932
+ // will not let you check `foo instanceof Map<String, Foo>`,
1933
+ // and you must instead check `foo instanceof Map`.
1934
+ toJavaTypeNoGenerics(type, opts) {
1935
+ const typeStr = this.toJavaType(type, opts);
1936
+ const leftAngleBracketIdx = typeStr.indexOf('<');
1937
+ const rightAngleBracketIdx = typeStr.indexOf('>');
1938
+ if ((leftAngleBracketIdx < 0 && rightAngleBracketIdx >= 0) ||
1939
+ (leftAngleBracketIdx >= 0 && rightAngleBracketIdx < 0)) {
1940
+ throw new Error(`Invalid generic type: found ${typeStr}`);
1941
+ }
1942
+ return leftAngleBracketIdx > 0 && rightAngleBracketIdx > 0
1943
+ ? typeStr.slice(0, leftAngleBracketIdx)
1944
+ : typeStr;
1945
+ }
1729
1946
  toJavaType(type, opts) {
1730
1947
  const types = this.toJavaTypes(type, opts);
1731
1948
  if (types.length > 1) {
@@ -2366,4 +2583,9 @@ function splitNamespace(ns) {
2366
2583
  function escape(s) {
2367
2584
  return s.replace(/["\\<>&]/g, (c) => `&#${c.charCodeAt(0)};`);
2368
2585
  }
2586
+ function containsUnionType(typeRef) {
2587
+ return (spec.isUnionTypeReference(typeRef) ||
2588
+ (spec.isCollectionTypeReference(typeRef) &&
2589
+ containsUnionType(typeRef.collection.elementtype)));
2590
+ }
2369
2591
  //# sourceMappingURL=java.js.map
package/lib/version.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /** The short version number for this JSII compiler (e.g: `X.Y.Z`) */
2
- export declare const VERSION = "1.66.0";
2
+ export declare const VERSION: string;
3
3
  /** The qualified version number for this JSII compiler (e.g: `X.Y.Z (build #######)`) */
4
- export declare const VERSION_DESC = "1.66.0 (build 3c9512b)";
4
+ export declare const VERSION_DESC = "1.68.0 (build b45f2f6)";
5
5
  //# sourceMappingURL=version.d.ts.map
package/lib/version.js CHANGED
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
- // Generated at 2022-08-29T23:52:00Z by generate.sh
2
+ // Generated at 2022-09-22T19:38:42Z by generate.sh
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.VERSION_DESC = exports.VERSION = void 0;
5
5
  /** The short version number for this JSII compiler (e.g: `X.Y.Z`) */
6
- exports.VERSION = '1.66.0';
6
+ // eslint-disable-next-line @typescript-eslint/no-inferrable-types
7
+ exports.VERSION = '1.68.0';
7
8
  /** The qualified version number for this JSII compiler (e.g: `X.Y.Z (build #######)`) */
8
- exports.VERSION_DESC = '1.66.0 (build 3c9512b)';
9
+ exports.VERSION_DESC = '1.68.0 (build b45f2f6)';
9
10
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsii-pacmak",
3
- "version": "1.66.0",
3
+ "version": "1.68.0",
4
4
  "description": "A code generation framework for jsii backend languages",
5
5
  "license": "Apache-2.0",
6
6
  "author": {
@@ -37,35 +37,35 @@
37
37
  "package": "package-js"
38
38
  },
39
39
  "dependencies": {
40
- "@jsii/check-node": "1.66.0",
41
- "@jsii/spec": "^1.66.0",
40
+ "@jsii/check-node": "1.68.0",
41
+ "@jsii/spec": "^1.68.0",
42
42
  "clone": "^2.1.2",
43
- "codemaker": "^1.66.0",
43
+ "codemaker": "^1.68.0",
44
44
  "commonmark": "^0.30.0",
45
45
  "escape-string-regexp": "^4.0.0",
46
46
  "fs-extra": "^10.1.0",
47
- "jsii-reflect": "^1.66.0",
48
- "jsii-rosetta": "^1.66.0",
47
+ "jsii-reflect": "^1.68.0",
48
+ "jsii-rosetta": "^1.68.0",
49
49
  "semver": "^7.3.7",
50
50
  "spdx-license-list": "^6.6.0",
51
51
  "xmlbuilder": "^15.1.1",
52
52
  "yargs": "^16.2.0"
53
53
  },
54
54
  "devDependencies": {
55
- "@jsii/dotnet-runtime": "^1.66.0",
56
- "@jsii/java-runtime": "^1.66.0",
57
- "@jsii/go-runtime": "^1.66.0",
58
- "@scope/jsii-calc-lib": "^1.66.0",
55
+ "@jsii/dotnet-runtime": "^1.68.0",
56
+ "@jsii/java-runtime": "^1.68.0",
57
+ "@jsii/go-runtime": "^1.68.0",
58
+ "@scope/jsii-calc-lib": "^1.68.0",
59
59
  "@types/clone": "^2.1.1",
60
60
  "@types/diff": "^5.0.2",
61
61
  "@types/commonmark": "^0.27.5",
62
62
  "@types/fs-extra": "^9.0.13",
63
63
  "@types/semver": "^7.3.12",
64
64
  "diff": "^5.1.0",
65
- "jsii": "^1.66.0",
66
- "jsii-build-tools": "^1.66.0",
65
+ "jsii": "^1.68.0",
66
+ "jsii-build-tools": "^1.68.0",
67
67
  "jsii-calc": "^3.20.120",
68
- "pyright": "^1.1.267"
68
+ "pyright": "^1.1.272"
69
69
  },
70
70
  "keywords": [
71
71
  "jsii",