diff --git a/core/src/main/scala-2/sttp/tapir/internal/OneOfMacro.scala b/core/src/main/scala-2/sttp/tapir/internal/OneOfMacro.scala index a662315471..72f9f60ba6 100644 --- a/core/src/main/scala-2/sttp/tapir/internal/OneOfMacro.scala +++ b/core/src/main/scala-2/sttp/tapir/internal/OneOfMacro.scala @@ -45,31 +45,26 @@ private[tapir] object OneOfMacro { val schemaForE = q"""{ - import _root_.sttp.tapir.internal._ - import _root_.sttp.tapir.Schema - import _root_.sttp.tapir.Schema._ - import _root_.sttp.tapir.SchemaType._ - import _root_.scala.collection.immutable.{List, Map} - val mappingAsList = List(..$mapping) - val mappingAsMap: Map[$weakTypeV, Schema[_]] = mappingAsList.toMap + val mappingAsList = _root_.scala.collection.immutable.List(..$mapping) + val mappingAsMap: _root_.scala.collection.immutable.Map[$weakTypeV, _root_.sttp.tapir.Schema[_]] = mappingAsList.toMap val discriminatorName = _root_.sttp.tapir.FieldName($name, $conf.toEncodedName($name)) // cannot use .collect because of a bug in ScalaJS (Trying to access the this of another class ... during phase: jscode) val discriminatorMapping = mappingAsMap.toList.flatMap { - case (k, Schema(_, Some(fname), _, _, _, _, _, _, _, _, _)) => List($asString.apply(k) -> SRef(fname)) - case _ => Nil + case (k, _root_.sttp.tapir.Schema(_, _root_.scala.Some(fname), _, _, _, _, _, _, _, _, _)) => _root_.scala.collection.immutable.List($asString.apply(k) -> _root_.sttp.tapir.SchemaType.SRef(fname)) + case _ => _root_.scala.Nil } .toMap - val sname = SName(${weakTypeE.typeSymbol.fullName},${extractTypeArguments(c)(weakTypeE)}) + val sname = _root_.sttp.tapir.Schema.SName(${weakTypeE.typeSymbol.fullName},${extractTypeArguments(c)(weakTypeE)}) // cast needed because of Scala 2.12 val subtypes = mappingAsList.map(_._2) - Schema((SCoproduct[$weakTypeE](subtypes, None) { e => + _root_.sttp.tapir.Schema((_root_.sttp.tapir.SchemaType.SCoproduct[$weakTypeE](subtypes, _root_.scala.None) { e => val ee: $weakTypeV = $extractor(e) - mappingAsMap.get(ee).map(m => SchemaWithValue(m.asInstanceOf[Schema[Any]], e)) + mappingAsMap.get(ee).map(m => _root_.sttp.tapir.SchemaType.SchemaWithValue(m.asInstanceOf[_root_.sttp.tapir.Schema[Any]], e)) }).addDiscriminatorField( discriminatorName, $discriminatorSchema, discriminatorMapping - ), Some(sname)) + ), _root_.scala.Some(sname)) }""" Debug.logGeneratedCode(c)(weakTypeE.typeSymbol.fullName, schemaForE) @@ -88,32 +83,27 @@ private[tapir] object OneOfMacro { val subclasses = symbol.knownDirectSubclasses.toList.sortBy(_.name.encodedName.toString) val subclassesSchemas = subclasses.map(subclass => - q"${subclass.name.encodedName.toString} -> Schema.wrapWithSingleFieldProduct(implicitly[Schema[${subclass.asType}]])($conf)" + q"${subclass.name.encodedName.toString} -> _root_.sttp.tapir.Schema.wrapWithSingleFieldProduct(_root_.scala.Predef.implicitly[_root_.sttp.tapir.Schema[${subclass.asType}]])($conf)" ) val subclassesSchemaCases = subclasses.map { subclass => - cq"""v: ${subclass.asType} => Some(SchemaWithValue(subclassNameToSchemaMap(${subclass.name.encodedName.toString}).asInstanceOf[Schema[Any]], v))""" + cq"""v: ${subclass.asType} => _root_.scala.Some(_root_.sttp.tapir.SchemaType.SchemaWithValue(subclassNameToSchemaMap(${subclass.name.encodedName.toString}).asInstanceOf[_root_.sttp.tapir.Schema[Any]], v))""" } val schemaForE = q"""{ - import _root_.sttp.tapir.Schema - import _root_.sttp.tapir.Schema._ - import _root_.sttp.tapir.SchemaType._ - import _root_.scala.collection.immutable.{List, Map} + val subclassNameToSchema: _root_.scala.collection.immutable.List[(String, _root_.sttp.tapir.Schema[_])] = _root_.scala.collection.immutable.List($subclassesSchemas: _*) + val subclassNameToSchemaMap: _root_.scala.collection.immutable.Map[String, _root_.sttp.tapir.Schema[_]] = subclassNameToSchema.toMap - val subclassNameToSchema: List[(String, Schema[_])] = List($subclassesSchemas: _*) - val subclassNameToSchemaMap: Map[String, Schema[_]] = subclassNameToSchema.toMap - - val sname = SName(${weakTypeE.typeSymbol.fullName},${extractTypeArguments(c)(weakTypeE)}) + val sname = _root_.sttp.tapir.Schema.SName(${weakTypeE.typeSymbol.fullName},${extractTypeArguments(c)(weakTypeE)}) // cast needed because of Scala 2.12 val subtypes = subclassNameToSchema.map(_._2) - Schema( - schemaType = SCoproduct[$weakTypeE](subtypes, None) { e => + _root_.sttp.tapir.Schema( + schemaType = _root_.sttp.tapir.SchemaType.SCoproduct[$weakTypeE](subtypes, _root_.scala.None) { e => e match { case ..$subclassesSchemaCases } - }, - name = Some(sname) + }, + name = _root_.scala.Some(sname) ) }""" diff --git a/core/src/main/scala-2/sttp/tapir/internal/SchemaAnnotationsMacro.scala b/core/src/main/scala-2/sttp/tapir/internal/SchemaAnnotationsMacro.scala index 3142efb3ee..ccad712f9e 100644 --- a/core/src/main/scala-2/sttp/tapir/internal/SchemaAnnotationsMacro.scala +++ b/core/src/main/scala-2/sttp/tapir/internal/SchemaAnnotationsMacro.scala @@ -43,7 +43,7 @@ private[tapir] object SchemaAnnotationsMacro { val validateEach = annotations.collect { case ann if ann.tree.tpe <:< ValidateEachAnn => firstArg(ann) } c.Expr[SchemaAnnotations[T]]( - q"""_root_.sttp.tapir.SchemaAnnotations.apply($description, $encodedExample, $default, $format, $deprecated, $hidden, $encodedName, List(..$validate), List(..$validateEach))""" + q"""_root_.sttp.tapir.SchemaAnnotations.apply($description, $encodedExample, $default, $format, $deprecated, $hidden, $encodedName, _root_.scala.List(..$validate), _root_.scala.List(..$validateEach))""" ) } } diff --git a/core/src/main/scala-2/sttp/tapir/internal/SchemaMapMacro.scala b/core/src/main/scala-2/sttp/tapir/internal/SchemaMapMacro.scala index 657fb95966..31cb69003f 100644 --- a/core/src/main/scala-2/sttp/tapir/internal/SchemaMapMacro.scala +++ b/core/src/main/scala-2/sttp/tapir/internal/SchemaMapMacro.scala @@ -9,7 +9,7 @@ private[tapir] object SchemaMapMacro { c: blackbox.Context )(schemaForV: c.Expr[Schema[V]]): c.Expr[Schema[Map[String, V]]] = { import c.universe._ - generateSchemaForMap[String, V](c)(c.Expr[String => String](q"""identity"""))(schemaForV) + generateSchemaForMap[String, V](c)(c.Expr[String => String](q"""_root_.scala.Predef.identity"""))(schemaForV) } /* Extract name and generic type parameters of map value type for object info creation */ @@ -34,8 +34,8 @@ private[tapir] object SchemaMapMacro { q"""{ val s = $schemaForV _root_.sttp.tapir.Schema( - _root_.sttp.tapir.SchemaType.SOpenProduct(Nil, s)(_.map { case (k, v) => ($keyToString(k), v) }), - Some(_root_.sttp.tapir.Schema.SName("Map", $genericTypeParameters)) + _root_.sttp.tapir.SchemaType.SOpenProduct(_root_.scala.Nil, s)(_.map { case (k, v) => ($keyToString(k), v) }), + _root_.scala.Some(_root_.sttp.tapir.Schema.SName("Map", $genericTypeParameters)) ) }""" Debug.logGeneratedCode(c)(weakTypeV.typeSymbol.fullName, schemaForMap) diff --git a/core/src/main/scala-2/sttp/tapir/internal/ValidatorEnumerationMacro.scala b/core/src/main/scala-2/sttp/tapir/internal/ValidatorEnumerationMacro.scala index bea98f7989..336b96dae6 100644 --- a/core/src/main/scala-2/sttp/tapir/internal/ValidatorEnumerationMacro.scala +++ b/core/src/main/scala-2/sttp/tapir/internal/ValidatorEnumerationMacro.scala @@ -29,7 +29,7 @@ private[tapir] object ValidatorEnumerationMacro { } else { val instances = subclasses.map(x => Ident(x.asInstanceOf[scala.reflect.internal.Symbols#Symbol].sourceModule.asInstanceOf[Symbol])) val validatorEnum = - q"_root_.sttp.tapir.Validator.Enumeration($instances, None, Some(_root_.sttp.tapir.Schema.SName(${symbol.fullName})))" + q"_root_.sttp.tapir.Validator.Enumeration($instances, _root_.scala.None, _root_.scala.Some(_root_.sttp.tapir.Schema.SName(${symbol.fullName})))" Debug.logGeneratedCode(c)(t.typeSymbol.fullName, validatorEnum) c.Expr[Validator.Enumeration[E]](validatorEnum) } @@ -54,7 +54,7 @@ private[tapir] object ValidatorEnumerationMacro { case Nil => c.abort(c.enclosingPosition, s"Invalid enum name: ${weakTypeT.toString}") } - q"_root_.sttp.tapir.Validator.enumeration($enumeration.values.toList, v => Option(v), Some(sttp.tapir.Schema.SName(${enumNameComponents + q"_root_.sttp.tapir.Validator.enumeration($enumeration.values.toList, v => _root_.scala.Option(v), _root_.scala.Some(sttp.tapir.Schema.SName(${enumNameComponents .mkString(".")})))" } } diff --git a/core/src/test/scala/sttp/tapir/namespacing/SchemaMacroNamespaceTest.scala b/core/src/test/scala/sttp/tapir/namespacing/SchemaMacroNamespaceTest.scala index 8b00a7906b..8c453bd422 100644 --- a/core/src/test/scala/sttp/tapir/namespacing/SchemaMacroNamespaceTest.scala +++ b/core/src/test/scala/sttp/tapir/namespacing/SchemaMacroNamespaceTest.scala @@ -2,6 +2,7 @@ package sttp.tapir.namespacing import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers +import sttp.tapir.Schema class SchemaMacroNamespaceTest extends AnyFlatSpec with Matchers { @@ -16,4 +17,80 @@ class SchemaMacroNamespaceTest extends AnyFlatSpec with Matchers { import sttp.tapir.Codec Codec.derivedEnumeration[String, MyProduct](MyProduct.fromString, _.toString) } + + it should "compile macro-generated code for shadowed _root_.scala names" in { + + /** @see [[https://github.com/softwaremill/tapir/issues/3407 Github Issue #3407]] */ + sealed abstract class BuiltinTypenameCollisionEnum + + object BuiltinTypenameCollisionEnum { + case object Option extends BuiltinTypenameCollisionEnum + case object Some extends BuiltinTypenameCollisionEnum + case object None extends BuiltinTypenameCollisionEnum + case object List extends BuiltinTypenameCollisionEnum + case object Nil extends BuiltinTypenameCollisionEnum + case object Map extends BuiltinTypenameCollisionEnum + case object Array extends BuiltinTypenameCollisionEnum + case object Either extends BuiltinTypenameCollisionEnum + case object Left extends BuiltinTypenameCollisionEnum + case object Right extends BuiltinTypenameCollisionEnum + case object Unit extends BuiltinTypenameCollisionEnum + + case object implicitly extends BuiltinTypenameCollisionCaseClass + case object identity extends BuiltinTypenameCollisionCaseClass + + val schema: sttp.tapir.Schema[BuiltinTypenameCollisionEnum] = + sttp.tapir.Schema.derivedEnumeration[BuiltinTypenameCollisionEnum].defaultStringBased + } + + sealed abstract class BuiltinTypenameCollisionCaseClass + + object BuiltinTypenameCollisionCaseClass { + + import sttp.tapir.generic.auto._ + + case class Option(a: String) extends BuiltinTypenameCollisionCaseClass + case class Some(a: Int) extends BuiltinTypenameCollisionCaseClass + case class None(b: Boolean) extends BuiltinTypenameCollisionCaseClass + case class List(c: String) extends BuiltinTypenameCollisionCaseClass + case class Nil(b: String) extends BuiltinTypenameCollisionCaseClass + case class Map(d: Int) extends BuiltinTypenameCollisionCaseClass + + /** can't make this work - it either can't derive schema, or when schema is explicit in companion like below, it fails with next + * alphabetical co-product part. Magnolia issue? + * {{{ + * case class Array(a: Boolean) extends BuiltinTypenameCollisionCaseClass + * + * object Array { + * implicit lazy val schema: sttp.tapir.Schema[Array] = Schema( + * sttp.tapir.SchemaType.SProduct( + * scala.List( + * sttp.tapir.SchemaType.SProductField( + * sttp.tapir.FieldName("a"), + * Schema.schemaForBoolean, + * (_: Any) => scala.None + * ) + * ) + * ) + * ) + * } + * }}} + */ + + case class Either(e: String) extends BuiltinTypenameCollisionCaseClass + case class Left(x: Double) extends BuiltinTypenameCollisionCaseClass + case class Right(y: Double) extends BuiltinTypenameCollisionCaseClass + case class Unit() extends BuiltinTypenameCollisionCaseClass + case class implicitly(a: Int) extends BuiltinTypenameCollisionCaseClass + case class identity(b: Boolean) extends BuiltinTypenameCollisionCaseClass + + val schema: sttp.tapir.Schema[BuiltinTypenameCollisionCaseClass] = + sttp.tapir.Schema.oneOfWrapped[BuiltinTypenameCollisionCaseClass] + } + + assert( + List(BuiltinTypenameCollisionCaseClass.schema, BuiltinTypenameCollisionEnum.schema).flatMap(_.name).nonEmpty + ) + } + }