jsii-pacmak 1.114.1 → 1.116.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/lib/npm-modules.d.ts +1 -1
- package/lib/npm-modules.js +1 -3
- package/lib/packaging.d.ts +1 -5
- package/lib/packaging.js +12 -6
- package/lib/rosetta-assembly.d.ts +4 -0
- package/lib/rosetta-assembly.js +9 -3
- package/lib/targets/dotnet/dotnetdocgenerator.d.ts +4 -1
- package/lib/targets/dotnet/dotnetdocgenerator.js +66 -13
- package/lib/targets/dotnet/dotnetgenerator.d.ts +0 -4
- package/lib/targets/dotnet/dotnetgenerator.js +24 -14
- package/lib/targets/dotnet/dotnetruntimegenerator.js +11 -2
- package/lib/targets/dotnet/dotnettyperesolver.d.ts +13 -0
- package/lib/targets/dotnet/dotnettyperesolver.js +40 -2
- package/lib/targets/dotnet.d.ts +1 -1
- package/lib/targets/dotnet.js +6 -4
- package/lib/targets/go/runtime/runtime-type-checking.js +1 -0
- package/lib/targets/go/types/go-type-reference.d.ts +3 -0
- package/lib/targets/go/types/go-type-reference.js +20 -0
- package/lib/targets/go.js +1 -1
- package/lib/targets/java.d.ts +28 -4
- package/lib/targets/java.js +408 -217
- package/lib/targets/python/requirements-dev.txt +1 -1
- package/lib/targets/python/type-name.d.ts +18 -0
- package/lib/targets/python/type-name.js +59 -1
- package/lib/targets/python.d.ts +2 -1
- package/lib/targets/python.js +50 -18
- package/lib/targets/type-literals.d.ts +22 -0
- package/lib/targets/type-literals.js +39 -0
- package/lib/type-utils.d.ts +3 -0
- package/lib/type-utils.js +10 -0
- package/lib/type-visitor.d.ts +19 -0
- package/lib/type-visitor.js +47 -0
- package/lib/util.d.ts +18 -5
- package/lib/util.js +80 -13
- package/lib/version.d.ts +1 -1
- package/lib/version.js +3 -3
- package/package.json +12 -12
package/lib/npm-modules.d.ts
CHANGED
package/lib/npm-modules.js
CHANGED
|
@@ -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
|
|
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
|
}
|
package/lib/packaging.d.ts
CHANGED
|
@@ -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
|
-
|
|
25
|
+
packCommand += ` ${JSON.stringify(this.moduleDirectory)}`;
|
|
27
26
|
if (logging.level.valueOf() >= logging.LEVEL_VERBOSE) {
|
|
28
|
-
|
|
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,
|
|
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, {
|
|
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
|
package/lib/rosetta-assembly.js
CHANGED
|
@@ -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
|
|
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
|
|
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 < and >
|
|
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
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
// <code> 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
|
|
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
|
-
|
|
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, '<').replace(/>/g, '>');
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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(
|
|
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:
|
|
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
|
-
|
|
147
|
-
|
|
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(`
|
|
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
|
package/lib/targets/dotnet.d.ts
CHANGED
|
@@ -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 = "
|
|
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
|
*/
|
package/lib/targets/dotnet.js
CHANGED
|
@@ -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 = '
|
|
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.
|
|
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.
|
|
72
|
-
|
|
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
|
});
|
|
@@ -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
|
}
|