Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code generation fails on OpenAPI 3.1.0 API definition #135

Open
domesticmouse opened this issue Feb 21, 2024 · 2 comments
Open

Code generation fails on OpenAPI 3.1.0 API definition #135

domesticmouse opened this issue Feb 21, 2024 · 2 comments
Labels
bug Something isn't working

Comments

@domesticmouse
Copy link

Description of the bug

Code generator generates invalid code for an OpenAPI specification

Steps to reproduce

  1. Create an api definiton file salad-api.json:
{
    "openapi": "3.1.0",
    "info": {
        "title": "FastAPI",
        "description": "# Salad API\n\nThis API stores the inventory of salad for a store. \n\n",
        "version": "0.1.0"
    },
    "paths": {
        "/inventory": {
            "get": {
                "summary": "Inventory",
                "description": "Return the entire inventory",
                "operationId": "inventory_inventory_get",
                "responses": {
                    "200": {
                        "description": "Successful Response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "items": {
                                        "$ref": "#/components/schemas/Item-Output"
                                    },
                                    "type": "array",
                                    "title": "Response Inventory Inventory Get"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "summary": "Inventory Add",
                "description": "Add a new item to the inventory",
                "operationId": "inventory_add_inventory_post",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/Item-Input"
                            }
                        }
                    },
                    "required": true
                },
                "responses": {
                    "201": {
                        "description": "Successful Response",
                        "content": {
                            "application/json": {
                                "schema": {}
                            }
                        }
                    },
                    "422": {
                        "description": "Validation Error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/HTTPValidationError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/inventory/{item}": {
            "get": {
                "summary": "Item Get",
                "description": "Return the inventory for a specific item",
                "operationId": "item_get_inventory__item__get",
                "parameters": [
                    {
                        "name": "item",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "title": "Item"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Successful Response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Item-Output"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Validation Error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/HTTPValidationError"
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "summary": "Inventory Remove",
                "description": "Delete an item from the inventory",
                "operationId": "inventory_remove_inventory__item__delete",
                "parameters": [
                    {
                        "name": "item",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "title": "Item"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "Successful Response"
                    },
                    "422": {
                        "description": "Validation Error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/HTTPValidationError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/inventory/{item}/add": {
            "get": {
                "summary": "Item Add",
                "description": "Increase stock levels for an item",
                "operationId": "item_add_inventory__item__add_get",
                "parameters": [
                    {
                        "name": "item",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "title": "Item"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Successful Response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Item-Output"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Validation Error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/HTTPValidationError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/inventory/{item}/remove": {
            "get": {
                "summary": "Item Remove",
                "description": "Decrease stock levels for an item",
                "operationId": "item_remove_inventory__item__remove_get",
                "parameters": [
                    {
                        "name": "item",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "title": "Item"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Successful Response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Item-Output"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Validation Error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/HTTPValidationError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/": {
            "get": {
                "summary": "Healthcheck",
                "description": "Root health check",
                "operationId": "healthcheck__get",
                "responses": {
                    "200": {
                        "description": "Successful Response",
                        "content": {
                            "application/json": {
                                "schema": {}
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "HTTPValidationError": {
                "properties": {
                    "detail": {
                        "items": {
                            "$ref": "#/components/schemas/ValidationError"
                        },
                        "type": "array",
                        "title": "Detail"
                    }
                },
                "type": "object",
                "title": "HTTPValidationError"
            },
            "Item-Input": {
                "properties": {
                    "name": {
                        "type": "string",
                        "title": "Name"
                    },
                    "id": {
                        "type": "string",
                        "title": "Id"
                    },
                    "emoji": {
                        "type": "string",
                        "title": "Emoji"
                    },
                    "cost_cents": {
                        "type": "integer",
                        "title": "Cost Cents"
                    },
                    "stock_count": {
                        "type": "integer",
                        "title": "Stock Count"
                    },
                    "image_url": {
                        "type": "string",
                        "title": "Image Url"
                    }
                },
                "type": "object",
                "required": [
                    "name",
                    "id",
                    "emoji",
                    "cost_cents",
                    "stock_count",
                    "image_url"
                ],
                "title": "Item"
            },
            "Item-Output": {
                "properties": {
                    "name": {
                        "type": "string",
                        "title": "Name"
                    },
                    "id": {
                        "type": "string",
                        "title": "Id"
                    },
                    "emoji": {
                        "type": "string",
                        "title": "Emoji"
                    },
                    "cost_cents": {
                        "type": "integer",
                        "title": "Cost Cents"
                    },
                    "stock_count": {
                        "type": "integer",
                        "title": "Stock Count"
                    },
                    "image_url": {
                        "type": "string",
                        "title": "Image Url"
                    },
                    "cost_AUD": {
                        "type": "string",
                        "title": "Cost Aud",
                        "readOnly": true
                    }
                },
                "type": "object",
                "required": [
                    "name",
                    "id",
                    "emoji",
                    "cost_cents",
                    "stock_count",
                    "image_url",
                    "cost_AUD"
                ],
                "title": "Item"
            },
            "ValidationError": {
                "properties": {
                    "loc": {
                        "items": {
                            "anyOf": [
                                {
                                    "type": "string"
                                },
                                {
                                    "type": "integer"
                                }
                            ]
                        },
                        "type": "array",
                        "title": "Location"
                    },
                    "msg": {
                        "type": "string",
                        "title": "Message"
                    },
                    "type": {
                        "type": "string",
                        "title": "Error Type"
                    }
                },
                "type": "object",
                "required": [
                    "loc",
                    "msg",
                    "type"
                ],
                "title": "ValidationError"
            }
        }
    }
}
  1. Create the configuration for the code generator:
import 'package:openapi_generator_annotations/openapi_generator_annotations.dart';

@Openapi(
    additionalProperties:
        AdditionalProperties(pubName: 'salad_api_client', pubAuthor: 'Google'),
    inputSpec: InputSpec(path: 'salad-api.json'),
    generatorName: Generator.dart,
    outputDirectory: 'salad_api_client')
class SaladApiConfig {}
  1. Run the code generator:
$ dart run build_runner build
Building package executable... (3.3s)
Built build_runner:build_runner.
[INFO] Generating build script completed, took 174ms
[INFO] Precompiling build script... completed, took 3.4s
[INFO] Building new asset graph completed, took 681ms
[INFO] Checking for unexpected pre-existing outputs. completed, took 0ms
[INFO] Generating SDK summary completed, took 2.7s
[WARNING] openapi_generator on lib/main.dart:
Your current `analyzer` version may not fully support your current SDK version.

Analyzer language version: 3.2.0
SDK language version: 3.3.0

Please update to the latest `analyzer` version (6.4.1) by running
`flutter packages upgrade`.

If you are not getting the latest version by running the above command, you
can try adding a constraint like the following to your pubspec to start
diagnosing why you can't get the latest version:

dev_dependencies:
  analyzer: ^6.4.1

[INFO] openapi_generator on lib/main.dart:

:::::::::::::::::::::::::::::::::::::::::::
::      Openapi generator for dart       ::
:::::::::::::::::::::::::::::::::::::::::::

[WARNING] openapi_generator on lib/main.dart:
loadSpec - /Users/brettmorgan/Documents/GitHub/myapp/.dart_tool/openapi-generator-cache.json
[WARNING] openapi_generator on lib/main.dart:
loadSpec - salad-api.json
[INFO] openapi_generator on lib/main.dart:Loaded cached and current spec files.
[INFO] openapi_generator on lib/main.dart:Dirty Spec found. Running generation.
[INFO] openapi_generator on lib/main.dart:Running following command to generate openapi client - [ generate -o=salad_api_client -i=salad-api.json -g=dart --additional-properties=allowUnicodeIdentifiers=false,ensureUniqueParams=true,useEnumExtension=true,enumUnknownDefaultCase=false,prependFormOrBodyParameters=false,pubAuthor=Google,pubName=salad_api_client,legacyDiscriminatorBehavior=true,sortModelPropertiesByRequiredFlag=true,sortParamsByRequiredFlag=true,wrapper=none ]
[INFO] openapi_generator on lib/main.dart:Openapi generator completed successfully.
[INFO] openapi_generator on lib/main.dart:Installing dependencies with generated source. flutter pub get
[INFO] openapi_generator on lib/main.dart:Install completed successfully.
[INFO] openapi_generator on lib/main.dart:Skipping source gen because generator does not need it.
[WARNING] openapi_generator on lib/main.dart:
loadSpec - salad-api.json
[INFO] openapi_generator on lib/main.dart:Successfully cached spec changes.
[SEVERE] openapi_generator on lib/main.dart:
Failed to format generated code.

Failed to format generated code. Could not format because the source could not be parsed:

line 16, column 3 of lib/model/validation_error_loc_inner.dart: Expected an identifier.

16 │   });
   │   ^

line 21, column 3 of lib/model/validation_error_loc_inner.dart: Expected an identifier.

21 │   @override
   │   ^

line 19, column 96 of lib/model/validation_error_loc_inner.dart: Expected to find ';'.

19 │   bool operator ==(Object other) => identical(this, other) || other is ValidationErrorLocInner &&
   │                                                                                                ^^

line 25, column 3 of lib/model/validation_error_loc_inner.dart: Expected an identifier.

25 │   @override
   │   ^

line 22, column 20 of lib/model/validation_error_loc_inner.dart: Expected to find ';'.

22 │   int get hashCode =>
   │                    ^^

 #0      OpenapiGenerator.formatCode (package:openapi_generator/src/openapi_generator_runner.dart:486:34)
<asynchronous suspension>
#1      OpenapiGenerator.generatorV2.<anonymous closure> (package:openapi_generator/src/openapi_generator_runner.dart:212:9)
<asynchronous suspension>
#2      OpenapiGenerator.generatorV2 (package:openapi_generator/src/openapi_generator_runner.dart:211:7)
<asynchronous suspension>
#3      normalizeGeneratorOutput (package:source_gen/src/output_helpers.dart:10:1)
<asynchronous suspension>
#4      StreamCompleter.setSourceStream (package:async/src/stream_completer.dart:76:3)
<asynchronous suspension>

[INFO] openapi_generator on lib/main.dart:Creating generated timestamp with 2024-02-21T16:29:37.796799
[INFO] Running build completed, took 8.3s
[INFO] Caching finalized dependency graph completed, took 36ms
[SEVERE] Failed after 8.3s

Expected behavior

Generate a valid client library.

Logs

See above

Screenshots

No response

Platform

Linux

Library version

5.0.2

Flutter version

3.19.0

Flutter channel

stable

Additional context

$ flutter doctor -v 
[✓] Flutter (Channel stable, 3.19.0, on macOS 14.3.1 23D60 darwin-arm64, locale en)
    • Flutter version 3.19.0 on channel stable at /Users/brettmorgan/flutter
    • Upstream repository https://github.com/flutter/flutter
    • Framework revision bae5e49bc2 (7 days ago), 2024-02-13 17:46:18 -0800
    • Engine revision 04817c99c9
    • Dart version 3.3.0
    • DevTools version 2.31.1

[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at /Users/brettmorgan/Library/Android/sdk
    • Platform android-34-ext8, build-tools 34.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 15.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 15C500b
    • CocoaPods version 1.15.0

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.3)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)

[✓] IntelliJ IDEA Community Edition (version 2023.3.2)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin version 77.0.1
    • Dart plugin version 233.13135.65

[✓] VS Code (version 1.86.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.82.0

[✓] Connected device (3 available)
    • sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64  • Android 14 (API 34) (emulator)
    • macOS (desktop)             • macos         • darwin-arm64   • macOS 14.3.1 23D60 darwin-arm64
    • Chrome (web)                • chrome        • web-javascript • Google Chrome 121.0.6167.184

[✓] Network resources
    • All expected network resources are available.

• No issues found!
@domesticmouse domesticmouse added the bug Something isn't working label Feb 21, 2024
@DaniinXorchenabo
Copy link

Hi, looks like, this has been fixed in 5.0.3 version, but for some reason this hasn't been published in official registry.

You can edit your pubspec.yaml and install new version manually:

dev_dependencies:
  ...
  openapi_generator: ^5.0.2
  openapi_generator_cli:  ^5.0.2
  openapi_generator_annotations: ^5.0.2

dependency_overrides:
  analyzer: ^6.4.1
  meta: ^1.15.0
  openapi_generator:
    git:
      url: https://github.com/gibahjoe/openapi-generator-dart.git
      ref: v5.0.3
      path: openapi-generator
      version: ^5.0.3
  openapi_generator_cli:
    git:
      url: https://github.com/gibahjoe/openapi-generator-dart.git
      ref: v5.0.3
      path: openapi-generator-cli
      version: ^5.0.3
  openapi_generator_annotations:
    git:
      url: https://github.com/gibahjoe/openapi-generator-dart.git
      ref: v5.0.3
      path: openapi-generator-annotations
      version: ^5.0.3

May be override analyzer and meta not necessary. I'm not testing this.

@ebrahim2222
Copy link

not solved

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants