jsii-pacmak 1.114.1 → 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 (37) hide show
  1. package/lib/npm-modules.d.ts +1 -1
  2. package/lib/npm-modules.js +1 -3
  3. package/lib/packaging.d.ts +1 -5
  4. package/lib/packaging.js +12 -6
  5. package/lib/rosetta-assembly.d.ts +4 -0
  6. package/lib/rosetta-assembly.js +9 -3
  7. package/lib/targets/dotnet/dotnetdocgenerator.d.ts +4 -1
  8. package/lib/targets/dotnet/dotnetdocgenerator.js +66 -13
  9. package/lib/targets/dotnet/dotnetgenerator.d.ts +0 -4
  10. package/lib/targets/dotnet/dotnetgenerator.js +24 -14
  11. package/lib/targets/dotnet/dotnetruntimegenerator.js +11 -2
  12. package/lib/targets/dotnet/dotnettyperesolver.d.ts +13 -0
  13. package/lib/targets/dotnet/dotnettyperesolver.js +40 -2
  14. package/lib/targets/dotnet.d.ts +1 -1
  15. package/lib/targets/dotnet.js +6 -4
  16. package/lib/targets/go/runtime/runtime-type-checking.js +1 -0
  17. package/lib/targets/go/types/go-type-reference.d.ts +3 -0
  18. package/lib/targets/go/types/go-type-reference.js +20 -0
  19. package/lib/targets/go.js +1 -1
  20. package/lib/targets/java.d.ts +28 -4
  21. package/lib/targets/java.js +406 -217
  22. package/lib/targets/python/requirements-dev.txt +1 -1
  23. package/lib/targets/python/type-name.d.ts +18 -0
  24. package/lib/targets/python/type-name.js +59 -1
  25. package/lib/targets/python.d.ts +2 -1
  26. package/lib/targets/python.js +50 -18
  27. package/lib/targets/type-literals.d.ts +22 -0
  28. package/lib/targets/type-literals.js +39 -0
  29. package/lib/type-utils.d.ts +3 -0
  30. package/lib/type-utils.js +10 -0
  31. package/lib/type-visitor.d.ts +19 -0
  32. package/lib/type-visitor.js +47 -0
  33. package/lib/util.d.ts +18 -5
  34. package/lib/util.js +80 -13
  35. package/lib/version.d.ts +1 -1
  36. package/lib/version.js +3 -3
  37. package/package.json +12 -12
@@ -1,7 +1,7 @@
1
1
  import { JsiiModule } from './packaging';
2
2
  import { Toposorted } from './toposort';
3
3
  /**
4
- * Find all modules that need to be packagerd
4
+ * Find all modules that need to be packaged
5
5
  *
6
6
  * If the input list is empty, include the current directory.
7
7
  *
@@ -10,7 +10,7 @@ const toposort_1 = require("./toposort");
10
10
  const util_1 = require("./util");
11
11
  const logging = require("../lib/logging");
12
12
  /**
13
- * Find all modules that need to be packagerd
13
+ * Find all modules that need to be packaged
14
14
  *
15
15
  * If the input list is empty, include the current directory.
16
16
  *
@@ -66,12 +66,10 @@ async function findJsiiModules(directories, recurse) {
66
66
  }
67
67
  // outdir is either by package.json/jsii.outdir (relative to package root) or via command line (relative to cwd)
68
68
  const outputDirectory = pkg.jsii.outdir && path.resolve(realPath, pkg.jsii.outdir);
69
- const targets = [...Object.keys(pkg.jsii.targets), 'js']; // "js" is an implicit target.
70
69
  ret.push(new packaging_1.JsiiModule({
71
70
  name: pkg.name,
72
71
  moduleDirectory: realPath,
73
72
  defaultOutputDirectory: outputDirectory,
74
- availableTargets: targets,
75
73
  dependencyNames,
76
74
  }));
77
75
  }
@@ -9,10 +9,6 @@ export interface JsiiModuleOptions {
9
9
  * The module directory
10
10
  */
11
11
  moduleDirectory: string;
12
- /**
13
- * Identifier of the targets to build
14
- */
15
- availableTargets: string[];
16
12
  /**
17
13
  * Output directory where to package everything
18
14
  */
@@ -26,7 +22,6 @@ export declare class JsiiModule {
26
22
  readonly name: string;
27
23
  readonly dependencyNames: string[];
28
24
  readonly moduleDirectory: string;
29
- readonly availableTargets: string[];
30
25
  outputDirectory: string;
31
26
  private _tarball?;
32
27
  _assembly?: Assembly;
@@ -38,6 +33,7 @@ export declare class JsiiModule {
38
33
  get tarball(): string;
39
34
  load(system: TypeSystem, validate?: boolean): Promise<Assembly>;
40
35
  get assembly(): Assembly;
36
+ get availableTargets(): string[];
41
37
  cleanup(): Promise<void>;
42
38
  }
43
39
  //# sourceMappingURL=packaging.d.ts.map
package/lib/packaging.js CHANGED
@@ -6,11 +6,11 @@ const path = require("path");
6
6
  const util_1 = require("./util");
7
7
  const logging = require("../lib/logging");
8
8
  exports.DEFAULT_PACK_COMMAND = 'npm pack';
9
+ const ASSEMBLY_SUPPORTED_FEATURES = ['intersection-types'];
9
10
  class JsiiModule {
10
11
  constructor(options) {
11
12
  this.name = options.name;
12
13
  this.moduleDirectory = options.moduleDirectory;
13
- this.availableTargets = options.availableTargets;
14
14
  this.outputDirectory = options.defaultOutputDirectory;
15
15
  this.dependencyNames = options.dependencyNames ?? [];
16
16
  }
@@ -19,20 +19,19 @@ class JsiiModule {
19
19
  */
20
20
  async npmPack(packCommand = exports.DEFAULT_PACK_COMMAND) {
21
21
  this._tarball = await util_1.Scratch.make(async (tmpdir) => {
22
- const args = [];
23
22
  if (packCommand === exports.DEFAULT_PACK_COMMAND) {
24
23
  // Quoting (JSON-stringifying) the module directory in order to avoid
25
24
  // problems if there are spaces or other special characters in the path.
26
- args.push(JSON.stringify(this.moduleDirectory));
25
+ packCommand += ` ${JSON.stringify(this.moduleDirectory)}`;
27
26
  if (logging.level.valueOf() >= logging.LEVEL_VERBOSE) {
28
- args.push('--loglevel=verbose');
27
+ packCommand += ' --loglevel=verbose';
29
28
  }
30
29
  }
31
30
  else {
32
31
  // Ensure module is copied to tmpdir to ensure parallel execution does not contend on generated tarballs
33
32
  await fs.copy(this.moduleDirectory, tmpdir, { dereference: true });
34
33
  }
35
- const out = await (0, util_1.shell)(packCommand, args, {
34
+ const out = await (0, util_1.shell)(packCommand, {
36
35
  cwd: tmpdir,
37
36
  });
38
37
  // Take only the last line of npm pack which should contain the
@@ -57,7 +56,10 @@ class JsiiModule {
57
56
  }
58
57
  async load(system, validate = true) {
59
58
  return system
60
- .loadModule(this.moduleDirectory, { validate })
59
+ .loadModule(this.moduleDirectory, {
60
+ validate,
61
+ supportedFeatures: ASSEMBLY_SUPPORTED_FEATURES,
62
+ })
61
63
  .then((assembly) => (this._assembly = assembly));
62
64
  }
63
65
  get assembly() {
@@ -66,6 +68,10 @@ class JsiiModule {
66
68
  }
67
69
  return this._assembly;
68
70
  }
71
+ get availableTargets() {
72
+ // "js" is an implicit target
73
+ return [...Object.keys(this.assembly.targets ?? {}), 'js'];
74
+ }
69
75
  async cleanup() {
70
76
  if (this._tarball) {
71
77
  await this._tarball.cleanup();
@@ -11,6 +11,10 @@ import { RosettaTabletReader } from 'jsii-rosetta';
11
11
  * and then assert it in the type system.
12
12
  *
13
13
  * The check should be cheap, this gets called quite a lot.
14
+ *
15
+ * (In actual fact, Rosetta doesn't do much with the Assembly, just crawl
16
+ * all API documentations, so basically most new features would be supported...
17
+ * but we technically should do *something* here anyway).
14
18
  */
15
19
  export declare function assertSpecIsRosettaCompatible(x: spec.Assembly): asserts x is Parameters<RosettaTabletReader['addAssembly']>[0];
16
20
  //# sourceMappingURL=rosetta-assembly.d.ts.map
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.assertSpecIsRosettaCompatible = assertSpecIsRosettaCompatible;
4
+ const ROSETTA_SUPPORTED_ASSEMBLY_FEATURES = [
5
+ 'intersection-types',
6
+ ];
4
7
  /**
5
8
  * Assert that the given spec is safe to give to Rosetta
6
9
  *
@@ -12,12 +15,15 @@ exports.assertSpecIsRosettaCompatible = assertSpecIsRosettaCompatible;
12
15
  * and then assert it in the type system.
13
16
  *
14
17
  * The check should be cheap, this gets called quite a lot.
18
+ *
19
+ * (In actual fact, Rosetta doesn't do much with the Assembly, just crawl
20
+ * all API documentations, so basically most new features would be supported...
21
+ * but we technically should do *something* here anyway).
15
22
  */
16
23
  function assertSpecIsRosettaCompatible(x) {
17
- const rosettaSupportedFeatures = [];
18
- const unsupported = (x.usedFeatures ?? []).filter((f) => !rosettaSupportedFeatures.includes(f));
24
+ const unsupported = (x.usedFeatures ?? []).filter((f) => !ROSETTA_SUPPORTED_ASSEMBLY_FEATURES.includes(f));
19
25
  if (unsupported.length > 0) {
20
- throw new Error(`This assembly uses features Rosetta doesn't support yet: ${unsupported.join(', ')}`);
26
+ throw new Error(`This assembly uses features that jsii-pacmak doesn't think jsii-rosetta can handle yet: ${unsupported.join(', ')}`);
21
27
  }
22
28
  }
23
29
  //# sourceMappingURL=rosetta-assembly.js.map
@@ -1,6 +1,7 @@
1
1
  import * as spec from '@jsii/spec';
2
2
  import { CodeMaker } from 'codemaker';
3
3
  import { RosettaTabletReader, ApiLocation } from 'jsii-rosetta';
4
+ import { DotNetTypeResolver } from './dotnettyperesolver';
4
5
  /**
5
6
  * Generates the Jsii attributes and calls for the .NET runtime
6
7
  *
@@ -9,9 +10,10 @@ import { RosettaTabletReader, ApiLocation } from 'jsii-rosetta';
9
10
  export declare class DotNetDocGenerator {
10
11
  private readonly rosetta;
11
12
  private readonly assembly;
13
+ private readonly resolver;
12
14
  private readonly code;
13
15
  private readonly nameutils;
14
- constructor(code: CodeMaker, rosetta: RosettaTabletReader, assembly: spec.Assembly);
16
+ constructor(code: CodeMaker, rosetta: RosettaTabletReader, assembly: spec.Assembly, resolver: DotNetTypeResolver);
15
17
  /**
16
18
  * Emits all documentation depending on what is available in the jsii model
17
19
  *
@@ -31,5 +33,6 @@ export declare class DotNetDocGenerator {
31
33
  private convertExample;
32
34
  private convertSamplesInMarkdown;
33
35
  private emitXmlDoc;
36
+ private renderTypeForDocs;
34
37
  }
35
38
  //# sourceMappingURL=dotnetdocgenerator.d.ts.map
@@ -7,15 +7,27 @@ const xmlbuilder = require("xmlbuilder");
7
7
  const _utils_1 = require("../_utils");
8
8
  const nameutils_1 = require("./nameutils");
9
9
  const rosetta_assembly_1 = require("../../rosetta-assembly");
10
+ const type_utils_1 = require("../../type-utils");
11
+ const type_visitor_1 = require("../../type-visitor");
12
+ // Define some tokens that will be turned into literal < and > in XML comments.
13
+ // This will be used by a function later on that needs to output literal tokens,
14
+ // in a string where they would usually be escaped into &lt; and &gt;
15
+ //
16
+ // We use a random string in here so the actual token values cannot be predicted
17
+ // in advance, so that an attacker can not use this knowledge to inject the tokens
18
+ // literally into doc comments, and perform an XSS attack that way.
19
+ const L_ANGLE = `@l${Math.random()}@`;
20
+ const R_ANGLE = `@r${Math.random()}@`;
10
21
  /**
11
22
  * Generates the Jsii attributes and calls for the .NET runtime
12
23
  *
13
24
  * Uses the same instance of CodeMaker as the rest of the code
14
25
  */
15
26
  class DotNetDocGenerator {
16
- constructor(code, rosetta, assembly) {
27
+ constructor(code, rosetta, assembly, resolver) {
17
28
  this.rosetta = rosetta;
18
29
  this.assembly = assembly;
30
+ this.resolver = resolver;
19
31
  this.nameutils = new nameutils_1.DotNetNameUtils();
20
32
  this.code = code;
21
33
  }
@@ -35,34 +47,44 @@ class DotNetDocGenerator {
35
47
  this.emitXmlDoc('summary', (0, _utils_1.renderSummary)(obj.docs));
36
48
  // Handling parameters only if the obj is a method
37
49
  const objMethod = obj;
38
- if (objMethod.parameters) {
50
+ if (objMethod && objMethod.parameters) {
39
51
  objMethod.parameters.forEach((param) => {
40
52
  // Remove any slug `@` from the parameter name - it's not supposed to show up here.
41
53
  const paramName = this.nameutils
42
54
  .convertParameterName(param.name)
43
55
  .replace(/^@/, '');
44
- this.emitXmlDoc('param', param.docs?.summary ?? '', {
56
+ const unionHint = (0, type_utils_1.containsUnionType)(param.type)
57
+ ? `Type union: ${this.renderTypeForDocs(param.type)}`
58
+ : '';
59
+ this.emitXmlDoc('param', combineSentences(param.docs?.summary, unionHint), {
45
60
  attributes: { name: paramName },
46
61
  });
47
62
  });
48
63
  }
49
- // At this pdocfx namespacedocd a valid instance of docs
50
- if (!docs) {
51
- return;
52
- }
53
- if (docs.returns) {
54
- this.emitXmlDoc('returns', docs.returns);
64
+ const returnUnionHint = objMethod.returns && (0, type_utils_1.containsUnionType)(objMethod.returns.type)
65
+ ? `Type union: ${this.renderTypeForDocs(objMethod.returns.type)}`
66
+ : '';
67
+ if (docs?.returns || returnUnionHint) {
68
+ this.emitXmlDoc('returns', combineSentences(docs?.returns, returnUnionHint));
55
69
  }
70
+ const propUnionHint = spec.isProperty(obj) && (0, type_utils_1.containsUnionType)(obj.type)
71
+ ? `Type union: ${this.renderTypeForDocs(obj.type)}`
72
+ : '';
56
73
  // Remarks does not use emitXmlDoc() because the remarks can contain code blocks
57
74
  // which are fenced with <code> tags, which would be escaped to
58
75
  // &lt;code&gt; if we used the xml builder.
59
- const remarks = this.renderRemarks(docs, apiLocation);
60
- if (remarks.length > 0) {
76
+ const remarks = this.renderRemarks(docs ?? {}, apiLocation);
77
+ if (remarks.length > 0 || propUnionHint) {
61
78
  this.code.line('/// <remarks>');
62
79
  remarks.forEach((r) => this.code.line(`/// ${r}`.trimRight()));
80
+ if (propUnionHint) {
81
+ // Very likely to contain < and > from `Dictionary<...>`, but we also want the literal angle brackets
82
+ // from `<see cref="...">`.
83
+ this.code.line(`/// <para>${unescapeAngleMarkers(escapeAngleBrackets(propUnionHint))}</para>`);
84
+ }
63
85
  this.code.line('/// </remarks>');
64
86
  }
65
- if (docs.example) {
87
+ if (docs?.example) {
66
88
  this.code.line('/// <example>');
67
89
  this.emitXmlDoc('code', this.convertExample(docs.example, apiLocation));
68
90
  this.code.line('/// </example>');
@@ -139,7 +161,8 @@ class DotNetDocGenerator {
139
161
  for (const [name, value] of Object.entries(attributes)) {
140
162
  xml.att(name, value);
141
163
  }
142
- const xmlstring = xml.end({ allowEmpty: true, pretty: false });
164
+ // Unescape angle brackets that may have been injected by `renderTypeForDocs`
165
+ const xmlstring = unescapeAngleMarkers(xml.end({ allowEmpty: true, pretty: false }));
143
166
  const trimLeft = tag !== 'code';
144
167
  for (const line of xmlstring
145
168
  .split('\n')
@@ -147,6 +170,22 @@ class DotNetDocGenerator {
147
170
  this.code.line(`/// ${line}`);
148
171
  }
149
172
  }
173
+ renderTypeForDocs(x) {
174
+ return (0, type_visitor_1.visitTypeReference)(x, {
175
+ named: (ref) => `${L_ANGLE}see cref="${this.resolver.toNativeFqn(ref.fqn)}" /${R_ANGLE}`,
176
+ primitive: (ref) => this.resolver.toDotNetType(ref),
177
+ collection: (ref) => {
178
+ switch (ref.collection.kind) {
179
+ case spec.CollectionKind.Array:
180
+ return `(${this.renderTypeForDocs(ref.collection.elementtype)})[]`;
181
+ case spec.CollectionKind.Map:
182
+ return `Dictionary<string, ${this.renderTypeForDocs(ref.collection.elementtype)}>`;
183
+ }
184
+ },
185
+ union: (ref) => `either ${ref.union.types.map((x) => this.renderTypeForDocs(x)).join(' or ')}`,
186
+ intersection: (ref) => `${ref.intersection.types.map((x) => this.renderTypeForDocs(x)).join(' + ')}`,
187
+ });
188
+ }
150
189
  }
151
190
  exports.DotNetDocGenerator = DotNetDocGenerator;
152
191
  /**
@@ -159,4 +198,18 @@ function shouldMentionStability(s) {
159
198
  // Don't render "stable" or "external", those are both stable by implication
160
199
  return s === spec.Stability.Deprecated || s === spec.Stability.Experimental;
161
200
  }
201
+ function combineSentences(...xs) {
202
+ return xs.filter((x) => x).join('. ');
203
+ }
204
+ function escapeAngleBrackets(x) {
205
+ return x.replace(/</g, '&lt;').replace(/>/g, '&gt;');
206
+ }
207
+ /**
208
+ * Replace the special angle markers produced by renderTypeForDocs with literal angle brackets
209
+ */
210
+ function unescapeAngleMarkers(x) {
211
+ return x
212
+ .replace(new RegExp(L_ANGLE, 'g'), '<')
213
+ .replace(new RegExp(R_ANGLE, 'g'), '>');
214
+ }
162
215
  //# sourceMappingURL=dotnetdocgenerator.js.map
@@ -72,10 +72,6 @@ export declare class DotNetGenerator extends Generator {
72
72
  * Used to figure out if the override or virtual keywords are necessary.
73
73
  */
74
74
  private isMemberDefinedOnAncestor;
75
- /**
76
- * Renders method parameters string
77
- */
78
- private renderMethodParameters;
79
75
  /**
80
76
  * Renders parameters string for methods or constructors
81
77
  */
@@ -42,7 +42,7 @@ class DotNetGenerator extends generator_1.Generator {
42
42
  generate(fingerprint) {
43
43
  this.typeresolver = new dotnettyperesolver_1.DotNetTypeResolver(this.assembly, (fqn) => this.findModule(fqn), (fqn) => this.findType(fqn), this.assembliesCurrentlyBeingCompiled);
44
44
  this.dotnetRuntimeGenerator = new dotnetruntimegenerator_1.DotNetRuntimeGenerator(this.code, this.typeresolver);
45
- this.dotnetDocGenerator = new dotnetdocgenerator_1.DotNetDocGenerator(this.code, this.rosetta, this.assembly);
45
+ this.dotnetDocGenerator = new dotnetdocgenerator_1.DotNetDocGenerator(this.code, this.rosetta, this.assembly, this.typeresolver);
46
46
  this.emitAssemblyDocs();
47
47
  // We need to resolve the dependency tree
48
48
  this.typeresolver.resolveNamespacesDependencies();
@@ -165,7 +165,8 @@ class DotNetGenerator extends generator_1.Generator {
165
165
  ? this.typeresolver.toDotNetType(method.returns.type)
166
166
  : 'void';
167
167
  const nullable = method.returns?.optional ? '?' : '';
168
- this.code.line(`${returnType}${nullable} ${this.nameutils.convertMethodName(method.name)}(${this.renderMethodParameters(method)});`);
168
+ const { parameters, whereClause, typeParameters } = this.typeresolver.renderGenericParameters(method.parameters);
169
+ this.code.line(`${returnType}${nullable} ${this.nameutils.convertMethodName(method.name)}${typeParameters}(${this.renderParametersString(parameters)})${whereClause};`);
169
170
  }
170
171
  onInterfaceMethodOverload(ifc, overload, _originalMethod) {
171
172
  this.onInterfaceMethod(ifc, overload);
@@ -187,7 +188,12 @@ class DotNetGenerator extends generator_1.Generator {
187
188
  memberName: prop.name,
188
189
  });
189
190
  this.dotnetRuntimeGenerator.emitAttributesForProperty(prop);
190
- const propType = this.typeresolver.toDotNetType(prop.type);
191
+ // Unfortunately we can only render this as one type. We'll take the first one.
192
+ let apparentType = prop.type;
193
+ if (spec.isIntersectionTypeReference(apparentType)) {
194
+ apparentType = apparentType.intersection.types[0];
195
+ }
196
+ const propType = this.typeresolver.toDotNetType(apparentType);
191
197
  const propName = this.nameutils.convertPropertyName(prop.name);
192
198
  if (prop.optional) {
193
199
  this.code.line('[Amazon.JSII.Runtime.Deputy.JsiiOptional]');
@@ -253,7 +259,11 @@ class DotNetGenerator extends generator_1.Generator {
253
259
  });
254
260
  this.dotnetRuntimeGenerator.emitDeprecatedAttributeIfNecessary(initializer);
255
261
  if (initializer.parameters) {
256
- parametersDefinition = this.renderParametersString(initializer.parameters);
262
+ const { parameters, whereClause } = this.typeresolver.renderGenericParameters(initializer.parameters);
263
+ if (whereClause) {
264
+ throw new Error('C# does not allow generic parameters to a constructor');
265
+ }
266
+ parametersDefinition = this.renderParametersString(parameters);
257
267
  for (const p of initializer.parameters) {
258
268
  parametersBase += `${this.nameutils.convertParameterName(p.name)}`;
259
269
  // If this is not the last parameter, append ,
@@ -391,7 +401,8 @@ class DotNetGenerator extends generator_1.Generator {
391
401
  const access = this.renderAccessLevel(method);
392
402
  const methodName = this.nameutils.convertMethodName(method.name);
393
403
  const isOptional = method.returns && method.returns.optional ? '?' : '';
394
- const signature = `${returnType}${isOptional} ${methodName}(${this.renderMethodParameters(method)})`;
404
+ const { parameters, whereClause, typeParameters } = this.typeresolver.renderGenericParameters(method.parameters);
405
+ const signature = `${returnType}${isOptional} ${methodName}${typeParameters}(${this.renderParametersString(parameters)})${whereClause}`;
395
406
  this.dotnetDocGenerator.emitDocs(method, {
396
407
  api: 'member',
397
408
  fqn: definingType.fqn,
@@ -514,12 +525,6 @@ class DotNetGenerator extends generator_1.Generator {
514
525
  }
515
526
  return false;
516
527
  }
517
- /**
518
- * Renders method parameters string
519
- */
520
- renderMethodParameters(method) {
521
- return this.renderParametersString(method.parameters);
522
- }
523
528
  /**
524
529
  * Renders parameters string for methods or constructors
525
530
  */
@@ -728,10 +733,15 @@ class DotNetGenerator extends generator_1.Generator {
728
733
  const access = this.renderAccessLevel(prop);
729
734
  const staticKeyWord = prop.static ? 'static ' : '';
730
735
  const propName = this.nameutils.convertPropertyName(prop.name);
731
- const propTypeFQN = this.typeresolver.toDotNetType(prop.type);
736
+ // Unfortunately we can only render this as one type. We'll take the first one.
737
+ let apparentType = prop.type;
738
+ if (spec.isIntersectionTypeReference(apparentType)) {
739
+ apparentType = apparentType.intersection.types[0];
740
+ }
741
+ const propTypeFQN = this.typeresolver.toDotNetType(apparentType);
732
742
  const isOptional = prop.optional ? '?' : '';
733
743
  // We need to use a backing field so we can perform type checking if the property type is a union, and this is a struct.
734
- const backingFieldName = spec.isInterfaceType(cls) && datatype && containsUnionType(prop.type)
744
+ const backingFieldName = spec.isInterfaceType(cls) && datatype && containsUnionType(apparentType)
735
745
  ? // We down-case the first letter, private fields are conventionally named with a _ prefix, and a camelCase name.
736
746
  `_${propName.replace(/[A-Z]/, (c) => c.toLowerCase())}`
737
747
  : undefined;
@@ -773,7 +783,7 @@ class DotNetGenerator extends generator_1.Generator {
773
783
  const reflectCls = this.reflectAssembly.findType(cls.fqn);
774
784
  const syntheticParam = new reflect.Parameter(reflectCls.system, reflectCls, new reflect.Method(reflectCls.system, reflectCls.assembly, reflectCls, reflectCls, { name: '<synthetic>' }), {
775
785
  name: 'value',
776
- type: prop.type,
786
+ type: apparentType,
777
787
  optional: prop.optional,
778
788
  });
779
789
  if (backingFieldName) {
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DotNetRuntimeGenerator = void 0;
4
4
  const spec = require("@jsii/spec");
5
5
  const nameutils_1 = require("./nameutils");
6
+ const type_literals_1 = require("../type-literals");
6
7
  /**
7
8
  * Generates the Jsii attributes and calls for the jsii .NET runtime
8
9
  *
@@ -143,8 +144,16 @@ class DotNetRuntimeGenerator {
143
144
  const paramTypes = new Array();
144
145
  const params = new Array();
145
146
  if (method.parameters) {
146
- for (const param of method.parameters) {
147
- paramTypes.push(`typeof(${this.typeresolver.toDotNetType(param.type)}${param.variadic ? '[]' : ''})`);
147
+ const { parameters } = this.typeresolver.renderGenericParameters(method.parameters);
148
+ for (const param of parameters) {
149
+ if ((0, type_literals_1.isLiteralTypeReference)(param.type)) {
150
+ // Generic type argument -- since we don't actually need this type anyway because we don't use it
151
+ // for method resolution, we can just use Object.
152
+ paramTypes.push('typeof(System.Object)');
153
+ }
154
+ else {
155
+ paramTypes.push(`typeof(${this.typeresolver.toDotNetType(param.type)}${param.variadic ? '[]' : ''})`);
156
+ }
148
157
  params.push(this.nameutils.convertParameterName(param.name));
149
158
  }
150
159
  }
@@ -48,6 +48,19 @@ export declare class DotNetTypeResolver {
48
48
  * Translates a collection in jsii to the name of a native .NET collection
49
49
  */
50
50
  private toDotNetCollectionName;
51
+ /**
52
+ * Render generics for function parameters; updates parameters replacing generic types with type parameters
53
+ *
54
+ * FIXME: This is the wrong way around. It is better to have the renderer
55
+ * assign a unique name and return the fact that a type needs generics. That
56
+ * way it's trivially possible to represent "union-of-intersections", which
57
+ * otherwise will be hard. See the way it's done for Java.
58
+ */
59
+ renderGenericParameters(inParameters: spec.Parameter[] | undefined): {
60
+ parameters: spec.Parameter[];
61
+ typeParameters: string;
62
+ whereClause: string;
63
+ };
51
64
  }
52
65
  export {};
53
66
  //# sourceMappingURL=dotnettyperesolver.d.ts.map
@@ -5,6 +5,7 @@ const spec = require("@jsii/spec");
5
5
  const codemaker_1 = require("codemaker");
6
6
  const filegenerator_1 = require("./filegenerator");
7
7
  const nameutils_1 = require("./nameutils");
8
+ const type_literals_1 = require("../type-literals");
8
9
  class DotNetTypeResolver {
9
10
  constructor(assembly, findModule, findType, assembliesCurrentlyBeingCompiled) {
10
11
  this.assembliesCurrentlyBeingCompiled = assembliesCurrentlyBeingCompiled;
@@ -100,12 +101,12 @@ class DotNetTypeResolver {
100
101
  return this.toDotNetCollection(typeref);
101
102
  }
102
103
  else if (spec.isNamedTypeReference(typeref)) {
103
- return this.toNativeFqn(typeref.fqn);
104
+ return (0, type_literals_1.literalTypeReference)(typeref) ?? this.toNativeFqn(typeref.fqn);
104
105
  }
105
106
  else if (spec.isUnionTypeReference(typeref)) {
106
107
  return 'object';
107
108
  }
108
- throw new Error(`Invalid type reference: ${JSON.stringify(typeref)}`);
109
+ throw new Error(`Unresolvable type reference: ${JSON.stringify(typeref)}`);
109
110
  }
110
111
  /**
111
112
  * Translates any jsii type to the name of its corresponding .NET type (as a .NET string).
@@ -219,6 +220,43 @@ class DotNetTypeResolver {
219
220
  throw new Error(`Unsupported collection kind: ${ref.collection.kind}`);
220
221
  }
221
222
  }
223
+ /**
224
+ * Render generics for function parameters; updates parameters replacing generic types with type parameters
225
+ *
226
+ * FIXME: This is the wrong way around. It is better to have the renderer
227
+ * assign a unique name and return the fact that a type needs generics. That
228
+ * way it's trivially possible to represent "union-of-intersections", which
229
+ * otherwise will be hard. See the way it's done for Java.
230
+ */
231
+ renderGenericParameters(inParameters) {
232
+ const parameters = new Array();
233
+ const typeParameters = new Array();
234
+ const genericConstraints = new Array();
235
+ for (const p of inParameters ?? []) {
236
+ if (spec.isIntersectionTypeReference(p.type)) {
237
+ const typeParameterName = `T${Object.keys(genericConstraints).length + 1}`;
238
+ parameters.push({
239
+ name: p.name,
240
+ docs: p.docs,
241
+ optional: p.optional,
242
+ variadic: p.variadic,
243
+ type: (0, type_literals_1.makeLiteralTypeReference)(typeParameterName),
244
+ });
245
+ typeParameters.push(typeParameterName);
246
+ genericConstraints.push(`where ${typeParameterName}: ${p.type.intersection.types
247
+ .map((t) => this.toDotNetType(t))
248
+ .join(', ')}`);
249
+ }
250
+ else {
251
+ parameters.push(p);
252
+ }
253
+ }
254
+ return {
255
+ parameters,
256
+ typeParameters: typeParameters.length > 0 ? `<${typeParameters.join(', ')}>` : '',
257
+ whereClause: genericConstraints.length > 0 ? ` ${genericConstraints.join(' ')}` : '',
258
+ };
259
+ }
222
260
  }
223
261
  exports.DotNetTypeResolver = DotNetTypeResolver;
224
262
  //# sourceMappingURL=dotnettyperesolver.js.map
@@ -3,7 +3,7 @@ import { TargetBuilder, BuildOptions } from '../builder';
3
3
  import { JsiiModule } from '../packaging';
4
4
  import { PackageInfo, Target, TargetOptions } from '../target';
5
5
  import { DotNetGenerator } from './dotnet/dotnetgenerator';
6
- export declare const TARGET_FRAMEWORK = "netcoreapp3.1";
6
+ export declare const TARGET_FRAMEWORK = "net6.0";
7
7
  /**
8
8
  * Build .NET packages all together, by generating an aggregate solution file
9
9
  */
@@ -10,7 +10,7 @@ const util_1 = require("../util");
10
10
  const dotnetgenerator_1 = require("./dotnet/dotnetgenerator");
11
11
  const version_utils_1 = require("./version-utils");
12
12
  const _1 = require(".");
13
- exports.TARGET_FRAMEWORK = 'netcoreapp3.1';
13
+ exports.TARGET_FRAMEWORK = 'net6.0';
14
14
  /**
15
15
  * Build .NET packages all together, by generating an aggregate solution file
16
16
  */
@@ -36,7 +36,7 @@ class DotnetBuilder {
36
36
  scratchDirs.push(tempSourceDir);
37
37
  // Build solution
38
38
  logging.debug('Building .NET');
39
- await (0, util_1.shell)('dotnet', ['build', '--force', '--configuration', 'Release'], {
39
+ await (0, util_1.subprocess)('dotnet', ['build', '--force', '--configuration', 'Release'], {
40
40
  cwd: tempSourceDir.directory,
41
41
  retry: { maxAttempts: 5 },
42
42
  });
@@ -68,8 +68,10 @@ class DotnetBuilder {
68
68
  });
69
69
  }
70
70
  // Use 'dotnet' command line tool to build a solution file from these csprojs
71
- await (0, util_1.shell)('dotnet', ['new', 'sln', '-n', 'JsiiBuild'], { cwd: tmpDir });
72
- await (0, util_1.shell)('dotnet', ['sln', 'add', ...csProjs], { cwd: tmpDir });
71
+ await (0, util_1.subprocess)('dotnet', ['new', 'sln', '-n', 'JsiiBuild'], {
72
+ cwd: tmpDir,
73
+ });
74
+ await (0, util_1.subprocess)('dotnet', ['sln', 'add', ...csProjs], { cwd: tmpDir });
73
75
  await this.generateNuGetConfigForLocalDeps(tmpDir);
74
76
  return ret;
75
77
  });
@@ -179,6 +179,7 @@ class Validation {
179
179
  return Validation.collectionCheck(expression, description, typeMap.value);
180
180
  case 'primitive':
181
181
  case 'void':
182
+ case 'intersection':
182
183
  return undefined;
183
184
  }
184
185
  }
@@ -18,6 +18,9 @@ type TypeMap = {
18
18
  } | {
19
19
  readonly type: 'union';
20
20
  readonly value: readonly GoTypeRef[];
21
+ } | {
22
+ readonly type: 'intersection';
23
+ readonly value: readonly GoTypeRef[];
21
24
  } | {
22
25
  readonly type: 'interface';
23
26
  readonly value: GoTypeRef;
@@ -63,6 +63,9 @@ class GoTypeRef {
63
63
  if (!opaqueUnionType && ref.unionOfTypes) {
64
64
  return ref.unionOfTypes.some((item) => containsDate(item, opaqueUnionType));
65
65
  }
66
+ if (!opaqueUnionType && ref.intersectionOfTypes) {
67
+ return ref.intersectionOfTypes.some((item) => containsDate(item, opaqueUnionType));
68
+ }
66
69
  return false;
67
70
  }
68
71
  }
@@ -111,6 +114,13 @@ class GoTypeRef {
111
114
  }
112
115
  }
113
116
  break;
117
+ case 'intersection':
118
+ if (!this.options.opaqueUnionTypes) {
119
+ for (const t of this.typeMap.value) {
120
+ ret.push(...t.dependencies);
121
+ }
122
+ }
123
+ break;
114
124
  case 'void':
115
125
  case 'primitive':
116
126
  break;
@@ -164,6 +174,12 @@ class GoTypeRef {
164
174
  value: ref.reference.unionOfTypes.map((typeRef) => new GoTypeRef(this.root, typeRef, this.options)),
165
175
  };
166
176
  }
177
+ else if (ref.reference.intersectionOfTypes) {
178
+ return {
179
+ type: 'intersection',
180
+ value: ref.reference.intersectionOfTypes.map((typeRef) => new GoTypeRef(this.root, typeRef, this.options)),
181
+ };
182
+ }
167
183
  else if (ref.reference.void) {
168
184
  return { type: 'void' };
169
185
  }
@@ -195,6 +211,10 @@ class GoTypeRef {
195
211
  return `${prefix}${typeMap.value.namespace}.${baseName}`;
196
212
  }
197
213
  }
214
+ else if (typeMap.type === 'intersection') {
215
+ const components = typeMap.value.map((inner) => this.scopedTypeName(inner.typeMap, scope, false));
216
+ return `interface{ ${components.join(';')} }`;
217
+ }
198
218
  else if (typeMap.type === 'union') {
199
219
  return 'interface{}';
200
220
  }