Skip to content

Commit 9537a7f

Browse files
authored
[typescript] Prevent generating invalid enum code due to empty variable names (#20699)
* [typescript] Prevent generating invalid enum code due to empty variable names After sanitizing all characters (e.g. multibyte characters), the enum variable name may become an empty string. Since an empty string would cause a syntax error, this patch pads the pseudo variable name (`STRING`) to avoid that issue. For example, given the following OpenAPI definition: ```yaml openapi: "3.0.0" info: title: Sample project version: '1.0' description: 'Sample API Check "API Key" ' license: name: Apache 2.0 url: 'https://www.apache.org/licenses/LICENSE-2.0' paths: {} components: schemas: Greeting: type: string enum: - 'こんにちは' - '你好' - '안녕하세요' ``` The current logic generates the following code for Greeting: ```typescript export enum Greeting { = 'こんにちは', 2 = '你好', 3 = '안녕하세요' } ``` This code is invalid. With this patch, the generated code becomes: ```typescript export enum Greeting { STRING = 'こんにちは', STRING2 = '你好', STRING3 = '안녕하세요' } ``` Signed-off-by: moznion <[email protected]> * Remove unnecessary imports Signed-off-by: moznion <[email protected]> * Use new sanitizer for TypeScript symbol which takes wider variety characters for enum var name Signed-off-by: moznion <[email protected]> --------- Signed-off-by: moznion <[email protected]>
1 parent a06a2b4 commit 9537a7f

File tree

3 files changed

+68
-2
lines changed

3 files changed

+68
-2
lines changed

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,9 +311,25 @@ public String toEnumVarName(String name, String datatype) {
311311

312312
if (enumName.matches("\\d.*")) { // starts with number
313313
return "_" + enumName;
314-
} else {
315-
return enumName;
316314
}
315+
316+
if (enumName.isEmpty()) {
317+
// After sanitizing *all* characters (e.g. multibyte characters), the var name becomes an empty string.
318+
// An empty string would cause a syntax error, so this code attempts to re-sanitize the name using another sanitizer that allows a wider variety of characters.
319+
// For backward compatibility, this additional sanitization is only applied if the original sanitized name is empty.
320+
final String sanitized = sanitizeNameForTypeScriptSymbol(name);
321+
if (sanitized.isEmpty()) {
322+
// After re-sanitizing, this pads a pseudo var name ("STRING") if still the name is empty.
323+
return "STRING";
324+
}
325+
return "_" + sanitized;
326+
}
327+
328+
return enumName;
329+
}
330+
331+
private String sanitizeNameForTypeScriptSymbol(String name) {
332+
return sanitizeName(name, "[^\\p{L}\\p{Nd}\\$_]");
317333
}
318334

319335
private String getNameWithEnumPropertyNaming(String name) {

modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/TypeScriptClientCodegenTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@
55
import io.swagger.v3.oas.models.PathItem;
66
import io.swagger.v3.oas.models.media.*;
77
import org.openapitools.codegen.*;
8+
import org.openapitools.codegen.config.CodegenConfigurator;
89
import org.openapitools.codegen.languages.TypeScriptClientCodegen;
910
import org.openapitools.codegen.model.ModelMap;
1011
import org.openapitools.codegen.model.ModelsMap;
1112
import org.openapitools.codegen.utils.ModelUtils;
1213
import org.testng.Assert;
1314
import org.testng.annotations.Test;
1415

16+
import java.io.File;
17+
import java.nio.file.Files;
18+
import java.nio.file.Paths;
1519
import java.util.Collections;
1620
import java.util.List;
1721
import java.util.Map;
@@ -179,4 +183,31 @@ public void testAdditionalPropertiesPutForConfigValues() throws Exception {
179183

180184
Assert.assertEquals(codegen.getLicenseName(), licenseName);
181185
}
186+
187+
@Test
188+
public void testForAllSanitizedEnum() throws Exception {
189+
final File output = Files.createTempDirectory("typescriptnodeclient_").toFile();
190+
output.deleteOnExit();
191+
192+
final CodegenConfigurator configurator = new CodegenConfigurator()
193+
.setGeneratorName("typescript")
194+
.setInputSpec("src/test/resources/bugs/typescript_enum_var_name_all_sanitized.yaml")
195+
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
196+
197+
final ClientOptInput clientOptInput = configurator.toClientOptInput();
198+
final DefaultGenerator generator = new DefaultGenerator();
199+
final List<File> files = generator.opts(clientOptInput).generate();
200+
files.forEach(File::deleteOnExit);
201+
202+
TestUtils.assertFileContains(
203+
Paths.get(output + "/models/Greeting.ts"),
204+
"export enum Greeting {\n" +
205+
" _こんにちは = 'こんにちは',\n" +
206+
" _你好 = '你好',\n" +
207+
" _안녕하세요 = '안녕하세요',\n" +
208+
" STRING = '!@#%',\n" +
209+
" STRING2 = '^&*\uD83C\uDF63'",
210+
"}"
211+
);
212+
}
182213
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
openapi: "3.0.0"
2+
info:
3+
title: Sample project
4+
version: '1.0'
5+
description: 'Sample API Check "API Key" '
6+
license:
7+
name: Apache 2.0
8+
url: 'https://www.apache.org/licenses/LICENSE-2.0'
9+
paths: {}
10+
components:
11+
schemas:
12+
Greeting:
13+
type: string
14+
enum:
15+
- 'こんにちは'
16+
- '你好'
17+
- '안녕하세요'
18+
- '!@#%'
19+
- '^&*🍣'

0 commit comments

Comments
 (0)