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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this fix specific to the angular codegen, or could it be moved to the parent class (abstract typescript) or would it even be useful to fix it in the base class?

also, would this need to be fixed in the template instead of rewriting the data type here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@macjohnny There is a related #20877 which suggests that it could be done in the parent class. Not sure about the base class.

Honestly, I asked GitHub Copilot to fix this for me, I don't have any in-depth knowledge of the code to decide where the fix should land - parent class, base class, template? I expected that reviewers would point me to the right place if the current fix is sub-optimal.

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