diff --git a/docs/reference/msbuild-props.md b/docs/reference/msbuild-props.md index 4b82b350..7d737e2b 100644 --- a/docs/reference/msbuild-props.md +++ b/docs/reference/msbuild-props.md @@ -7,6 +7,7 @@ The following properties can be used to customize the build processes for genera | `GenerateNodeApiTypeDefinitions` | Set to `true` to generate TypeScript type definitions for .NET APIs in the current project. (This is enabled by default when referencing the `Microsoft.JavaScript.NodeApi.Generator` package.) See [Develop a Node.js addon module](../scenarios/js-dotnet-module). | | `GenerateNodeApiTypeDefinitionsForReferences` | Set to `true` to generate TypeScript type definitions for .NET APIs in assemblies referenced by the current project. (This is enabled by default when **_an empty project_** references the `Microsoft.JavaScript.NodeApi.Generator` package.) See [Dynamically invoke .NET APIs from JavaScript](../scenarios/js-dotnet-dynamic). | | `NodeApiTypeDefinitionsFileName` | Name of the type-definitions file generated for a project. Defaults to `$(TargetName).d.ts`. | +| `NodeApiTypeDefinitionsEnableWarnings` | Set to `true` to enable warnings when [generating type definitions](../features/type-definitions). The warnings are suppressed by default because they can be verbose when referencing system or external assemblies. | `NodeApiJSModuleType` | Set to either `commonjs` or `esm` to specify the module system used by the generated type definitions. If unspecified, the module type is detected automatically from `package.json`, which is usually correct. | | `NodeApiSystemReferenceAssembly` | Item-list of assembly names (not file paths) to be included in typedefs generator. The `System`, `System.Runtime`, and `System.Console` assemblies are included by default. Add system assembly names to the item-list to generate type definitions for them. System assemblies are provided by the installed .NET SDK. | | `PublishNodeModule` | Set to `true` to produce a Native AOT `.node` binary and `.js` module-loader script when building the `Publish` target. The files will be placed in the directory indicated by the `PublishDir` variable. See [Develop a Node.js addon module with .NET Native AOT](../scenarios/js-aot-module). | diff --git a/src/NodeApi.Generator/NodeApi.Generator.targets b/src/NodeApi.Generator/NodeApi.Generator.targets index 0282de65..f72220c4 100644 --- a/src/NodeApi.Generator/NodeApi.Generator.targets +++ b/src/NodeApi.Generator/NodeApi.Generator.targets @@ -139,10 +139,6 @@ Outputs="@(NodeApiReferenceAssemblies->'$(TargetDir)%(Filename).d.ts')" Condition=" '$(GenerateNodeApiTypeDefinitions)' == 'true' AND '$(Compile)' == '' " > - - <_SuppressTSGenerationWarnings>--nowarn - - @@ -172,6 +168,7 @@ + diff --git a/src/NodeApi.Generator/TypeDefinitionsGenerator.cs b/src/NodeApi.Generator/TypeDefinitionsGenerator.cs index 4f3eca63..a16fd6d3 100644 --- a/src/NodeApi.Generator/TypeDefinitionsGenerator.cs +++ b/src/NodeApi.Generator/TypeDefinitionsGenerator.cs @@ -2332,12 +2332,66 @@ private static string FormatDocMemberParameterType( private static string TSIdentifier(string? identifier) { - return identifier switch - { - // A method parameter named "function" is valid in C# but invalid in TS. - "function" => "_" + identifier, - null => "_", - _ => identifier, - }; + return string.IsNullOrEmpty(identifier) ? "_" : + s_tsReservedWords.Contains(identifier) ? "_" + identifier : identifier; } + + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words + private static readonly HashSet s_tsReservedWords = new() + { + "arguments", + "as", + "async", + "await", + "break", + "case", + "catch", + "class", + "const", + "continue", + "debugger", + "default", + "delete", + "do", + "else", + "enum", + "eval", + "export", + "extends", + "false", + "finally", + "for", + "from", + "function", + "get", + "if", + "implements", + "import", + "in", + "instanceof", + "interface", + "let", + "new", + "null", + "of", + "package", + "private", + "protected", + "public", + "return", + "set", + "static", + "super", + "switch", + "this", + "throw", + "true", + "try", + "typeof", + "var", + "void", + "while", + "with", + "yield", + }; } diff --git a/test/TypeDefsGeneratorTests.cs b/test/TypeDefsGeneratorTests.cs index 992876dc..14d57633 100644 --- a/test/TypeDefsGeneratorTests.cs +++ b/test/TypeDefsGeneratorTests.cs @@ -71,14 +71,14 @@ export interface SimpleInterface { TestProperty: string; /** method */ - TestMethod(): string; + TestMethod(_default: string | undefined): string; } """.ReplaceLineEndings(), GenerateTypeDefinition(typeof(SimpleInterface), new Dictionary { ["T:SimpleInterface"] = "interface", ["P:SimpleInterface.TestProperty"] = "property", - ["M:SimpleInterface.TestMethod"] = "method", + ["M:SimpleInterface.TestMethod(System.String)"] = "method", })); } @@ -96,7 +96,7 @@ export class SimpleClass implements SimpleInterface { TestProperty: string; /** method */ - TestMethod(): string; + TestMethod(_default: string | undefined): string; } """.ReplaceLineEndings(), GenerateTypeDefinition(typeof(SimpleClass), new Dictionary @@ -104,7 +104,7 @@ export class SimpleClass implements SimpleInterface { ["T:SimpleClass"] = "class", ["M:SimpleClass.#ctor"] = "constructor", ["P:SimpleClass.TestProperty"] = "property", - ["M:SimpleClass.TestMethod"] = "method", + ["M:SimpleClass.TestMethod(System.String)"] = "method", })); } @@ -120,7 +120,7 @@ public void GenerateSimpleProperty() [Fact] public void GenerateSimpleMethod() { - Assert.Equal(@"TestMethod(): string;", + Assert.Equal(@"TestMethod(_default: string | undefined): string;", GenerateMemberDefinition( typeof(SimpleClass).GetMethod(nameof(SimpleClass.TestMethod))!, new Dictionary())); @@ -250,7 +250,7 @@ public void GenerateJSDocLink() export interface SimpleInterface { TestProperty: string; - TestMethod(): string; + TestMethod(_default: string | undefined): string; } """.ReplaceLineEndings(), GenerateTypeDefinition(typeof(SimpleInterface), new Dictionary @@ -296,13 +296,13 @@ export interface SimpleClass { public interface SimpleInterface { string TestProperty { get; set; } - string TestMethod(); + string TestMethod(string? @default); // 'default' is a reserved word in JS } public class SimpleClass : SimpleInterface { public string TestProperty { get; set; } = null!; - public string TestMethod() { return string.Empty; } + public string TestMethod(string? @default) { return @default ?? string.Empty; } } public delegate void SimpleDelegate(string arg); @@ -334,9 +334,9 @@ public class GenericClass : GenericInterface public static class SimpleClassExtensions { public static void TestExtensionA(this SimpleClass value) - => value.TestMethod(); + => value.TestMethod(null); public static void TestExtensionB(this SimpleClass value) - => value.TestMethod(); + => value.TestMethod(null); } #endif