Skip to content

Commit

Permalink
feat: .NET Support (#73)
Browse files Browse the repository at this point in the history
Adds support for generating a .NET (C#) project.

I choose `namespace` rather than `package` since it seemed more appropriate when generating source code.

I went with `dotnet` since it matches the jsii naming, but `csharp` may make more sense for configuration options / cli parameters. I don't believe there are any plans to generate F# code in jsii, but if there were, I'd lean towards using `csharp` naming.
  • Loading branch information
jsteinich authored Sep 22, 2020
1 parent 491ae93 commit a0dc5ea
Show file tree
Hide file tree
Showing 10 changed files with 799 additions and 1 deletion.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `[email protected]` 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 `[email protected]` 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`).
Expand Down
17 changes: 17 additions & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -30,6 +32,7 @@ async function main() {
...parseJsiiOptions(),
...parsePythonOptions(),
...parseJavaOptions(),
...parseCSharpOptions(),
});

function parseJsiiOptions() {
Expand Down Expand Up @@ -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 {
Expand Down
7 changes: 7 additions & 0 deletions src/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, {
Expand Down
22 changes: 22 additions & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
}
7 changes: 7 additions & 0 deletions src/srcmak.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
}
});
}
6 changes: 5 additions & 1 deletion src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 "-"`);
}
}
Loading

0 comments on commit a0dc5ea

Please sign in to comment.