jsii-pacmak 1.65.0 → 1.67.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 (41) hide show
  1. package/generate.sh +2 -1
  2. package/lib/targets/dotnet/dotnetgenerator.js +19 -110
  3. package/lib/targets/dotnet/dotnettyperesolver.js +5 -4
  4. package/lib/targets/dotnet/runtime-type-checking.d.ts +13 -0
  5. package/lib/targets/dotnet/runtime-type-checking.js +146 -0
  6. package/lib/targets/go/dependencies.d.ts +16 -0
  7. package/lib/targets/go/dependencies.js +59 -0
  8. package/lib/targets/go/emit-context.d.ts +2 -0
  9. package/lib/targets/go/package.d.ts +1 -0
  10. package/lib/targets/go/package.js +54 -33
  11. package/lib/targets/go/runtime/class-constructor.d.ts +2 -1
  12. package/lib/targets/go/runtime/class-constructor.js +4 -1
  13. package/lib/targets/go/runtime/method-call.d.ts +2 -2
  14. package/lib/targets/go/runtime/method-call.js +11 -5
  15. package/lib/targets/go/runtime/property-access.d.ts +3 -2
  16. package/lib/targets/go/runtime/property-access.js +7 -2
  17. package/lib/targets/go/runtime/runtime-type-checking.d.ts +29 -0
  18. package/lib/targets/go/runtime/runtime-type-checking.js +408 -0
  19. package/lib/targets/go/types/class.d.ts +10 -5
  20. package/lib/targets/go/types/class.js +60 -30
  21. package/lib/targets/go/types/enum.d.ts +2 -2
  22. package/lib/targets/go/types/enum.js +6 -2
  23. package/lib/targets/go/types/go-type-reference.d.ts +6 -1
  24. package/lib/targets/go/types/go-type-reference.js +37 -21
  25. package/lib/targets/go/types/go-type.d.ts +4 -1
  26. package/lib/targets/go/types/go-type.js +3 -0
  27. package/lib/targets/go/types/interface.d.ts +5 -3
  28. package/lib/targets/go/types/interface.js +40 -17
  29. package/lib/targets/go/types/struct.d.ts +7 -3
  30. package/lib/targets/go/types/struct.js +41 -2
  31. package/lib/targets/go/types/type-member.d.ts +8 -1
  32. package/lib/targets/go/types/type-member.js +63 -18
  33. package/lib/targets/go.d.ts +6 -2
  34. package/lib/targets/go.js +6 -4
  35. package/lib/targets/java.d.ts +19 -0
  36. package/lib/targets/java.js +223 -1
  37. package/lib/targets/python/type-name.js +3 -3
  38. package/lib/targets/python.js +5 -1
  39. package/lib/version.d.ts +2 -2
  40. package/lib/version.js +4 -3
  41. package/package.json +14 -14
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:-})';
@@ -3,10 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DotNetGenerator = void 0;
4
4
  const spec = require("@jsii/spec");
5
5
  const clone = require("clone");
6
- const crypto_1 = require("crypto");
7
6
  const fs = require("fs-extra");
8
7
  const http = require("http");
9
8
  const https = require("https");
9
+ const reflect = require("jsii-reflect");
10
10
  const path = require("path");
11
11
  const generator_1 = require("../../generator");
12
12
  const logging_1 = require("../../logging");
@@ -15,6 +15,7 @@ const dotnetruntimegenerator_1 = require("./dotnetruntimegenerator");
15
15
  const dotnettyperesolver_1 = require("./dotnettyperesolver");
16
16
  const filegenerator_1 = require("./filegenerator");
17
17
  const nameutils_1 = require("./nameutils");
18
+ const runtime_type_checking_1 = require("./runtime-type-checking");
18
19
  /**
19
20
  * CODE GENERATOR V2
20
21
  */
@@ -272,7 +273,8 @@ class DotNetGenerator extends generator_1.Generator {
272
273
  // the instance will be created in the kernel (where it'd fail on a sub-optimal error instead)...
273
274
  this.code.line('[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]');
274
275
  this.code.openBlock(`private static DeputyProps _MakeDeputyProps(${parametersDefinition})`);
275
- this.emitUnionParameterValdation(initializer.parameters);
276
+ this.emitUnionParameterValdation(this.reflectAssembly.findType(cls.fqn)
277
+ .initializer?.parameters);
276
278
  const args = parametersBase.length > 0
277
279
  ? `new object?[]{${parametersBase}}`
278
280
  : `System.Array.Empty<object?>()`;
@@ -432,7 +434,7 @@ class DotNetGenerator extends generator_1.Generator {
432
434
  }
433
435
  else {
434
436
  this.code.openBlock(`${access} ${staticKeyWord}${overrideKeyWord}${virtualKeyWord}${signature}`);
435
- this.emitUnionParameterValdation(method.parameters);
437
+ this.emitUnionParameterValdation(this.reflectAssembly.findType(cls.fqn).allMethods.find((m) => m.name === method.name).parameters);
436
438
  this.code.line(this.dotnetRuntimeGenerator.createInvokeMethodIdentifier(method, cls));
437
439
  this.code.closeBlock();
438
440
  }
@@ -443,113 +445,18 @@ class DotNetGenerator extends generator_1.Generator {
443
445
  * @param parameters the list of parameters received by the function.
444
446
  * @param noMangle use parameter names as-is (useful for setters, for example) instead of mangling them.
445
447
  */
446
- emitUnionParameterValdation(parameters, { noMangle = false } = {}) {
448
+ emitUnionParameterValdation(parameters = [], opts = { noMangle: false }) {
447
449
  if (!this.runtimeTypeChecking) {
448
450
  // We were configured not to emit those, so bail out now.
449
451
  return;
450
452
  }
451
- const unionParameters = parameters?.filter(({ type }) => containsUnionType(type));
452
- if (unionParameters == null || unionParameters.length === 0) {
453
+ const validator = runtime_type_checking_1.ParameterValidator.forParameters(parameters, this.nameutils, opts);
454
+ if (validator == null) {
453
455
  return;
454
456
  }
455
457
  this.code.openBlock('if (Amazon.JSII.Runtime.Configuration.RuntimeTypeChecking)');
456
- for (const param of unionParameters) {
457
- const name = noMangle
458
- ? param.name
459
- : this.nameutils.convertParameterName(param.name);
460
- if (param.optional) {
461
- this.code.openBlock(`if (${name} != null)`);
462
- }
463
- validate.call(this, name, noMangle ? name : `argument {nameof(${name})}`, param.type, noMangle ? name : `{nameof(${name})}`);
464
- if (param.optional) {
465
- this.code.closeBlock();
466
- }
467
- }
458
+ validator.emit(this.code, this.typeresolver);
468
459
  this.code.closeBlock();
469
- function validate(value, descr, type, parameterName) {
470
- if (spec.isUnionTypeReference(type)) {
471
- validateTypeUnion.call(this, value, descr, type, parameterName);
472
- }
473
- else {
474
- const collectionType = type;
475
- if (collectionType.collection.kind === spec.CollectionKind.Array) {
476
- validateArray.call(this, value, descr, collectionType.collection.elementtype, parameterName);
477
- }
478
- else if (collectionType.collection.kind === spec.CollectionKind.Map) {
479
- validateMap.call(this, value, descr, collectionType.collection.elementtype, parameterName);
480
- }
481
- else {
482
- throw new Error(`Unhandled collection kind: ${spec.describeTypeReference(type)}`);
483
- }
484
- }
485
- }
486
- function validateArray(value, descr, elementType, parameterName) {
487
- const varName = `__idx_${(0, crypto_1.createHash)('sha256')
488
- .update(descr)
489
- .digest('hex')
490
- .slice(0, 6)}`;
491
- this.code.openBlock(`for (int ${varName} = 0 ; ${varName} < ${value}.Length ; ${varName}++)`);
492
- validate.call(this, `${value}[${varName}]`, `${descr}[{${varName}}]`, elementType, parameterName);
493
- this.code.closeBlock();
494
- }
495
- function validateMap(value, descr, elementType, parameterName) {
496
- const varName = `__item_${(0, crypto_1.createHash)('sha256')
497
- .update(descr)
498
- .digest('hex')
499
- .slice(0, 6)}`;
500
- this.code.openBlock(`foreach (var ${varName} in ${value})`);
501
- validate.call(this, `${varName}.Value`, `${descr}[\\"{${varName}.Key}\\"]`, elementType, parameterName);
502
- this.code.closeBlock();
503
- }
504
- function validateTypeUnion(value, descr, type, parameterName) {
505
- this.code.indent('if (');
506
- let emitAnd = false;
507
- const typeRefs = type.union.types;
508
- for (const typeRef of typeRefs) {
509
- const prefix = emitAnd ? '&& ' : '';
510
- const dotNetType = this.typeresolver.toDotNetType(typeRef);
511
- // In the case of double, we test for all standard numeric types of .NET (these implicitly convert).
512
- const test = dotNetType === 'double'
513
- ? [
514
- 'byte',
515
- 'decimal',
516
- 'double',
517
- 'float',
518
- 'int',
519
- 'long',
520
- 'sbyte',
521
- 'short',
522
- 'uint',
523
- 'ulong',
524
- 'ushort',
525
- ]
526
- .map((numeric) => `${value} is ${numeric}`)
527
- .join(' || ')
528
- : `${value} is ${dotNetType}`;
529
- this.code.line(`${prefix}!(${test})`);
530
- emitAnd = true;
531
- }
532
- if (typeRefs.some((ref) => spec.isNamedTypeReference(ref) &&
533
- spec.isInterfaceType(this.findType(ref.fqn)))) {
534
- // AnonymousObject will convert to any interface type, even if unsafely. It is the opaque
535
- // type returned when a non-intrinsically typed value is passed through an any or union
536
- // return point. We basically cannot type-check that at runtime in a complete way.
537
- this.code.line(`&& !(${value} is Amazon.JSII.Runtime.Deputy.AnonymousObject)`);
538
- }
539
- this.code.unindent(')');
540
- this.code.openBlock('');
541
- const placeholders = typeRefs
542
- .map((typeRef) => {
543
- const typeName = this.typeresolver.toDotNetTypeName(typeRef);
544
- if (typeName.startsWith('"') && typeName.endsWith('"')) {
545
- return typeName.slice(1, -1);
546
- }
547
- return `{${typeName}}`;
548
- })
549
- .join(', ');
550
- this.code.line(`throw new System.ArgumentException($"Expected ${descr} to be one of: ${placeholders}; received {${value}.GetType().FullName}", $"${parameterName}");`);
551
- this.code.closeBlock();
552
- }
553
460
  }
554
461
  /**
555
462
  * Founds out if a member (property or method) is already defined in one of the base classes
@@ -870,15 +777,15 @@ class DotNetGenerator extends generator_1.Generator {
870
777
  }
871
778
  }
872
779
  // Emit setters
780
+ const reflectCls = this.reflectAssembly.findType(cls.fqn);
781
+ const syntheticParam = new reflect.Parameter(reflectCls.system, reflectCls, new reflect.Method(reflectCls.system, reflectCls.assembly, reflectCls, reflectCls, { name: '<synthetic>' }), {
782
+ name: 'value',
783
+ type: prop.type,
784
+ optional: prop.optional,
785
+ });
873
786
  if (backingFieldName) {
874
787
  this.code.openBlock('set');
875
- this.emitUnionParameterValdation([
876
- {
877
- name: 'value',
878
- type: prop.type,
879
- optional: prop.optional,
880
- },
881
- ], { noMangle: true });
788
+ this.emitUnionParameterValdation([syntheticParam], { noMangle: true });
882
789
  this.code.line(`${backingFieldName} = value;`);
883
790
  this.code.closeBlock();
884
791
  }
@@ -892,7 +799,9 @@ class DotNetGenerator extends generator_1.Generator {
892
799
  : 'SetInstanceProperty(value);';
893
800
  if (containsUnionType(prop.type)) {
894
801
  this.code.openBlock('set');
895
- this.emitUnionParameterValdation([{ name: 'value', optional: prop.optional, type: prop.type }], { noMangle: true });
802
+ this.emitUnionParameterValdation([syntheticParam], {
803
+ noMangle: true,
804
+ });
896
805
  this.code.line(setCode);
897
806
  this.code.closeBlock();
898
807
  }
@@ -203,13 +203,14 @@ class DotNetTypeResolver {
203
203
  * Translates a collection in jsii to the name of a native .NET collection
204
204
  */
205
205
  toDotNetCollectionName(ref) {
206
+ const [_, dollar, quote, content] = /^(?:(\$)?("))?([^"]+)"?$/.exec(this.toDotNetTypeName(ref.collection.elementtype));
207
+ const interpolates = dollar || !quote ? '$' : '';
208
+ const elementTypeName = quote ? content : `{${content}}`;
206
209
  switch (ref.collection.kind) {
207
210
  case spec.CollectionKind.Array:
208
- const elementDotNetTypeName = this.toDotNetTypeName(ref.collection.elementtype);
209
- return `$"{${elementDotNetTypeName}}[]"`;
211
+ return `${interpolates}"${elementTypeName}[]"`;
210
212
  case spec.CollectionKind.Map:
211
- const elementDotNetType = this.toDotNetType(ref.collection.elementtype);
212
- return `typeof(System.Collections.Generic.IDictionary<string, ${elementDotNetType}>).FullName`;
213
+ return `${interpolates}"System.Collections.Generic.IDictionary<string, ${elementTypeName}>"`;
213
214
  default:
214
215
  throw new Error(`Unsupported collection kind: ${ref.collection.kind}`);
215
216
  }
@@ -0,0 +1,13 @@
1
+ import { CodeMaker } from 'codemaker';
2
+ import { Parameter } from 'jsii-reflect';
3
+ import { DotNetTypeResolver } from './dotnettyperesolver';
4
+ import { DotNetNameUtils } from './nameutils';
5
+ export declare class ParameterValidator {
6
+ private readonly validations;
7
+ static forParameters(parameters: readonly Parameter[], nameUtils: DotNetNameUtils, { noMangle }: {
8
+ readonly noMangle: boolean;
9
+ }): ParameterValidator | undefined;
10
+ private constructor();
11
+ emit(code: CodeMaker, resolver: DotNetTypeResolver): void;
12
+ }
13
+ //# sourceMappingURL=runtime-type-checking.d.ts.map
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ParameterValidator = void 0;
4
+ const spec_1 = require("@jsii/spec");
5
+ const crypto_1 = require("crypto");
6
+ const jsii_reflect_1 = require("jsii-reflect");
7
+ class ParameterValidator {
8
+ constructor(validations) {
9
+ this.validations = validations;
10
+ }
11
+ static forParameters(parameters, nameUtils, { noMangle }) {
12
+ if (parameters.length === 0) {
13
+ return undefined;
14
+ }
15
+ const parameterValidations = new Map();
16
+ for (const param of parameters) {
17
+ const expr = noMangle
18
+ ? param.name
19
+ : nameUtils.convertParameterName(param.name);
20
+ const argName = `nameof(${expr})`;
21
+ const validations = new Array();
22
+ const validation = Validation.forTypeReference(argName, expr, `${noMangle ? '' : 'argument '}{${argName}}`, param.variadic
23
+ ? new jsii_reflect_1.TypeReference(param.system, {
24
+ collection: {
25
+ kind: spec_1.CollectionKind.Array,
26
+ elementtype: param.type.spec,
27
+ },
28
+ })
29
+ : param.type, param.optional);
30
+ if (validation) {
31
+ validations.push(validation);
32
+ }
33
+ if (validations.length !== 0) {
34
+ parameterValidations.set(param, validations);
35
+ }
36
+ }
37
+ if (parameterValidations.size === 0) {
38
+ return undefined;
39
+ }
40
+ return new ParameterValidator(parameterValidations);
41
+ }
42
+ emit(code, resolver) {
43
+ for (const [_parameter, validations] of this.validations) {
44
+ for (const validation of validations) {
45
+ validation.emit(code, resolver);
46
+ }
47
+ }
48
+ }
49
+ }
50
+ exports.ParameterValidator = ParameterValidator;
51
+ class Validation {
52
+ static forTypeReference(argument, expression, description, ref, allowNull) {
53
+ if (ref.unionOfTypes) {
54
+ return Validation.unionCheck(argument, expression, description, ref.unionOfTypes, allowNull);
55
+ }
56
+ else if (ref.arrayOfType) {
57
+ return Validation.collectionCheck(argument, expression, description, 'array', ref.arrayOfType);
58
+ }
59
+ else if (ref.mapOfType) {
60
+ return Validation.collectionCheck(argument, expression, description, 'map', ref.mapOfType);
61
+ }
62
+ return undefined;
63
+ }
64
+ static collectionCheck(argument, expression, description, type, elementType) {
65
+ const elementValidator = Validation.forTypeReference(argument, `${expression}[idx]`, `${description}[@{idx}]`, elementType, false);
66
+ if (elementValidator == null) {
67
+ return undefined;
68
+ }
69
+ class CollectionCheck extends Validation {
70
+ emit(code, resolver) {
71
+ // We need to come up with a unique-enough ID here... so we use a hash.
72
+ const prefix = type === 'array' ? '__idx' : '__item';
73
+ const varName = `${prefix}_${(0, crypto_1.createHash)('sha256')
74
+ .update(expression)
75
+ .digest('hex')
76
+ .slice(0, 6)}`;
77
+ if (type === 'array') {
78
+ code.openBlock(`for (var ${varName} = 0 ; ${varName} < ${expression}.Length ; ${varName}++)`);
79
+ }
80
+ else {
81
+ code.openBlock(`foreach (var ${varName} in ${expression})`);
82
+ }
83
+ Validation.forTypeReference(argument, type === 'array' ? `${expression}[${varName}]` : `${varName}.Value`, `${description}[${type === 'array' ? `{${varName}}` : `"{${varName}.Key}"`}]`, elementType, false).emit(code, resolver);
84
+ code.closeBlock();
85
+ }
86
+ }
87
+ return new CollectionCheck();
88
+ }
89
+ static unionCheck(argument, expression, description, types, allowNull) {
90
+ const hasInterface = types.some((t) => t.type?.isInterfaceType());
91
+ class UnionCheck extends Validation {
92
+ emit(code, resolver) {
93
+ const validTypes = new Array();
94
+ const castVarName = `cast_${(0, crypto_1.createHash)('sha256')
95
+ .update(expression)
96
+ .digest('hex')
97
+ .slice(0, 6)}`;
98
+ code.openBlock(`switch (${expression})`);
99
+ for (const type of types) {
100
+ validTypes.push(resolver.toDotNetTypeName(type.spec));
101
+ const typeNames = [resolver.toDotNetType(type.spec)];
102
+ if (typeNames[0] === 'double') {
103
+ // For doubles, we accept any numeric value, really...
104
+ typeNames.push('byte', 'decimal', 'float', 'int', 'long', 'sbyte', 'short', 'uint', 'ulong', 'ushort');
105
+ }
106
+ for (const typeName of typeNames) {
107
+ code.indent(`case ${typeName} ${castVarName}:`);
108
+ Validation.forTypeReference(argument, castVarName, description, type, allowNull)?.emit(code, resolver);
109
+ code.line('break;');
110
+ code.unindent(false);
111
+ }
112
+ }
113
+ if (hasInterface) {
114
+ code.indent(`case Amazon.JSII.Runtime.Deputy.AnonymousObject ${castVarName}:`);
115
+ code.line('// Not enough information to type-check...');
116
+ code.line('break;');
117
+ code.unindent(false);
118
+ }
119
+ code.indent('case null:');
120
+ const acceptedTypes = validTypes
121
+ .map((t) => t.startsWith('"')
122
+ ? t.slice(1, t.length - 1)
123
+ : t.startsWith('$"')
124
+ ? t.slice(2, t.length - 1)
125
+ : `{${t}}`)
126
+ .join(', ');
127
+ if (allowNull) {
128
+ code.line('break;');
129
+ }
130
+ else {
131
+ const message = JSON.stringify(`Expected ${description} to be one of: ${acceptedTypes}; received null`);
132
+ code.line(`throw new System.ArgumentException($${message}, ${argument});`);
133
+ }
134
+ code.unindent(false);
135
+ code.indent('default:');
136
+ const message = JSON.stringify(`Expected ${description} to be one of: ${acceptedTypes}; received {${expression}.GetType().FullName}`);
137
+ code.line(`throw new System.ArgumentException($${message}, ${argument});`);
138
+ code.unindent(false);
139
+ code.closeBlock();
140
+ }
141
+ }
142
+ return new UnionCheck();
143
+ }
144
+ constructor() { }
145
+ }
146
+ //# sourceMappingURL=runtime-type-checking.js.map
@@ -1,8 +1,11 @@
1
+ import { Package } from './package';
1
2
  /**
2
3
  * Information about a module's dependency on "special" packages (either part of
3
4
  * the go standard library, or generated as part of the current module).
4
5
  */
5
6
  export interface SpecialDependencies {
7
+ /** Whether the go standard library for string formatting is needed */
8
+ readonly fmt: boolean;
6
9
  /** Whether the jsii runtime library for go is needed */
7
10
  readonly runtime: boolean;
8
11
  /** Whether the package's initialization hook is needed */
@@ -12,4 +15,17 @@ export interface SpecialDependencies {
12
15
  /** Whether go's standard library "time" module is needed */
13
16
  readonly time: boolean;
14
17
  }
18
+ export declare function reduceSpecialDependencies(...specialDepsList: readonly SpecialDependencies[]): SpecialDependencies;
19
+ export interface ImportedModule {
20
+ readonly alias?: string;
21
+ readonly module: string;
22
+ }
23
+ export declare function toImportedModules(specialDeps: SpecialDependencies, context: Package): readonly ImportedModule[];
24
+ /**
25
+ * The name of a sub-package that includes internal type aliases it has to be
26
+ * "internal" so it not published.
27
+ */
28
+ export declare const INTERNAL_PACKAGE_NAME = "internal";
29
+ export declare const JSII_RT_MODULE: ImportedModule;
30
+ export declare const GO_REFLECT: ImportedModule;
15
31
  //# sourceMappingURL=dependencies.d.ts.map
@@ -1,3 +1,62 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GO_REFLECT = exports.JSII_RT_MODULE = exports.INTERNAL_PACKAGE_NAME = exports.toImportedModules = exports.reduceSpecialDependencies = void 0;
4
+ const assert = require("assert");
5
+ const runtime_1 = require("./runtime");
6
+ function reduceSpecialDependencies(...specialDepsList) {
7
+ const [first, ...rest] = specialDepsList;
8
+ if (!first) {
9
+ assert(rest.length === 0);
10
+ return {
11
+ fmt: false,
12
+ init: false,
13
+ internal: false,
14
+ runtime: false,
15
+ time: false,
16
+ };
17
+ }
18
+ return rest.reduce((acc, elt) => ({
19
+ fmt: acc.fmt || elt.fmt,
20
+ init: acc.init || elt.init,
21
+ internal: acc.internal || elt.internal,
22
+ runtime: acc.runtime || elt.runtime,
23
+ time: acc.time || elt.time,
24
+ }), first);
25
+ }
26
+ exports.reduceSpecialDependencies = reduceSpecialDependencies;
27
+ function toImportedModules(specialDeps, context) {
28
+ const result = new Array();
29
+ if (specialDeps.fmt) {
30
+ result.push({ module: 'fmt' });
31
+ }
32
+ if (specialDeps.time) {
33
+ result.push({ module: 'time' });
34
+ }
35
+ if (specialDeps.runtime) {
36
+ result.push(exports.JSII_RT_MODULE);
37
+ }
38
+ if (specialDeps.init) {
39
+ result.push({
40
+ alias: runtime_1.JSII_INIT_ALIAS,
41
+ module: `${context.root.goModuleName}/${runtime_1.JSII_INIT_PACKAGE}`,
42
+ });
43
+ }
44
+ if (specialDeps.internal) {
45
+ result.push({
46
+ module: `${context.goModuleName}/${exports.INTERNAL_PACKAGE_NAME}`,
47
+ });
48
+ }
49
+ return result;
50
+ }
51
+ exports.toImportedModules = toImportedModules;
52
+ /**
53
+ * The name of a sub-package that includes internal type aliases it has to be
54
+ * "internal" so it not published.
55
+ */
56
+ exports.INTERNAL_PACKAGE_NAME = 'internal';
57
+ exports.JSII_RT_MODULE = {
58
+ alias: runtime_1.JSII_RT_ALIAS,
59
+ module: runtime_1.JSII_RT_PACKAGE_NAME,
60
+ };
61
+ exports.GO_REFLECT = { module: 'reflect' };
3
62
  //# sourceMappingURL=dependencies.js.map
@@ -8,5 +8,7 @@ export interface EmitContext {
8
8
  readonly code: CodeMaker;
9
9
  /** A Documentation generator. Includes Rosetta stone to translate code examples. */
10
10
  readonly documenter: Documentation;
11
+ /** Whether runtime type checking code should be emitted */
12
+ readonly runtimeTypeChecking: boolean;
11
13
  }
12
14
  //# sourceMappingURL=emit-context.d.ts.map
@@ -48,6 +48,7 @@ export declare abstract class Package {
48
48
  private emitGoInitFunction;
49
49
  private emitImports;
50
50
  private emitTypes;
51
+ private emitValidators;
51
52
  private emitInternal;
52
53
  }
53
54
  export declare class RootPackage extends Package {
@@ -4,6 +4,7 @@ exports.InternalPackage = exports.RootPackage = exports.Package = exports.GO_VER
4
4
  const path_1 = require("path");
5
5
  const semver = require("semver");
6
6
  const version_1 = require("../../version");
7
+ const dependencies_1 = require("./dependencies");
7
8
  const readme_file_1 = require("./readme-file");
8
9
  const runtime_1 = require("./runtime");
9
10
  const types_1 = require("./types");
@@ -11,9 +12,6 @@ const util_1 = require("./util");
11
12
  const version_file_1 = require("./version-file");
12
13
  exports.GOMOD_FILENAME = 'go.mod';
13
14
  exports.GO_VERSION = '1.16';
14
- // the name of a sub-package that includes internal type aliases it has to be
15
- // "internal" so it not published.
16
- const INTERNAL_PACKAGE_NAME = 'internal';
17
15
  /*
18
16
  * Package represents a single `.go` source file within a package. This can be the root package file or a submodule
19
17
  */
@@ -121,7 +119,7 @@ class Package {
121
119
  foriegnTypeName: original,
122
120
  foriegnType: typeref,
123
121
  fieldName: aliasName,
124
- embed: `${INTERNAL_PACKAGE_NAME}.${aliasName}`,
122
+ embed: `${dependencies_1.INTERNAL_PACKAGE_NAME}.${aliasName}`,
125
123
  };
126
124
  this.embeddedTypes.set(type.fqn, embeddedType);
127
125
  return embeddedType;
@@ -136,21 +134,22 @@ class Package {
136
134
  * responsible for correctly initializing the module, including registering
137
135
  * the declared types with the jsii runtime for go.
138
136
  */
139
- emitGoInitFunction({ code }) {
137
+ emitGoInitFunction(context) {
140
138
  // We don't emit anything if there are not types in this (sub)module. This
141
139
  // avoids registering an `init` function that does nothing, which is poor
142
140
  // form. It also saves us from "imported but unused" errors that would arise
143
141
  // as a consequence.
144
142
  if (this.types.length > 0) {
143
+ const { code } = context;
145
144
  const initFile = (0, path_1.join)(this.directory, `${this.packageName}.go`);
146
145
  code.openFile(initFile);
147
146
  code.line(`package ${this.packageName}`);
148
147
  code.line();
149
- importGoModules(code, [GO_REFLECT, JSII_RT_MODULE]);
148
+ importGoModules(code, [dependencies_1.GO_REFLECT, dependencies_1.JSII_RT_MODULE]);
150
149
  code.line();
151
150
  code.openBlock('func init()');
152
151
  for (const type of this.types) {
153
- type.emitRegistration(code);
152
+ type.emitRegistration(context);
154
153
  }
155
154
  code.closeBlock();
156
155
  code.closeFile(initFile);
@@ -158,24 +157,7 @@ class Package {
158
157
  }
159
158
  emitImports(code, type) {
160
159
  const toImport = new Array();
161
- const specialDeps = type.specialDependencies;
162
- if (specialDeps.time) {
163
- toImport.push({ module: 'time' });
164
- }
165
- if (specialDeps.runtime) {
166
- toImport.push(JSII_RT_MODULE);
167
- }
168
- if (specialDeps.init) {
169
- toImport.push({
170
- alias: runtime_1.JSII_INIT_ALIAS,
171
- module: `${this.root.goModuleName}/${runtime_1.JSII_INIT_PACKAGE}`,
172
- });
173
- }
174
- if (specialDeps.internal) {
175
- toImport.push({
176
- module: `${this.goModuleName}/${INTERNAL_PACKAGE_NAME}`,
177
- });
178
- }
160
+ toImport.push(...(0, dependencies_1.toImportedModules)(type.specialDependencies, this));
179
161
  for (const goModuleName of new Set(type.dependencies.map(({ goModuleName }) => goModuleName))) {
180
162
  // If the module is the same as the current one being written, don't emit an import statement
181
163
  if (goModuleName !== this.goModuleName) {
@@ -193,6 +175,50 @@ class Package {
193
175
  this.emitImports(context.code, type);
194
176
  type.emit(context);
195
177
  context.code.closeFile(filePath);
178
+ this.emitValidators(context, type);
179
+ }
180
+ }
181
+ emitValidators({ code, runtimeTypeChecking }, type) {
182
+ if (!runtimeTypeChecking) {
183
+ return;
184
+ }
185
+ if (type.parameterValidators.length === 0 && type.structValidator == null) {
186
+ return;
187
+ }
188
+ emit.call(this, (0, path_1.join)(this.directory, `${this.packageName}_${type.name}__runtime_type_checks.go`), false);
189
+ emit.call(this, (0, path_1.join)(this.directory, `${this.packageName}_${type.name}__no_runtime_type_checking.go`), true);
190
+ function emit(filePath, forNoOp) {
191
+ code.openFile(filePath);
192
+ // Conditional compilation tag...
193
+ code.line(`//go:build ${forNoOp ? '' : '!'}no_runtime_type_checking`);
194
+ // For go1.16 compatibility
195
+ code.line(`// +build ${forNoOp ? '' : '!'}no_runtime_type_checking`);
196
+ code.line();
197
+ this.emitHeader(code);
198
+ if (!forNoOp) {
199
+ const specialDependencies = (0, dependencies_1.reduceSpecialDependencies)(...type.parameterValidators.map((v) => v.specialDependencies), ...(type.structValidator
200
+ ? [type.structValidator.specialDependencies]
201
+ : []));
202
+ importGoModules(code, [
203
+ ...(0, dependencies_1.toImportedModules)(specialDependencies, this),
204
+ ...Array.from(new Set([
205
+ ...(type.structValidator?.dependencies ?? []),
206
+ ...type.parameterValidators.flatMap((v) => v.dependencies),
207
+ ].map((mod) => mod.goModuleName)))
208
+ .filter((mod) => mod !== this.goModuleName)
209
+ .map((mod) => ({ module: mod })),
210
+ ]);
211
+ code.line();
212
+ }
213
+ else {
214
+ code.line('// Building without runtime type checking enabled, so all the below just return nil');
215
+ code.line();
216
+ }
217
+ type.structValidator?.emitImplementation(code, this, forNoOp);
218
+ for (const validator of type.parameterValidators) {
219
+ validator.emitImplementation(code, this, forNoOp);
220
+ }
221
+ code.closeFile(filePath);
196
222
  }
197
223
  }
198
224
  emitInternal(context) {
@@ -200,9 +226,9 @@ class Package {
200
226
  return;
201
227
  }
202
228
  const code = context.code;
203
- const fileName = (0, path_1.join)(this.directory, INTERNAL_PACKAGE_NAME, 'types.go');
229
+ const fileName = (0, path_1.join)(this.directory, dependencies_1.INTERNAL_PACKAGE_NAME, 'types.go');
204
230
  code.openFile(fileName);
205
- code.line(`package ${INTERNAL_PACKAGE_NAME}`);
231
+ code.line(`package ${dependencies_1.INTERNAL_PACKAGE_NAME}`);
206
232
  const imports = new Set();
207
233
  for (const alias of this.embeddedTypes.values()) {
208
234
  if (!alias.foriegnType) {
@@ -321,7 +347,7 @@ class RootPackage extends Package {
321
347
  code.line(`package ${runtime_1.JSII_INIT_PACKAGE}`);
322
348
  code.line();
323
349
  const toImport = [
324
- JSII_RT_MODULE,
350
+ dependencies_1.JSII_RT_MODULE,
325
351
  { module: 'embed', alias: '_' },
326
352
  ];
327
353
  if (dependencies.length > 0) {
@@ -391,11 +417,6 @@ function determineMajorVersionSuffix(version) {
391
417
  }
392
418
  return `/v${sv.major}`;
393
419
  }
394
- const JSII_RT_MODULE = {
395
- alias: runtime_1.JSII_RT_ALIAS,
396
- module: runtime_1.JSII_RT_PACKAGE_NAME,
397
- };
398
- const GO_REFLECT = { module: 'reflect' };
399
420
  function importGoModules(code, modules) {
400
421
  if (modules.length === 0) {
401
422
  return;
@@ -1,9 +1,10 @@
1
1
  import { CodeMaker } from 'codemaker';
2
+ import { EmitContext } from '../emit-context';
2
3
  import { GoClassConstructor } from '../types';
3
4
  export declare class ClassConstructor {
4
5
  readonly parent: GoClassConstructor;
5
6
  constructor(parent: GoClassConstructor);
6
- emit(code: CodeMaker): void;
7
+ emit({ code, runtimeTypeChecking }: EmitContext): void;
7
8
  emitOverride(code: CodeMaker, instanceVar: string): void;
8
9
  }
9
10
  //# sourceMappingURL=class-constructor.d.ts.map