diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 5a8ebc3..b5ca820 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -23,4 +23,4 @@ jobs: - name: Check project is formatted uses: jrouly/scalafmt-native-action@v1 with: - version: '2.7.5' + version: '3.4.3' diff --git a/.scalafmt.conf b/.scalafmt.conf index d141fdb..d17e2d0 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,14 +1,17 @@ -version = 2.7.5 +version = 3.4.3 +runner.dialect = scala213 preset = default align.preset = most maxColumn = 120 project.git = true -align.tokens.add = [ +docstrings.style = AsteriskSpace +align.tokens."+" = [ {code = ":=", owner = "Term.ApplyInfix"} ] rewrite.rules = [RedundantBraces, RedundantParens] -# TODO update scalafmt for Scala 3 support -project.excludeFilters = [ - "src/main/scala-3/net/ceedubs/ficus/util/EnumerationUtil.scala" -] +fileOverride { + "glob:**/src/main/scala-3/**" { + runner.dialect = scala3 + } +} diff --git a/src/main/scala/net/ceedubs/ficus/readers/DurationReaders.scala b/src/main/scala/net/ceedubs/ficus/readers/DurationReaders.scala index 7b12d00..ce65ec8 100644 --- a/src/main/scala/net/ceedubs/ficus/readers/DurationReaders.scala +++ b/src/main/scala/net/ceedubs/ficus/readers/DurationReaders.scala @@ -8,9 +8,9 @@ import scala.util.Try trait DurationReaders { /** A reader for for a scala.concurrent.duration.FiniteDuration. This reader should be able to read any valid duration - * format as defined by the HOCON spec. - * For example, it can read "15 minutes" or "1 day". - */ + * format as defined by the HOCON spec. For + * example, it can read "15 minutes" or "1 day". + */ implicit def finiteDurationReader: ValueReader[FiniteDuration] = new ValueReader[FiniteDuration] { def read(config: Config, path: String): FiniteDuration = { val nanos = config.getDuration(path, NANOSECONDS) @@ -18,12 +18,13 @@ trait DurationReaders { } } - /** A reader for for a scala.concurrent.duration.Duration. This reader should be able to read any valid duration format - * as defined by the HOCON spec and positive - * and negative infinite values supported by Duration's apply method. - * For example, it can read "15 minutes", "1 day", "-Inf", or "PlusInf". - */ + /** A reader for for a scala.concurrent.duration.Duration. This reader should be able to read any valid duration + * format as defined by the HOCON spec and + * positive and negative infinite values supported by Duration's apply method. For + * example, it can read "15 minutes", "1 day", "-Inf", or "PlusInf". + */ implicit def durationReader: ValueReader[Duration] = new ValueReader[Duration] { def read(config: Config, path: String): Duration = (Try { diff --git a/src/main/scala/net/ceedubs/ficus/readers/InetSocketAddressReaders.scala b/src/main/scala/net/ceedubs/ficus/readers/InetSocketAddressReaders.scala index 9775ddc..c43251d 100644 --- a/src/main/scala/net/ceedubs/ficus/readers/InetSocketAddressReaders.scala +++ b/src/main/scala/net/ceedubs/ficus/readers/InetSocketAddressReaders.scala @@ -18,17 +18,19 @@ trait InetSocketAddressReaders { implicit val inetSocketAddressListReader: ValueReader[List[InetSocketAddress]] = new ValueReader[List[InetSocketAddress]] { def read(config: Config, path: String): List[InetSocketAddress] = - try config - .getString(path) - .split(", *") - .toList - .map(parseHostAndPort) - .partition(_.isEmpty) match { - case (errors, ok) if errors.isEmpty => - ok.flatten - case _ => - throw new IllegalArgumentException("Cannot parse string into hosts and ports") - } catch { + try + config + .getString(path) + .split(", *") + .toList + .map(parseHostAndPort) + .partition(_.isEmpty) match { + case (errors, ok) if errors.isEmpty => + ok.flatten + case _ => + throw new IllegalArgumentException("Cannot parse string into hosts and ports") + } + catch { case e: Exception => throw new ConfigException.WrongType(config.origin(), path, "java.net.InetSocketAddress", "String", e) } @@ -36,8 +38,9 @@ trait InetSocketAddressReaders { implicit val inetSocketAddressReader: ValueReader[InetSocketAddress] = new ValueReader[InetSocketAddress] { def read(config: Config, path: String): InetSocketAddress = - try parseHostAndPort(config.getString(path)) - .getOrElse(throw new IllegalArgumentException("Cannot parse string into host and port")) + try + parseHostAndPort(config.getString(path)) + .getOrElse(throw new IllegalArgumentException("Cannot parse string into host and port")) catch { case e: Exception => throw new ConfigException.WrongType(config.origin(), path, "java.net.InetSocketAddress", "String", e) diff --git a/src/main/scala/net/ceedubs/ficus/readers/NameMapper.scala b/src/main/scala/net/ceedubs/ficus/readers/NameMapper.scala index 1be1a4c..692d1d1 100644 --- a/src/main/scala/net/ceedubs/ficus/readers/NameMapper.scala +++ b/src/main/scala/net/ceedubs/ficus/readers/NameMapper.scala @@ -1,31 +1,34 @@ package net.ceedubs.ficus.readers -/** Defines an object that knows to map between names as they found in the code - * to those who should be defined in the configuration - */ +/** Defines an object that knows to map between names as they found in the code to those who should be defined in the + * configuration + */ trait NameMapper { /** Maps between the name in the code to name in configuration - * @param name The name as found in the code - */ + * @param name + * The name as found in the code + */ def map(name: String): String } /** Helper object to get the current name mapper - */ + */ object NameMapper { /** Gets the name mapper from the implicit scope - * @param nameMapper The name mapper from the implicit scope, or the default name mapper if not found - * @return The name mapper to be used in current implicit scope - */ + * @param nameMapper + * The name mapper from the implicit scope, or the default name mapper if not found + * @return + * The name mapper to be used in current implicit scope + */ def apply()(implicit nameMapper: NameMapper = DefaultNameMapper): NameMapper = nameMapper } /** Default implementation for name mapper, names in code equivalent to names in configuration - */ + */ case object DefaultNameMapper extends NameMapper { override def map(name: String): String = name diff --git a/src/main/scala/net/ceedubs/ficus/readers/ValueReader.scala b/src/main/scala/net/ceedubs/ficus/readers/ValueReader.scala index a85f306..c25611c 100644 --- a/src/main/scala/net/ceedubs/ficus/readers/ValueReader.scala +++ b/src/main/scala/net/ceedubs/ficus/readers/ValueReader.scala @@ -9,8 +9,8 @@ trait ValueReader[A] { self => def read(config: Config, path: String): A /** Turns a ValueReader[A] into a ValueReader[B] by applying the provided transformation `f` on the item of type A - * that is read from config - */ + * that is read from config + */ def map[B](f: A => B): ValueReader[B] = new ValueReader[B] { def read(config: Config, path: String): B = f(self.read(config, path)) } @@ -19,36 +19,35 @@ trait ValueReader[A] { self => object ValueReader { implicit def generatedReader[A](implicit generated: Generated[ValueReader[A]]): ValueReader[A] = generated.value - /** Returns the implicit ValueReader[A] in scope. - * `ValueReader[A]` is equivalent to `implicitly[ValueReader[A]]` - */ + /** Returns the implicit ValueReader[A] in scope. `ValueReader[A]` is equivalent to `implicitly[ValueReader[A]]` + */ def apply[A](implicit reader: ValueReader[A]): ValueReader[A] = reader /** ValueReader that receives a Config whose root is the path being read. - * - * This is generally the most concise way to implement a ValueReader that doesn't depend on the path of the value - * being read. - * - * For example to read a `case class FooBar(foo: Foo, bar: Bar)`, instead of - * {{{ - * new ValueReader[FooBar] { - * def read(config: Config, path: String): FooBar = { - * val localizedConfig = config.getConfig(path) - * FooBar( - * foo = localizedConfig.as[Foo]("foo"), - * bar = localizedConfig.as[Bar]("bar")) - * } - * } - * }}} - * you could do - * {{{ - * ValueReader.relative[FooBar] { config => - * FooBar( - * foo = config.as[Foo]("foo"), - * bar = config.as[Bar]("bar)) - * } - * }}} - */ + * + * This is generally the most concise way to implement a ValueReader that doesn't depend on the path of the value + * being read. + * + * For example to read a `case class FooBar(foo: Foo, bar: Bar)`, instead of + * {{{ + * new ValueReader[FooBar] { + * def read(config: Config, path: String): FooBar = { + * val localizedConfig = config.getConfig(path) + * FooBar( + * foo = localizedConfig.as[Foo]("foo"), + * bar = localizedConfig.as[Bar]("bar")) + * } + * } + * }}} + * you could do + * {{{ + * ValueReader.relative[FooBar] { config => + * FooBar( + * foo = config.as[Foo]("foo"), + * bar = config.as[Bar]("bar)) + * } + * }}} + */ def relative[A](f: Config => A): ValueReader[A] = new ValueReader[A] { def read(config: Config, path: String): A = f(config.getConfig(path)) } diff --git a/src/main/scala/net/ceedubs/ficus/readers/namemappers/HyphenNameMapper.scala b/src/main/scala/net/ceedubs/ficus/readers/namemappers/HyphenNameMapper.scala index ee83940..efdad64 100644 --- a/src/main/scala/net/ceedubs/ficus/readers/namemappers/HyphenNameMapper.scala +++ b/src/main/scala/net/ceedubs/ficus/readers/namemappers/HyphenNameMapper.scala @@ -6,6 +6,6 @@ object HyphenNameMapper extends NameMapper { private lazy val r = "((?<=[a-z0-9])[A-Z]|(?<=[a-zA-Z])[0-9]|(?!^)[A-Z](?=[a-z]))".r /** Maps from a camelCasedName to a hyphenated-name - */ + */ override def map(name: String): String = r.replaceAllIn(name, m => s"-${m.group(1)}").toLowerCase } diff --git a/src/main/scala/net/ceedubs/ficus/readers/namemappers/HyphenNameMapperNoDigits.scala b/src/main/scala/net/ceedubs/ficus/readers/namemappers/HyphenNameMapperNoDigits.scala index 2823c61..c270fab 100644 --- a/src/main/scala/net/ceedubs/ficus/readers/namemappers/HyphenNameMapperNoDigits.scala +++ b/src/main/scala/net/ceedubs/ficus/readers/namemappers/HyphenNameMapperNoDigits.scala @@ -6,6 +6,6 @@ object HyphenNameMapperNoDigits extends NameMapper { private lazy val r = "((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z]))".r /** Maps from a camelCasedName to a hyphenated-name - */ + */ override def map(name: String): String = r.replaceAllIn(name, m => s"-${m.group(1)}").toLowerCase }