[core] Clone inline sub-schemas before collapsing a nullable anyOf/oneOf

MA
13d ago
+149-23

Fixes #25030

When the 3.1 parser reads the spec from the issue (with resolve, as CodegenConfigurator does), the query parameter's anyOf: [string, null] and the broken_field property's anyOf: [string, null] get the same type: string instance as their first sub-schema. simplifyOneOfAnyOfWithOnlyOneNonNullSubSchema collapses each anyOf to that sub-schema and copies the parent's description onto it when the sub-schema has none. It already cloned the sub-schema first when it was a $ref, for the same reason, but not when it was inline. So the parameter, normalized first, wrote "WRONG DESCRIPTION! (schema)" onto the shared instance, and broken_field then kept it because the description was no longer null. nullable, readOnly and writeOnly leak the same way.

The fix clones the remaining sub-schema in both cases before applying the parent's metadata.

This also explains the 5 regenerated files in csharp/generichost/latest/AnnotatedEnum, whose spec is 3_1/simplifyOneOfAnyOf_test.yaml. There, AnyOfStringArrayOfString (its string branch and its array items) and PropertiesWithAnyOf.anyof_nullable_string had picked up description: to test oneOf and nullable: true, neither of which they declare. With the fix they come out as the spec defines them.

Tests:

  • ModelUtilsTest#simplifyAnyOfWithOnlyOneNonNullSubSchemaDoesNotMutateSharedInlineSchema: the inline counterpart of the existing $ref test. On master the second schema comes back with the first one's description.
  • OpenAPINormalizerTest#testSimplifyAnyOfKeepsDescriptionsOfSharedInlineSubSchema: normalizes the spec from the issue (3_1/issue_25030.json, parsed with resolve like the generator does). On master: expected [Correct description.] but found [WRONG DESCRIPTION! (schema)].

mvn test on modules/openapi-generator passes (5270 tests). ./bin/generate-samples.sh ./bin/configs/*.yaml (814 generators) changes only the AnnotatedEnum sample above, and ./bin/utils/export_docs_generators.sh changes nothing.

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Fixes #25030: prevents parent metadata from leaking onto shared inline sub-schemas when a nullable anyOf/oneOf collapses to a single sub-schema.

The 3.1 parser can hand multiple anyOf/oneOf lists the same instance of an identical inline sub-schema. simplifyOneOfAnyOfWithOnlyOneNonNullSubSchema only cloned the remaining sub-schema when it was a $ref, so for inline ones it copied the parent's description, nullable, readOnly, and writeOnly onto the shared instance, and each later location that collapsed to it kept the first location's values. The sub-schema is now cloned in both cases.

Tests

  • Added ModelUtilsTest#simplifyAnyOfWithOnlyOneNonNullSubSchemaDoesNotMutateSharedInlineSchema and OpenAPINormalizerTest#testSimplifyAnyOfKeepsDescriptionsOfSharedInlineSubSchema, which asserts the parser shares one type: string instance between both anyOf lists.
  • Regenerated AnnotatedEnum C# samples no longer carry the leaked to test oneOf description.