Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Escape reserved words in generated typedefs #357

Merged
merged 1 commit into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/reference/msbuild-props.md
Original file line number Diff line number Diff line change
Expand Up @@ -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). |
Expand Down
5 changes: 1 addition & 4 deletions src/NodeApi.Generator/NodeApi.Generator.targets
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,6 @@
Outputs="@(NodeApiReferenceAssemblies->'$(TargetDir)%(Filename).d.ts')"
Condition=" '$(GenerateNodeApiTypeDefinitions)' == 'true' AND '$(Compile)' == '' "
>
<PropertyGroup Condition=" '$(EnableTSGenerationWarnings)' != 'true' ">
<_SuppressTSGenerationWarnings>--nowarn</_SuppressTSGenerationWarnings>
</PropertyGroup>

<ItemGroup Condition="$(TargetFramework.StartsWith('net4'))">
<NodeApiSystemReferenceAssembly Include="mscorlib" />
<NodeApiSystemReferenceAssembly Include="System" />
Expand Down Expand Up @@ -172,6 +168,7 @@
<WriteLinesToFile File="$(NodeApiGeneratorResponseFile)" Lines="--assemblies &quot;$(_NodeApiGeneratorAssemblyReferences)&quot;" Overwrite="true" />
<WriteLinesToFile File="$(NodeApiGeneratorResponseFile)" Lines="--packs &quot;$(_NodeApiGeneratorTargetingPacks)&quot;" />
<WriteLinesToFile File="$(NodeApiGeneratorResponseFile)" Lines="--typedefs &quot;$(_NodeApiGeneratorTypeDefs)&quot;" />
<WriteLinesToFile File="$(NodeApiGeneratorResponseFile)" Lines="--nowarn" Condition=" '$(NodeApiTypeDefinitionsEnableWarnings)' != 'true' " />
<WriteLinesToFile File="$(NodeApiGeneratorResponseFile)" Lines="$(NodeApiTypeDefinitionsGeneratorOptions)" />

<!-- Run the generator using args from the response file. Note the '@' indicates the response file NOT an MSBuild item-list. -->
Expand Down
68 changes: 61 additions & 7 deletions src/NodeApi.Generator/TypeDefinitionsGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2332,12 +2332,66 @@

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;

Check warning on line 2336 in src/NodeApi.Generator/TypeDefinitionsGenerator.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest, net472, 20.x, Release)

Possible null reference argument for parameter 'item' in 'bool HashSet<string>.Contains(string item)'.

Check warning on line 2336 in src/NodeApi.Generator/TypeDefinitionsGenerator.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest, net472, 20.x, Release)

Possible null reference argument for parameter 'item' in 'bool HashSet<string>.Contains(string item)'.

Check warning on line 2336 in src/NodeApi.Generator/TypeDefinitionsGenerator.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest, net6.0, 20.x, Release)

Possible null reference argument for parameter 'item' in 'bool HashSet<string>.Contains(string item)'.

Check warning on line 2336 in src/NodeApi.Generator/TypeDefinitionsGenerator.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest, net6.0, 20.x, Release)

Possible null reference argument for parameter 'item' in 'bool HashSet<string>.Contains(string item)'.

Check warning on line 2336 in src/NodeApi.Generator/TypeDefinitionsGenerator.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest, net8.0, 18.x, Release)

Possible null reference argument for parameter 'item' in 'bool HashSet<string>.Contains(string item)'.

Check warning on line 2336 in src/NodeApi.Generator/TypeDefinitionsGenerator.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest, net8.0, 18.x, Release)

Possible null reference argument for parameter 'item' in 'bool HashSet<string>.Contains(string item)'.

Check warning on line 2336 in src/NodeApi.Generator/TypeDefinitionsGenerator.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest, net8.0, 20.x, Release)

Possible null reference argument for parameter 'item' in 'bool HashSet<string>.Contains(string item)'.

Check warning on line 2336 in src/NodeApi.Generator/TypeDefinitionsGenerator.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest, net8.0, 20.x, Release)

Possible null reference argument for parameter 'item' in 'bool HashSet<string>.Contains(string item)'.

Check warning on line 2336 in src/NodeApi.Generator/TypeDefinitionsGenerator.cs

View workflow job for this annotation

GitHub Actions / build (macos-latest, net6.0, 20.x, Release)

Possible null reference argument for parameter 'item' in 'bool HashSet<string>.Contains(string item)'.

Check warning on line 2336 in src/NodeApi.Generator/TypeDefinitionsGenerator.cs

View workflow job for this annotation

GitHub Actions / build (macos-latest, net8.0, 18.x, Release)

Possible null reference argument for parameter 'item' in 'bool HashSet<string>.Contains(string item)'.

Check warning on line 2336 in src/NodeApi.Generator/TypeDefinitionsGenerator.cs

View workflow job for this annotation

GitHub Actions / build (macos-latest, net8.0, 20.x, Release)

Possible null reference argument for parameter 'item' in 'bool HashSet<string>.Contains(string item)'.

Check warning on line 2336 in src/NodeApi.Generator/TypeDefinitionsGenerator.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, net6.0, 20.x, Release)

Possible null reference argument for parameter 'item' in 'bool HashSet<string>.Contains(string item)'.

Check warning on line 2336 in src/NodeApi.Generator/TypeDefinitionsGenerator.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, net8.0, 18.x, Release)

Possible null reference argument for parameter 'item' in 'bool HashSet<string>.Contains(string item)'.

Check warning on line 2336 in src/NodeApi.Generator/TypeDefinitionsGenerator.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, net8.0, 20.x, Release)

Possible null reference argument for parameter 'item' in 'bool HashSet<string>.Contains(string item)'.
}

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words
private static readonly HashSet<string> 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",
};
}
20 changes: 10 additions & 10 deletions test/TypeDefsGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ export interface SimpleInterface {
TestProperty: string;

/** method */
TestMethod(): string;
TestMethod(_default: string | undefined): string;
}
""".ReplaceLineEndings(),
GenerateTypeDefinition(typeof(SimpleInterface), new Dictionary<string, string>
{
["T:SimpleInterface"] = "interface",
["P:SimpleInterface.TestProperty"] = "property",
["M:SimpleInterface.TestMethod"] = "method",
["M:SimpleInterface.TestMethod(System.String)"] = "method",
}));
}

Expand All @@ -96,15 +96,15 @@ export class SimpleClass implements SimpleInterface {
TestProperty: string;

/** method */
TestMethod(): string;
TestMethod(_default: string | undefined): string;
}
""".ReplaceLineEndings(),
GenerateTypeDefinition(typeof(SimpleClass), new Dictionary<string, string>
{
["T:SimpleClass"] = "class",
["M:SimpleClass.#ctor"] = "constructor",
["P:SimpleClass.TestProperty"] = "property",
["M:SimpleClass.TestMethod"] = "method",
["M:SimpleClass.TestMethod(System.String)"] = "method",
}));
}

Expand All @@ -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<string, string>()));
Expand Down Expand Up @@ -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<string, XElement>
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -334,9 +334,9 @@ public class GenericClass<T> : GenericInterface<T>
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
Loading