Allow to retrieve schema type parameters full name
Hi there, I faced the following issue:
import sttp.tapir._
import sttp.tapir.generic.auto._
object A {
case class B(a: String)
}
object B {
case class B(b: Int)
}
case class Value[C](c: C)
Schema.derivedSchema[A.B].name //Some(SName(Playground.A.B,List()))
Schema.derivedSchema[Value[A.B]].name //Some(SName(Playground.Value,List(B)))
Schema.derivedSchema[Value[B.B]].name //Some(SName(Playground.Value,List(B)))
Specifically Value[A.B] and Value[B.B] produce the same Schema.SName that causes a conflict in the docs components.
As a temp fix I copied derivation logic:
https://github.com/softwaremill/tapir/blob/2f38f0c9562056340c1cf8f634047287826fab5f/core/src/main/scala-2/sttp/tapir/generic/auto/SchemaMagnoliaDerivation.scala#L49
with a small change: .map(_.short) -> .map(_.full)
Probably this is not a great final fix as an argument with name typeParameterShortNames contains a full type name now, but you should get an idea of the possible solution.
What do you think?
cc: @jackcviers
Hm maybe we should use some heuristic, instead of just "short" vs "full", include all name components (as divided by .) from the first one that starts with a capital letter (and which hence is an object / class)?
@adamw both will work for me. Anyway there is another transformation step from SName to component name in docs options, for example sttp.tapir.docs.openapi.OpenAPIDocsOptions#schemaName, which looks like:
private[docs] val defaultSchemaName: SName => String = info => {
val shortName = info.fullName.split('.').last
(shortName +: info.typeParameterShortNames).mkString("_")
}
In my case I added .replaceAll("\\.", "_"), with name components I'll join them by _
@yakivy yes, although during schema generation, there's also a de-duplication step, which in case of classes with same fullname, but different schema names, add a 2 (or 3...) suffix, so this would be not ideal, but not a bug.
Anyway, we should apply the same logic here. Maybe you'd like to try a PR? :)
@adamw no problem, will try to find a bit of time this week. How strict is tapir regarding to binary compatibility? Is it ok to rename type params field like:
case class SName(fullName: String, typeParameterNames: List[String])
or better to keep it as is with a fat warning in docs?
Great :) In case of classes in core, we need to maintain binary compatibility. So I think the name is fixed, we'll have to resort to comments. You can check if your changes are binary-compatible using mimaCheckBinaryCompatibility while in core.
@adamw PR is ready for review