diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4583ce276..04294f35f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - scala: [2.13.16] + scala: [2.13.18] java: [temurin@17, temurin@21, temurin@25] runs-on: ${{ matrix.os }} steps: @@ -83,7 +83,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.16] + scala: [2.13.18] java: [temurin@17] runs-on: ${{ matrix.os }} steps: diff --git a/macros/src/main/scala/com/avsystem/commons/macros/MacroCommons.scala b/macros/src/main/scala/com/avsystem/commons/macros/MacroCommons.scala index e4d106014..325fc8536 100644 --- a/macros/src/main/scala/com/avsystem/commons/macros/MacroCommons.scala +++ b/macros/src/main/scala/com/avsystem/commons/macros/MacroCommons.scala @@ -234,11 +234,18 @@ trait MacroCommons extends CompatMacroCommons { bundle => primaryConstructorOf(clsTpe).typeSignatureIn(clsTpe) } + private def isDefaultAnnotArg(tree: Tree): Boolean = { + (tree.tpe match { + case AnnotatedType(annots, _) => annots.exists(_.tree.tpe.typeSymbol.name.toString == "defaultArg") + case _ => false + }) || + tree.symbol != null && tree.symbol.isSynthetic && tree.symbol.name.decodedName.toString.contains("$default$") + } + lazy val treeRes: Res[Tree] = annotTree match { case Apply(constr, args) => val newArgs = (args zip constructorSig.paramLists.head) map { - case (arg, param) if param.asTerm.isParamWithDefault && arg.symbol != null && - arg.symbol.isSynthetic && arg.symbol.name.decodedName.toString.contains("$default$") => + case (arg, param) if param.asTerm.isParamWithDefault && isDefaultAnnotArg(arg) => if (findAnnotation(param, DefaultsToNameAT).nonEmpty) Ok(q"${subject.name.decodedName.toString}") else @@ -283,6 +290,7 @@ trait MacroCommons extends CompatMacroCommons { bundle => .collectFirst { case (param, arg) if param.name == subSym.name => arg match { case Literal(Constant(value: T)) => value + case _ if param.asTerm.isParamWithDefault && isDefaultAnnotArg(arg) => whenDefault case t if param.asTerm.isParamWithDefault && t.symbol.isSynthetic && t.symbol.name.decodedName.toString.contains("$default$") => whenDefault case t if classTag[T] == classTag[Tree] => t.asInstanceOf[T] @@ -823,6 +831,7 @@ trait MacroCommons extends CompatMacroCommons { bundle => case class LitOrDefault[T: ClassTag](default: T) { def unapply(tree: Tree): Option[T] = tree match { case Literal(Constant(value: T)) => Some(value) + case _ if tree.tpe != null && tree.tpe.toString.endsWith("@scala.annotation.meta.defaultArg") => Some(default) case Select(_, TermName(n)) if n.startsWith("$lessinit$greater$default$") => Some(default) case _ => None } @@ -1394,7 +1403,7 @@ trait MacroCommons extends CompatMacroCommons { bundle => // while typechecking case body and not after that. Therefore we need a macro which will inject itself exactly // into that moment. val fakeMatch = - q""" + q""" import scala.language.experimental.macros def $normName(tpref: $StringCls, value: $ScalaPkg.Any): $ScalaPkg.Any = macro $CommonsPkg.macros.misc.WhiteMiscMacros.normalizeGadtSubtype diff --git a/mongo/jvm/src/main/scala/com/avsystem/commons/mongo/typed/TypedMongoClient.scala b/mongo/jvm/src/main/scala/com/avsystem/commons/mongo/typed/TypedMongoClient.scala index ce7862359..9dfeae98a 100644 --- a/mongo/jvm/src/main/scala/com/avsystem/commons/mongo/typed/TypedMongoClient.scala +++ b/mongo/jvm/src/main/scala/com/avsystem/commons/mongo/typed/TypedMongoClient.scala @@ -57,11 +57,14 @@ class TypedMongoClient( def listDatabaseNames: Observable[String] = multi(optionalizeFirstArg(nativeClient.listDatabaseNames(sessionOrNull))) - def listDatabases: Observable[Document] = + @deprecated("Use listTypedDatabases or listRawDatabases instead", "2.25.0") + def listDatabases: Observable[Nothing] = ??? + + def listRawDatabases: Observable[Document] = multi(optionalizeFirstArg(nativeClient.listDatabases(sessionOrNull))) - def listDatabases[T: GenCodec]: Observable[T] = - listDatabases.map(doc => BsonValueInput.read[T](doc.toBsonDocument)) + def listTypedDatabases[T: GenCodec]: Observable[T] = + listRawDatabases.map(doc => BsonValueInput.read[T](doc.toBsonDocument)) //TODO: `watch` methods diff --git a/mongo/jvm/src/main/scala/com/avsystem/commons/mongo/typed/TypedMongoDatabase.scala b/mongo/jvm/src/main/scala/com/avsystem/commons/mongo/typed/TypedMongoDatabase.scala index 739a05005..9f2144b68 100644 --- a/mongo/jvm/src/main/scala/com/avsystem/commons/mongo/typed/TypedMongoDatabase.scala +++ b/mongo/jvm/src/main/scala/com/avsystem/commons/mongo/typed/TypedMongoDatabase.scala @@ -47,11 +47,14 @@ class TypedMongoDatabase( def listCollectionNames: Observable[String] = multi(optionalizeFirstArg(nativeDatabase.listCollectionNames(sessionOrNull))) - def listCollections: Observable[Document] = + @deprecated("Use listTypedCollections or listRawCollections instead", "2.25.0") + def listDatabases: Observable[Nothing] = ??? + + def listRawCollections: Observable[Document] = multi(optionalizeFirstArg(nativeDatabase.listCollections(sessionOrNull))) - def listCollections[T: GenCodec]: Observable[T] = - listCollections.map(doc => BsonValueInput.read[T](doc.toBsonDocument)) + def listTypedCollections[T: GenCodec]: Observable[T] = + listRawCollections.map(doc => BsonValueInput.read[T](doc.toBsonDocument)) def createCollection( name: String, diff --git a/project/Commons.scala b/project/Commons.scala index 6841e1494..142c705b8 100644 --- a/project/Commons.scala +++ b/project/Commons.scala @@ -65,7 +65,7 @@ object Commons extends ProjectGroup("commons") { Developer("ddworak", "Dawid Dworak", "d.dworak@avsystem.com", url("https://github.com/ddworak")), ), - scalaVersion := "2.13.16", + scalaVersion := "2.13.18", githubWorkflowTargetTags ++= Seq("v*"), githubWorkflowArtifactUpload := false, diff --git a/redis/src/main/scala/com/avsystem/commons/redis/commands/ReplyDecoders.scala b/redis/src/main/scala/com/avsystem/commons/redis/commands/ReplyDecoders.scala index d8f537c5a..f9191385b 100644 --- a/redis/src/main/scala/com/avsystem/commons/redis/commands/ReplyDecoders.scala +++ b/redis/src/main/scala/com/avsystem/commons/redis/commands/ReplyDecoders.scala @@ -303,10 +303,10 @@ object ReplyDecoders { } val multiBulkAsXConsumerInfo: ReplyDecoder[XConsumerInfo] = - flatMultiBulkAsMap(bulkAsUTF8, undecoded).andThen(XConsumerInfo.apply) + flatMultiBulkAsMap(bulkAsUTF8, undecoded).andThen(XConsumerInfo.apply _) val multiBulkAsXGroupInfo: ReplyDecoder[XGroupInfo] = - flatMultiBulkAsMap(bulkAsUTF8, undecoded).andThen(XGroupInfo.apply) + flatMultiBulkAsMap(bulkAsUTF8, undecoded).andThen(XGroupInfo.apply _) def multiBulkAsXStreamInfoOf[Rec: RedisRecordCodec]: ReplyDecoder[XStreamInfo[Rec]] = flatMultiBulkAsMap(bulkAsUTF8, undecoded).andThen(XStreamInfo[Rec](_)) @@ -374,7 +374,7 @@ object ReplyDecoders { flatMultiBulkAsMap(bulkAs[A], bulkAs[B]) def flatMultiBulkAsRecord[R: RedisRecordCodec]: ReplyDecoder[R] = { - case ArrayMsg(elements: IndexedSeq[BulkStringMsg@unchecked]) if elements.forall(_.isInstanceOf[BulkStringMsg]) => + case ArrayMsg(elements: IndexedSeq[BulkStringMsg @unchecked]) if elements.forall(_.isInstanceOf[BulkStringMsg]) => RedisRecordCodec[R].read(elements) }