diff --git a/README.md b/README.md
index a89d6422..76911407 100644
--- a/README.md
+++ b/README.md
@@ -97,6 +97,35 @@ original module. This code depends on the following maven package (should be def
The output directory will also include a tarball `generated@0.0.0.jsii.tgz` that must be bundled in your project.
+### C# Output
+
+To produce a C# module from your source, use the `csharp` option:
+
+```ts
+await srcmak('srcdir', {
+ csharp: {
+ outdir: '/path/to/project/root',
+ namespace: 'HelloWorld'
+ }
+});
+```
+
+Or the `--csharp-*` switches in the CLI:
+
+```bash
+$ jsii-srcmak /src/dir --csharp-outdir=dir --csharp-namespace=HelloWorld
+```
+
+* The `outdir`/`--csharp-outdir` option points to the root directory of your C# project.
+* The `package`/`--csharp-namespace` option is the C# root namespace.
+
+The output directory will include a C# project that corresponds to the
+original module. This code depends on the following NuGet package (It is already defined as a dependency in the generated project):
+
+- [jsii](https://www.nuget.org/packages/Amazon.JSII.Runtime/)
+
+The output directory will also include a tarball `generated@0.0.0.jsii.tgz` that must be bundled in your project (It is already included as an embedded resource in the generated project).
+
### Entrypoint
The `entrypoint` option can be used to customize the name of the typescript entrypoint (default is `index.ts`).
diff --git a/src/cli.ts b/src/cli.ts
index 77eb006a..9d0017db 100644
--- a/src/cli.ts
+++ b/src/cli.ts
@@ -11,6 +11,8 @@ async function main() {
.option('python-module-name', { desc: 'python module name', type: 'string' })
.option('java-outdir', { desc: 'java output directory (requires --java-package)', type: 'string' })
.option('java-package', { desc: 'the java package (namespace) to use for all generated types', type: 'string' })
+ .option('csharp-outdir', { desc: 'C# output directory (requires --csharp-namespace)', type: 'string' })
+ .option('csharp-namespace', { desc: 'the C# namespace to use for all generated types', type: 'string' })
.showHelpOnFail(true)
.help();
@@ -30,6 +32,7 @@ async function main() {
...parseJsiiOptions(),
...parsePythonOptions(),
...parseJavaOptions(),
+ ...parseCSharpOptions(),
});
function parseJsiiOptions() {
@@ -70,6 +73,20 @@ async function main() {
}
}
+ function parseCSharpOptions() {
+ const outdir = argv['csharp-outdir'];
+ const namespace = argv['csharp-namespace'];
+ if (!outdir && !namespace) { return undefined; }
+ if (!outdir) { throw new Error('--csharp-outdir is required'); }
+ if (!namespace) { throw new Error('--csharp-namespace is required'); }
+ return {
+ csharp: {
+ outdir: outdir,
+ namespace: namespace,
+ },
+ }
+ }
+
function parseDepOption() {
if (argv.dep?.length === 0) { return undefined; }
return {
diff --git a/src/compile.ts b/src/compile.ts
index 3fce96df..b10f1f32 100644
--- a/src/compile.ts
+++ b/src/compile.ts
@@ -84,6 +84,13 @@ export async function compile(workdir: string, options: Options) {
};
}
+ if (options.csharp) {
+ targets.dotnet = {
+ namespace: options.csharp.namespace,
+ packageId: options.csharp.namespace,
+ };
+ }
+
await fs.writeFile(path.join(workdir, 'package.json'), JSON.stringify(pkg, undefined, 2));
await exec(compilerModule, args, {
diff --git a/src/options.ts b/src/options.ts
index 7642740a..4432beef 100644
--- a/src/options.ts
+++ b/src/options.ts
@@ -39,6 +39,13 @@ export interface Options {
* @default - java is not generated
*/
java?: JavaOutputOptions;
+
+ /**
+ * Produces C# code.
+ *
+ * @default - C# is not generated
+ */
+ csharp?: CSharpOutputOptions;
}
export interface JsiiOutputOptions {
@@ -77,3 +84,18 @@ export interface JavaOutputOptions {
*/
package: string;
}
+
+export interface CSharpOutputOptions {
+ /**
+ * Base root directory.
+ */
+ outdir: string;
+
+ /**
+ * The root namespace to generate types in
+ *
+ * This must follow standard C# namespace conventions.
+ * For example, it cannot include a hyphen ('-')
+ */
+ namespace: string;
+}
diff --git a/src/srcmak.ts b/src/srcmak.ts
index d3eccee1..212769dd 100644
--- a/src/srcmak.ts
+++ b/src/srcmak.ts
@@ -44,5 +44,12 @@ export async function srcmak(srcdir: string, options: Options = { }) {
await fs.mkdirp(target); // make sure target directory exists
await ncp(source, target, { clobber: false });
}
+
+ if (options.csharp) {
+ const reldir = options.csharp.namespace;
+ const source = path.resolve(path.join(workdir, 'dist/dotnet/', reldir));
+ const target = path.join(options.csharp.outdir, reldir);
+ await fs.move(source, target, { overwrite: true });
+ }
});
}
diff --git a/src/util.ts b/src/util.ts
index 8eda36d6..507354a4 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -58,7 +58,7 @@ export async function exec(moduleName: string, args: string[] = [], options: Spa
}
/**
- * This validates that the Python module name and Java package name
+ * This validates that the Python module name, Java package name, and C# namespace
* conform to language-specific constraints.
*
* @param options Options set by the consumer
@@ -72,4 +72,8 @@ export function validateOptions(options: Options) {
if (options.java?.package.includes('-')) {
throw new Error(`Java package [${options.java.package}] may not contain "-"`);
}
+
+ if (options.csharp?.namespace.includes('-')) {
+ throw new Error(`C# namespace [${options.csharp.namespace}] may not contain "-"`);
+ }
}
diff --git a/test/__snapshots__/cli.test.ts.snap b/test/__snapshots__/cli.test.ts.snap
index 045f6409..af0c72c8 100644
--- a/test/__snapshots__/cli.test.ts.snap
+++ b/test/__snapshots__/cli.test.ts.snap
@@ -1,5 +1,372 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`csharp output 1`] = `
+Object {
+ "MyPackage/.jsii": "{
+ \\"author\\": {
+ \\"name\\": \\"generated@generated.com\\",
+ \\"roles\\": [
+ \\"author\\"
+ ]
+ },
+ \\"description\\": \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060\\",
+ \\"homepage\\": \\"http://generated\\",
+ \\"jsiiVersion\\": \\"1.12.0 (build 5ddc9f2)\\",
+ \\"license\\": \\"Apache-2.0\\",
+ \\"name\\": \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060\\",
+ \\"repository\\": {
+ \\"type\\": \\"git\\",
+ \\"url\\": \\"http://generated\\"
+ },
+ \\"schema\\": \\"jsii/0.10.0\\",
+ \\"targets\\": {
+ \\"dotnet\\": {
+ \\"namespace\\": \\"MyPackage\\",
+ \\"packageId\\": \\"MyPackage\\"
+ },
+ \\"js\\": {
+ \\"npm\\": \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060\\"
+ }
+ },
+ \\"types\\": {
+ \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Calculator\\": {
+ \\"assembly\\": \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060\\",
+ \\"docs\\": {
+ \\"summary\\": \\"A sophisticaed multi-language calculator.\\"
+ },
+ \\"fqn\\": \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Calculator\\",
+ \\"initializer\\": {},
+ \\"kind\\": \\"class\\",
+ \\"locationInModule\\": {
+ \\"filename\\": \\"lib/main.ts\\",
+ \\"line\\": 19
+ },
+ \\"methods\\": [
+ {
+ \\"docs\\": {
+ \\"summary\\": \\"Adds the two operands.\\"
+ },
+ \\"locationInModule\\": {
+ \\"filename\\": \\"lib/main.ts\\",
+ \\"line\\": 24
+ },
+ \\"name\\": \\"add\\",
+ \\"parameters\\": [
+ {
+ \\"docs\\": {
+ \\"summary\\": \\"operands.\\"
+ },
+ \\"name\\": \\"ops\\",
+ \\"type\\": {
+ \\"fqn\\": \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Operands\\"
+ }
+ }
+ ],
+ \\"returns\\": {
+ \\"type\\": {
+ \\"primitive\\": \\"number\\"
+ }
+ }
+ },
+ {
+ \\"docs\\": {
+ \\"summary\\": \\"Multiplies the two operands.\\"
+ },
+ \\"locationInModule\\": {
+ \\"filename\\": \\"lib/main.ts\\",
+ \\"line\\": 40
+ },
+ \\"name\\": \\"mul\\",
+ \\"parameters\\": [
+ {
+ \\"docs\\": {
+ \\"summary\\": \\"operands.\\"
+ },
+ \\"name\\": \\"ops\\",
+ \\"type\\": {
+ \\"fqn\\": \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Operands\\"
+ }
+ }
+ ],
+ \\"returns\\": {
+ \\"type\\": {
+ \\"primitive\\": \\"number\\"
+ }
+ }
+ },
+ {
+ \\"docs\\": {
+ \\"summary\\": \\"Subtracts the two operands.\\"
+ },
+ \\"locationInModule\\": {
+ \\"filename\\": \\"lib/main.ts\\",
+ \\"line\\": 32
+ },
+ \\"name\\": \\"sub\\",
+ \\"parameters\\": [
+ {
+ \\"docs\\": {
+ \\"summary\\": \\"operands.\\"
+ },
+ \\"name\\": \\"ops\\",
+ \\"type\\": {
+ \\"fqn\\": \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Operands\\"
+ }
+ }
+ ],
+ \\"returns\\": {
+ \\"type\\": {
+ \\"primitive\\": \\"number\\"
+ }
+ }
+ }
+ ],
+ \\"name\\": \\"Calculator\\"
+ },
+ \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Operands\\": {
+ \\"assembly\\": \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060\\",
+ \\"datatype\\": true,
+ \\"docs\\": {
+ \\"summary\\": \\"Math operands.\\"
+ },
+ \\"fqn\\": \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Operands\\",
+ \\"kind\\": \\"interface\\",
+ \\"locationInModule\\": {
+ \\"filename\\": \\"lib/main.ts\\",
+ \\"line\\": 4
+ },
+ \\"name\\": \\"Operands\\",
+ \\"properties\\": [
+ {
+ \\"abstract\\": true,
+ \\"docs\\": {
+ \\"summary\\": \\"Left-hand side operand.\\"
+ },
+ \\"immutable\\": true,
+ \\"locationInModule\\": {
+ \\"filename\\": \\"lib/main.ts\\",
+ \\"line\\": 8
+ },
+ \\"name\\": \\"lhs\\",
+ \\"type\\": {
+ \\"primitive\\": \\"number\\"
+ }
+ },
+ {
+ \\"abstract\\": true,
+ \\"docs\\": {
+ \\"summary\\": \\"Right-hand side operand.\\"
+ },
+ \\"immutable\\": true,
+ \\"locationInModule\\": {
+ \\"filename\\": \\"lib/main.ts\\",
+ \\"line\\": 13
+ },
+ \\"name\\": \\"rhs\\",
+ \\"type\\": {
+ \\"primitive\\": \\"number\\"
+ }
+ }
+ ]
+ }
+ },
+ \\"version\\": \\"0.0.0\\",
+ \\"fingerprint\\": \\"F2Ja2YDGjKNYeGATUA/z5rZjbzgcQStHaXQMJ2VJRjg=\\"
+}
+",
+ "MyPackage/AssemblyInfo.cs": "using Amazon.JSII.Runtime.Deputy;
+
+[assembly: JsiiAssembly(\\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060\\", \\"0.0.0\\", \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060-0.0.0.tgz\\")]
+",
+ "MyPackage/MyPackage.csproj": "
+
+
+ 4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060
+ MyPackage
+ Apache-2.0
+ 0.0.0
+
+ generated@generated.com
+ en-US
+ http://generated
+ http://generated
+ git
+
+ true
+ true
+ true
+ true
+ enable
+ snupkg
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+ 0612,0618
+
+
+
+",
+ "MyPackage/MyPackage/Calculator.cs": "using Amazon.JSII.Runtime.Deputy;
+
+#pragma warning disable CS0672,CS0809,CS1591
+
+namespace MyPackage
+{
+ /// A sophisticaed multi-language calculator.
+ [JsiiClass(nativeType: typeof(MyPackage.Calculator), fullyQualifiedName: \\"4c6b576fbe7e27053874813d9754cb2e46811d806c1e0aa9aae8add4c3763060.Calculator\\")]
+ public class Calculator : DeputyBase
+ {
+ public Calculator(): base(new DeputyProps(System.Array.Empty