Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,31 @@ private String applyLocalTypeMapping(String type) {
return type;
}

@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
super.postProcessModelProperty(model, property);
if (property.isInnerEnum && property.items != null && property.enumName != null) {
// Fix maps/arrays of inner enums to use the correct enum name.
// The DefaultCodegen.updateDataTypeWithEnumForMap uses toEnumName(innerItem) which
// returns a name based on the inner item's name (e.g., "InnerEnum" for "inner").
// But the generated TypeScript enum uses property.enumName (e.g., "RuleMsgOperationReportingOptionsEnum").
// We replace the wrong inner enum name with the correct property enum name.
// The classname prefix will be added later by postProcessModels in AbstractTypeScriptClientCodegen.
CodegenProperty innerMostItem = property.items;
while (innerMostItem != null && (Boolean.TRUE.equals(innerMostItem.isMap)
|| Boolean.TRUE.equals(innerMostItem.isArray))) {
innerMostItem = innerMostItem.items;
}
if (innerMostItem != null && innerMostItem.enumName != null
&& !innerMostItem.enumName.equals(property.enumName)) {
// Replace the wrong enum name with the correct one (without classname prefix)
property.datatypeWithEnum = property.datatypeWithEnum.replace(
innerMostItem.enumName, property.enumName);
property.dataType = property.datatypeWithEnum;
}
}
}

@Override
public void postProcessParameter(CodegenParameter parameter) {
super.postProcessParameter(parameter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,4 +489,40 @@ public void testDeepObject() throws IOException {
assertThat(fileContents).containsSubsequence("'options',\n", "<any>options,\n", "QueryParamStyle.DeepObject,\n", "true,\n");
assertThat(fileContents).containsSubsequence("'inputOptions',\n", "<any>inputOptions,\n", "QueryParamStyle.DeepObject,\n", "true,\n");
}

@Test
public void testMapWithArrayOfEnumsUsesCorrectEnumName() throws IOException {
// GIVEN - a schema with a map property containing an array of enums
// This tests the fix for the issue where maps with array of enums generated
// "InnerEnum" type reference instead of the correct qualified enum name.
final String specPath = "src/test/resources/3_0/issue_19393_map_of_inner_enum.yaml";

File output = Files.createTempDirectory("test").toFile();
output.deleteOnExit();

// WHEN
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("typescript-angular")
.setInputSpec(specPath)
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));

final ClientOptInput clientOptInput = configurator.toClientOptInput();

Generator generator = new DefaultGenerator();
generator.opts(clientOptInput).generate();

// THEN - verify the map property uses the correct qualified enum name, not "InnerEnum"
final String fileContents = Files.readString(Paths.get(output + "/model/employeeWithMultiMapOfEnum.ts"));

// The property type should use the correctly qualified enum name
// Note: the test spec uses uniqueItems: true so Set is used instead of Array
assertThat(fileContents).contains("projectRoles?: { [key: string]: Set<EmployeeWithMultiMapOfEnum.ProjectRolesEnum>; }");

// Should NOT contain the incorrect "InnerEnum" reference
assertThat(fileContents).doesNotContain("InnerEnum");

// The enum should be defined in the namespace
assertThat(fileContents).contains("export const ProjectRolesEnum = {");
assertThat(fileContents).contains("export type ProjectRolesEnum = typeof ProjectRolesEnum[keyof typeof ProjectRolesEnum];");
}
}
Loading