Skip to content

[BUG][dart-dio] Bug generating inline enums with common names #21582

@tomcra

Description

@tomcra

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
openapi-generator version

master f632ab7

OpenAPI declaration file content or url
openapi: "3.0.3"
info:
  version: 1.0.0
  title: test
paths:
  /test:
    get:
      summary: test
      operationId: test
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ObjectThree'
components:
  schemas:
    ObjectOne:
      type: object
      properties:
        attribute:
          description: 'Object one attribute enum'
          type: 'array'
          uniqueItems: true
          items:
            type: 'string'
            enum: [
              'valueone',
              'vauetwo'
            ]
    ObjectTwo:
      type: object
      properties:
        attribute:
          description: 'Object two attribute enum'
          type: 'array'
          uniqueItems: true
          items:
            type: 'string'
            enum: [
              'valueone',
              'vauetwo'
            ]
    ObjectThree:
      type: object
      properties:
        objectone:
          $ref: '#/components/schemas/ObjectOne'
        objecttwo:
          $ref: '#/components/schemas/ObjectTwo'
Generation Details

Run using cli

generate -i modules/openapi-generator/src/test/resources/bugs/issues_21582.yaml -g dart-dio -o samples/openapi3/client/bug-samples/issue_21582

Run using generate-samples.sh

bin/generate-samples.sh bin/configs/dart-dio-enum-property-name.yaml
Steps to reproduce
  1. Run one of the commands above
  2. Check the output of the files. (see expected versus actual bellow).
  3. Run dart pub get on the output
  4. Run dart run build_runner build to get rid of the errors related to missing generated files
  5. See the ambiguous import and ambiguous export analyser errors in openapi.dart and serializers.g.dart. The name 'ObjectTwoAttributeEnum' is defined in the libraries 'package:openapi/src/model/object_one.dart' and 'package:openapi/src/model/object_two.dart'. Try using 'as prefix' for one of the import directives, or hiding the name from all but one of the imports.

Expected output in object_one.dart - note that the type of the attribute and name of the inline enum class is ObjectOneAttributeEnum

@BuiltValue()
abstract class ObjectOne implements Built<ObjectOne, ObjectOneBuilder> {
  /// Object one attribute enum
  @BuiltValueField(wireName: r'attribute')
  BuiltSet<ObjectOneAttributeEnum>? get attribute;
  // enum attributeEnum {  valueone,  vauetwo,  };

  ObjectOne._();

  factory ObjectOne([void updates(ObjectOneBuilder b)]) = _$ObjectOne;

  @BuiltValueHook(initializeBuilder: true)
  static void _defaults(ObjectOneBuilder b) => b;

  @BuiltValueSerializer(custom: true)
  static Serializer<ObjectOne> get serializer => _$ObjectOneSerializer();
}

class ObjectOneAttributeEnum extends EnumClass {

  @BuiltValueEnumConst(wireName: r'valueone')
  static const ObjectOneAttributeEnum valueone = _$objectOneAttributeEnum_valueone;
  @BuiltValueEnumConst(wireName: r'vauetwo')
  static const ObjectOneAttributeEnum vauetwo = _$objectOneAttributeEnum_vauetwo;

  static Serializer<ObjectOneAttributeEnum> get serializer => _$objectOneAttributeEnumSerializer;

  const ObjectOneAttributeEnum._(String name): super(name);

  static BuiltSet<ObjectOneAttributeEnum> get values => _$objectOneAttributeEnumValues;
  static ObjectOneAttributeEnum valueOf(String name) => _$objectOneAttributeEnumValueOf(name);
}

Actual output in object_one.dart - note that the type of the attribute and name of the inline enum class is ObjectTwoAttributeEnum

@BuiltValue()
abstract class ObjectOne implements Built<ObjectOne, ObjectOneBuilder> {
  /// Object one attribute enum
  @BuiltValueField(wireName: r'attribute')
  BuiltSet<ObjectTwoAttributeEnum>? get attribute;
  // enum attributeEnum {  valueone,  vauetwo,  };

  ObjectOne._();

  factory ObjectOne([void updates(ObjectOneBuilder b)]) = _$ObjectOne;

  @BuiltValueHook(initializeBuilder: true)
  static void _defaults(ObjectOneBuilder b) => b;

  @BuiltValueSerializer(custom: true)
  static Serializer<ObjectOne> get serializer => _$ObjectOneSerializer();
}

class ObjectTwoAttributeEnum extends EnumClass {

  @BuiltValueEnumConst(wireName: r'valueone')
  static const ObjectTwoAttributeEnum valueone = _$objectTwoAttributeEnum_valueone;
  @BuiltValueEnumConst(wireName: r'vauetwo')
  static const ObjectTwoAttributeEnum vauetwo = _$objectTwoAttributeEnum_vauetwo;

  static Serializer<ObjectTwoAttributeEnum> get serializer => _$objectTwoAttributeEnumSerializer;

  const ObjectTwoAttributeEnum._(String name): super(name);

  static BuiltSet<ObjectTwoAttributeEnum> get values => _$objectTwoAttributeEnumValues;
  static ObjectTwoAttributeEnum valueOf(String name) => _$objectTwoAttributeEnumValueOf(name);
}
Related issues/PRs
Suggest a fix

Suggest updating AbstractDartCodegen.java

Index: modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java	(revision 65cb95bef048b5110fda362feee52e76795fa26d)
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java	(date 1752834475778)
@@ -577,6 +577,12 @@
                 // inner items e.g. enums in collections, only works for one level
                 // but same is the case for DefaultCodegen
                 property.setDatatypeWithEnum(property.datatypeWithEnum.replace(property.items.datatypeWithEnum, enumName));
+                // Because properties are cached in org.openapitools.codegen.DefaultCodegen.fromProperty(java.lang.String, io.swagger.v3.oas.models.media.Schema, boolean, boolean)
+                // then the same object could be for multiple properties where the name of the inline enum is the same
+                // in 2 different classes and the following renaming will impact properties in other classes we
+                // therefore clone them before editing
+                property.items = property.items.clone();
+                property.mostInnerItems = property.items;
                 property.items.setDatatypeWithEnum(enumName);
                 property.items.setEnumName(enumName);
             } else {

Because the following uses a cache based on a key with property name and Schema the same object is returned for both attribute properties and the name is updated twice on the same object.

The fix simply clones the property before changing the name of the type

    public CodegenProperty fromProperty(String name, Schema p, boolean required, boolean schemaIsFromAdditionalProperties) {
        if (p == null) {
            LOGGER.error("Undefined property/schema for `{}`. Default to type:string.", name);
            return null;
        }
        LOGGER.debug("debugging fromProperty for {}: {}", name, p);
        NamedSchema ns = new NamedSchema(name, p, required, schemaIsFromAdditionalProperties);
        CodegenProperty cpc = schemaCodegenPropertyCache.get(ns);
        if (cpc != null) {
            LOGGER.debug("Cached fromProperty for {} : {} required={}", name, p.getName(), required);
            return cpc;
        }

Reference to the file is
org.openapitools.codegen.DefaultCodegen#fromProperty(java.lang.String, io.swagger.v3.oas.models.media.Schema, boolean, boolean)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions