guardrail-dev / guardrail

Principled code generation from OpenAPI specifications
https://guardrail.dev
MIT License
522 stars 132 forks source link

allOf with multiple $refs attempts to do multiple inheritance, yields "Class needs to be a trait to be mixed" #206

Open novakov-alexey-zz opened 5 years ago

novakov-alexey-zz commented 5 years ago

I am trying to generate a client for this API: https://raw.githubusercontent.com/aeternity/aeternity/master/config/swagger.yaml

with the following build.sbt:

lazy val root = (project in file("."))
  .settings(
    name := "ae-client",
    libraryDependencies ++= Seq(
      akka, akkaHttp, circe, akkaStream, circeGeneric, jawn, circeJava8, circeJawn, circeParser,
      catsEffect, http4sCirce, http4sClient, http4sCore, http4sDsl, http4sServer,
      scalaTest % Test
    )
  )

guardrailTasks in Compile := List(
  Client(file("/Users/aa/dev/git/Aethernity/ae-client/swagger.yaml"), framework="http4s"),
)

scalacOptions += "-Ypartial-unification"

Dependencies.scala

object Dependencies {
  val circeVersion = "0.11.1"
  val http4sVersion = "0.20.0-M7"

  lazy val scalaTest = "org.scalatest" %% "scalatest" % "3.0.5"
  lazy val akka = "com.typesafe.akka" %% "akka-actor" % "2.5.21"
  lazy val akkaHttp = "com.typesafe.akka" %% "akka-http" % "10.1.7"
  lazy val akkaStream = "com.typesafe.akka" %% "akka-stream" % "2.5.21"
  lazy val circe = "io.circe" %% "circe-core" % circeVersion
  lazy val circeGeneric = "io.circe" %% "circe-generic" % circeVersion
  lazy val circeParser = "io.circe" %% "circe-parser" % circeVersion
  lazy val circeJava8 = "io.circe" %% "circe-java8" % circeVersion
  lazy val jawn = "org.typelevel" %% "jawn-parser" % "0.14.1"
  lazy val circeJawn = "io.circe" %% "circe-jawn" % circeVersion
  lazy val catsEffect = "org.typelevel" %% "cats-effect" % "1.2.0"
  lazy val http4sCore = "org.http4s" %% "http4s-core" % http4sVersion
  lazy val http4sServer = "org.http4s" %% "http4s-blaze-server" % http4sVersion
  lazy val http4sCirce = "org.http4s" %% "http4s-circe" % http4sVersion
  lazy val http4sDsl = "org.http4s" %% "http4s-dsl" % http4sVersion
  lazy val http4sClient = "org.http4s" %% "http4s-blaze-client" % http4sVersion
}

I am not sure whether I have to specify all dependencies which are used by http4s template. It seems I have to.

In result, sbt plugin fails with lots of compilation errors. The first error is:

[error] /Users/aa/dev/git/Aethernity/ae-client/target/scala-2.12/src_managed/main/swagger/definitions/Channel.scala:5:187: not found: type EncodedHash
[error] case class Channel(id: String, initiatorId: String, responderId: String, channelAmount: Long, initiatorAmount: Long, responderAmount: Long, channelReserve: Long, delegateIds: IndexedSeq[EncodedHash] = IndexedSeq.empty, stateHash: String, round: Long, soloRound: Long, lockPeriod: Long, lockedUntil: Long)
[error]                                                                                                                                                                                           ^
[error] /Users/aa/dev/git/Aethernity/ae-client/target/scala-2.12/src_managed/main/swagger/definitions/ChannelCloseMutualTxJSON.scala:5:216: class ChannelCloseMutualTx needs to be a trait to be mixed in
[error] case class ChannelCloseMutualTxJSON(version: Long, channelId: String, fromId: String, initiatorAmountFinal: Long, responderAmountFinal: Long, ttl: Option[Long] = None, fee: Long, nonce: Long) extends GenericTx with ChannelCloseMutualTx

P.S. original issue: https://github.com/twilio/sbt-guardrail/issues/11

z4f1r0v commented 2 years ago

I'm also facing the same issue. For reference this is where the swagger code mentioned above lives right now.

blast-hardcheese commented 2 years ago

I'll take a look to see whether the recent work cleaning up internal data models has added clarity as to why this happens

blast-hardcheese commented 9 months ago

Minimal reproducing case:

swagger: '2.0'
info:
  description: 'This is the [Aeternity](https://www.aeternity.com/) node API.'
basePath: /v2
schemes:
  - http
definitions:
  ChannelCreateTx:
    type: object
    properties:
      foo:
        type: string
    required:
      - foo
  GenericTx:
    type: object
    discriminator: type
    properties:
      bar:
        type: string
    required:
      - bar
  ChannelCreateTxJSON:
    allOf:
      - $ref: '#/definitions/GenericTx'
      - $ref: '#/definitions/ChannelCreateTx'