diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ae528704e..92f3f12af 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,12 +24,7 @@ jobs: run: sbt "++${{ matrix.scala }} scalafmtCheckAll; scalafmtSbtCheck" - name: Compile - run: > - if [[ "${{ matrix.scala }}" =~ ^2\..* ]]; then - sbt coverage "++${{ matrix.scala }} test"; - else - sbt "++${{ matrix.scala }} test"; - fi + run: sbt "++${{ matrix.scala }} clean; compile" - name: Run tests run: > diff --git a/.scalafmt.conf b/.scalafmt.conf index 6ed2952dd..cc53665d5 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -2,3 +2,5 @@ version = 2.7.5 align.preset = none maxColumn = 120 + +docstrings.style = Asterisk diff --git a/core/src/main/scala-2.12-/pureconfig/FactoryCompat.scala b/core/src/main/scala-2.12-/pureconfig/FactoryCompat.scala index 2b8645c4a..1164aa973 100644 --- a/core/src/main/scala-2.12-/pureconfig/FactoryCompat.scala +++ b/core/src/main/scala-2.12-/pureconfig/FactoryCompat.scala @@ -3,12 +3,13 @@ package pureconfig import scala.collection.generic.CanBuildFrom import scala.collection.mutable -/** A compatibility layer for creating `CanBuildFrom`-like generic methods that work both on Scala 2.13 and pre-2.13 - * versions. - * - * @tparam A the type of elements that get added to the builder - * @tparam C the type of collection that it produces - */ +/** + * A compatibility layer for creating `CanBuildFrom`-like generic methods that work both on Scala 2.13 and pre-2.13 + * versions. + * + * @tparam A the type of elements that get added to the builder + * @tparam C the type of collection that it produces + */ trait FactoryCompat[-A, +C] { def newBuilder(): mutable.Builder[A, C] } diff --git a/core/src/main/scala/pureconfig/BasicReaders.scala b/core/src/main/scala/pureconfig/BasicReaders.scala index 371dda075..ad1f6c546 100644 --- a/core/src/main/scala/pureconfig/BasicReaders.scala +++ b/core/src/main/scala/pureconfig/BasicReaders.scala @@ -19,8 +19,9 @@ import pureconfig.error._ import scala.util.Try -/** Trait containing `ConfigReader` instances for primitive types. - */ +/** + * Trait containing `ConfigReader` instances for primitive types. + */ trait PrimitiveReaders { implicit val stringConfigReader: ConfigReader[String] = ConfigReader.fromCursor(_.asString) @@ -61,8 +62,9 @@ trait PrimitiveReaders { implicit val byteConfigReader: ConfigReader[Byte] = ConfigReader.fromCursor(_.asByte) } -/** Trait containing `ConfigReader` instance for Java Enums. - */ +/** + * Trait containing `ConfigReader` instance for Java Enums. + */ trait JavaEnumReader { implicit def javaEnumReader[A <: java.lang.Enum[A]](implicit tag: ClassTag[A]): ConfigReader[A] = @@ -72,8 +74,9 @@ trait JavaEnumReader { })) } -/** Trait containing `ConfigReader` instances for classes related to file system paths and URIs. - */ +/** + * Trait containing `ConfigReader` instances for classes related to file system paths and URIs. + */ trait UriAndPathReaders { implicit val urlConfigReader: ConfigReader[URL] = ConfigReader.fromNonEmptyString[URL](catchReadError(new URL(_))) @@ -84,16 +87,18 @@ trait UriAndPathReaders { implicit val uriConfigReader: ConfigReader[URI] = ConfigReader.fromString[URI](catchReadError(new URI(_))) } -/** Trait containing `ConfigReader` instances for classes related to regular expressions. - */ +/** + * Trait containing `ConfigReader` instances for classes related to regular expressions. + */ trait RegexReaders { implicit val patternReader: ConfigReader[Pattern] = ConfigReader.fromString[Pattern](catchReadError(Pattern.compile)) implicit val regexReader: ConfigReader[Regex] = ConfigReader.fromString[Regex](catchReadError(new Regex(_))) } -/** Trait containing `ConfigReader` instances for `java.time` classes. - */ +/** + * Trait containing `ConfigReader` instances for `java.time` classes. + */ trait JavaTimeReaders { implicit val instantConfigReader: ConfigReader[Instant] = @@ -115,9 +120,10 @@ trait JavaTimeReaders { ConfigReader.fromNonEmptyString[Year](catchReadError(Year.parse)) } -/** Trait containing `ConfigReader` instances for [[scala.concurrent.duration.Duration]] and - * [[scala.concurrent.duration.FiniteDuration]]. - */ +/** + * Trait containing `ConfigReader` instances for [[scala.concurrent.duration.Duration]] and + * [[scala.concurrent.duration.FiniteDuration]]. + */ trait DurationReaders { implicit val durationConfigReader: ConfigReader[Duration] = @@ -141,8 +147,9 @@ trait DurationReaders { } } -/** Trait containing `ConfigReader` instances for Java and Scala arbitrary-precision numeric types. - */ +/** + * Trait containing `ConfigReader` instances for Java and Scala arbitrary-precision numeric types. + */ trait NumericReaders { implicit val javaBigIntegerReader: ConfigReader[BigInteger] = @@ -158,8 +165,9 @@ trait NumericReaders { ConfigReader.fromNonEmptyString[BigDecimal](catchReadError(BigDecimal(_))) } -/** Trait containing `ConfigReader` instances for Typesafe config models. - */ +/** + * Trait containing `ConfigReader` instances for Typesafe config models. + */ trait TypesafeConfigReaders { implicit val configConfigReader: ConfigReader[Config] = @@ -190,9 +198,10 @@ trait TypesafeConfigReaders { } } -/** Trait containing `ConfigReader` instances for primitive types and simple classes in Java and Scala standard - * libraries. - */ +/** + * Trait containing `ConfigReader` instances for primitive types and simple classes in Java and Scala standard + * libraries. + */ trait BasicReaders extends PrimitiveReaders with JavaEnumReader diff --git a/core/src/main/scala/pureconfig/BasicWriters.scala b/core/src/main/scala/pureconfig/BasicWriters.scala index 0d41c15b1..4a6ca30f0 100644 --- a/core/src/main/scala/pureconfig/BasicWriters.scala +++ b/core/src/main/scala/pureconfig/BasicWriters.scala @@ -15,8 +15,9 @@ import scala.util.matching.Regex import com.typesafe.config._ -/** Trait containing `ConfigWriter` instances for primitive types. - */ +/** + * Trait containing `ConfigWriter` instances for primitive types. + */ trait PrimitiveWriters { implicit val stringConfigWriter: ConfigWriter[String] = ConfigWriter.forPrimitive[String] @@ -30,15 +31,17 @@ trait PrimitiveWriters { implicit val byteConfigWriter: ConfigWriter[Byte] = ConfigWriter.forPrimitive[Byte] } -/** Trait containing instance for `ConfigWriter` for Java Enum. - */ +/** + * Trait containing instance for `ConfigWriter` for Java Enum. + */ trait JavaEnumWriter { implicit def javaEnumWriter[A <: java.lang.Enum[A]]: ConfigWriter[A] = ConfigWriter.toDefaultString[A] } -/** Trait containing `ConfigWriter` instances for classes related to file system paths and URIs. - */ +/** + * Trait containing `ConfigWriter` instances for classes related to file system paths and URIs. + */ trait UriAndPathWriters { implicit val urlConfigWriter: ConfigWriter[URL] = ConfigWriter.toDefaultString[URL] @@ -48,8 +51,9 @@ trait UriAndPathWriters { implicit val uriConfigWriter: ConfigWriter[URI] = ConfigWriter.toDefaultString[URI] } -/** Trait containing `ConfigWriter` instances for classes related to regular expressions. - */ +/** + * Trait containing `ConfigWriter` instances for classes related to regular expressions. + */ trait RegexWriters { implicit val patternWriter: ConfigWriter[Pattern] = ConfigWriter.toString[Pattern](_.pattern) @@ -57,8 +61,9 @@ trait RegexWriters { ConfigWriter.toString[Regex](_.pattern.pattern) // Regex.regex isn't supported until 2.11 } -/** Trait containing `ConfigWriter` instances for `java.time` classes. - */ +/** + * Trait containing `ConfigWriter` instances for `java.time` classes. + */ trait JavaTimeWriters { implicit val instantConfigWriter: ConfigWriter[Instant] = ConfigWriter.toDefaultString[Instant] @@ -74,9 +79,10 @@ trait JavaTimeWriters { implicit val javaDurationConfigWriter: ConfigWriter[JavaDuration] = ConfigWriter.toDefaultString[JavaDuration] } -/** Trait containing `ConfigWriter` instances for [[scala.concurrent.duration.Duration]] and - * [[scala.concurrent.duration.FiniteDuration]]. - */ +/** + * Trait containing `ConfigWriter` instances for [[scala.concurrent.duration.Duration]] and + * [[scala.concurrent.duration.FiniteDuration]]. + */ trait DurationWriters { implicit val durationConfigWriter: ConfigWriter[Duration] = @@ -85,8 +91,9 @@ trait DurationWriters { ConfigWriter.toString[FiniteDuration](DurationUtils.fromDuration) } -/** Trait containing `ConfigWriter` instances for Java and Scala arbitrary-precision numeric types. - */ +/** + * Trait containing `ConfigWriter` instances for Java and Scala arbitrary-precision numeric types. + */ trait NumericWriters { implicit val javaBigDecimalWriter: ConfigWriter[JavaBigDecimal] = ConfigWriter.toDefaultString[JavaBigDecimal] @@ -95,8 +102,9 @@ trait NumericWriters { implicit val scalaBigIntWriter: ConfigWriter[BigInt] = ConfigWriter.toDefaultString[BigInt] } -/** Trait containing `ConfigWriter` instances for Typesafe config models. - */ +/** + * Trait containing `ConfigWriter` instances for Typesafe config models. + */ trait TypesafeConfigWriters { implicit val configConfigWriter: ConfigWriter[Config] = new ConfigWriter[Config] { @@ -120,9 +128,10 @@ trait TypesafeConfigWriters { } } -/** Trait containing `ConfigWriter` instances for primitive types and simple classes in Java and Scala standard - * libraries. - */ +/** + * Trait containing `ConfigWriter` instances for primitive types and simple classes in Java and Scala standard + * libraries. + */ trait BasicWriters extends PrimitiveWriters with JavaEnumWriter diff --git a/core/src/main/scala/pureconfig/CollectionReaders.scala b/core/src/main/scala/pureconfig/CollectionReaders.scala index e44504e35..ba5fa7a36 100644 --- a/core/src/main/scala/pureconfig/CollectionReaders.scala +++ b/core/src/main/scala/pureconfig/CollectionReaders.scala @@ -3,16 +3,18 @@ package pureconfig import scala.language.higherKinds import scala.reflect.ClassTag -/** A marker trait signaling that a `ConfigReader` accepts missing (undefined) values. - * - * The standard behavior of `ConfigReader`s that expect required keys in config objects is to return a `KeyNotFound` - * failure when one or more of them are missing. Mixing in this trait into the key's `ConfigReader` signals that if - * a value is missing for the key, the `ConfigReader` can be called with a cursor in the "undefined" state. - */ +/** + * A marker trait signaling that a `ConfigReader` accepts missing (undefined) values. + * + * The standard behavior of `ConfigReader`s that expect required keys in config objects is to return a `KeyNotFound` + * failure when one or more of them are missing. Mixing in this trait into the key's `ConfigReader` signals that if + * a value is missing for the key, the `ConfigReader` can be called with a cursor in the "undefined" state. + */ trait ReadsMissingKeys { this: ConfigReader[_] => } -/** Trait containing `ConfigReader` instances for collection types. - */ +/** + * Trait containing `ConfigReader` instances for collection types. + */ trait CollectionReaders { implicit def optionReader[A](implicit conv: Derivation[ConfigReader[A]]): ConfigReader[Option[A]] = diff --git a/core/src/main/scala/pureconfig/CollectionWriters.scala b/core/src/main/scala/pureconfig/CollectionWriters.scala index 2cf6cea1e..a36c37084 100644 --- a/core/src/main/scala/pureconfig/CollectionWriters.scala +++ b/core/src/main/scala/pureconfig/CollectionWriters.scala @@ -5,17 +5,19 @@ import scala.language.higherKinds import com.typesafe.config._ -/** A trait signaling that a `ConfigWriter` can write missing (undefined) values. - * - * `ConfigWriter`s always produce a valid `ConfigValue` with their `to` method. This trait adds an extra `toOpt` - * method that parent writers can use in order to decide whether or not they should write a value using this writer. - */ +/** + * A trait signaling that a `ConfigWriter` can write missing (undefined) values. + * + * `ConfigWriter`s always produce a valid `ConfigValue` with their `to` method. This trait adds an extra `toOpt` + * method that parent writers can use in order to decide whether or not they should write a value using this writer. + */ trait WritesMissingKeys[A] { this: ConfigWriter[A] => def toOpt(a: A): Option[ConfigValue] } -/** Trait containing `ConfigWriter` instances for collection types. - */ +/** + * Trait containing `ConfigWriter` instances for collection types. + */ trait CollectionWriters { implicit def optionWriter[A](implicit conv: Derivation[ConfigWriter[A]]): ConfigWriter[Option[A]] = diff --git a/core/src/main/scala/pureconfig/ConfigConvert.scala b/core/src/main/scala/pureconfig/ConfigConvert.scala index fc34f5018..822a6990f 100644 --- a/core/src/main/scala/pureconfig/ConfigConvert.scala +++ b/core/src/main/scala/pureconfig/ConfigConvert.scala @@ -1,8 +1,9 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/** @author Mario Pastorelli - */ +/** + * @author Mario Pastorelli + */ package pureconfig import scala.reflect.ClassTag @@ -10,36 +11,40 @@ import scala.util.Try import pureconfig.error.FailureReason -/** Trait for objects capable of reading and writing objects of a given type from and to `ConfigValues`. - */ +/** + * Trait for objects capable of reading and writing objects of a given type from and to `ConfigValues`. + */ trait ConfigConvert[A] extends ConfigReader[A] with ConfigWriter[A] { outer => - /** Transforms the values read and written by this `ConfigConvert` using two functions. - * - * @param f the function applied to values after they are read; a thrown exception will be caught and converted to a pureconfig FailureReason - * @param g the function applied to values before they are written - * @tparam B the type of the returned `ConfigConvert` - * @return a `ConfigConvert` that reads and writes values of type `B` by applying `f` and `g` on read and write, - * respectively. - */ + /** + * Transforms the values read and written by this `ConfigConvert` using two functions. + * + * @param f the function applied to values after they are read; a thrown exception will be caught and converted to a pureconfig FailureReason + * @param g the function applied to values before they are written + * @tparam B the type of the returned `ConfigConvert` + * @return a `ConfigConvert` that reads and writes values of type `B` by applying `f` and `g` on read and write, + * respectively. + */ def xmap[B](f: A => B, g: B => A): ConfigConvert[B] = ConfigConvert(map(f), contramap(g)) - /** Transforms the values read and written by this `ConfigConvert` using two functions where the reader may - * specify custom failure reason. - * - * @param f the function applied to values after they are read - * @param g the function applied to values before they are written - * @tparam B the type of the returned `ConfigConvert` - * @return a `ConfigConvert` that reads and writes values of type `B` by applying `f` and `g` on read and write, - * respectively. - */ + /** + * Transforms the values read and written by this `ConfigConvert` using two functions where the reader may + * specify custom failure reason. + * + * @param f the function applied to values after they are read + * @param g the function applied to values before they are written + * @tparam B the type of the returned `ConfigConvert` + * @return a `ConfigConvert` that reads and writes values of type `B` by applying `f` and `g` on read and write, + * respectively. + */ def xemap[B](f: A => Either[FailureReason, B], g: B => A): ConfigConvert[B] = ConfigConvert(emap(f), contramap(g)) } -/** Provides methods to create [[ConfigConvert]] instances. - */ +/** + * Provides methods to create [[ConfigConvert]] instances. + */ object ConfigConvert extends ConvertHelpers { def apply[A](implicit conv: Derivation[ConfigConvert[A]]): ConfigConvert[A] = conv.value diff --git a/core/src/main/scala/pureconfig/ConfigCursor.scala b/core/src/main/scala/pureconfig/ConfigCursor.scala index 7f2f3378f..9950fc232 100644 --- a/core/src/main/scala/pureconfig/ConfigCursor.scala +++ b/core/src/main/scala/pureconfig/ConfigCursor.scala @@ -8,46 +8,54 @@ import com.typesafe.config._ import pureconfig.backend.PathUtil import pureconfig.error._ -/** A wrapper for a `ConfigValue` providing safe navigation through the config and holding positional data for better - * error handling. - */ +/** + * A wrapper for a `ConfigValue` providing safe navigation through the config and holding positional data for better + * error handling. + */ sealed trait ConfigCursor { - /** The optional `ConfigValue` which this cursor points to. - */ + /** + * The optional `ConfigValue` which this cursor points to. + */ def valueOpt: Option[ConfigValue] - /** The path in the config to which this cursor points as a list of keys in reverse order (deepest key first). - */ + /** + * The path in the config to which this cursor points as a list of keys in reverse order (deepest key first). + */ def pathElems: List[String] - /** The path in the config to which this cursor points. - */ + /** + * The path in the config to which this cursor points. + */ def path: String = PathUtil.joinPath(pathElems.reverse) - /** The file system location of the config to which this cursor points. - */ + /** + * The file system location of the config to which this cursor points. + */ def origin: Option[ConfigOrigin] = valueOpt.map(_.origin()) - /** Returns whether this cursor points to an undefined value. A cursor can point to an undefined value when a missing - * config key is requested or when a `null` `ConfigValue` is provided, among other reasons. - * - * @return `true` if this cursor points to an undefined value, `false` otherwise. - */ + /** + * Returns whether this cursor points to an undefined value. A cursor can point to an undefined value when a missing + * config key is requested or when a `null` `ConfigValue` is provided, among other reasons. + * + * @return `true` if this cursor points to an undefined value, `false` otherwise. + */ def isUndefined: Boolean = valueOpt.isEmpty - /** Returns whether this cursor points to a `null` config value. An explicit `null` value is different than a missing - * value - `isUndefined` can be used to check for the latter. - * - * @return `true` if this cursor points to a `null` value, `false` otherwise. - */ + /** + * Returns whether this cursor points to a `null` config value. An explicit `null` value is different than a missing + * value - `isUndefined` can be used to check for the latter. + * + * @return `true` if this cursor points to a `null` value, `false` otherwise. + */ def isNull: Boolean = valueOpt.exists(_.unwrapped == null) - /** Casts this cursor to a `ConfigValue`. - * - * @return a `Right` with the config value pointed to by this cursor if the value is defined, `Left` with a list of - * failures otherwise. - */ + /** + * Casts this cursor to a `ConfigValue`. + * + * @return a `Right` with the config value pointed to by this cursor if the value is defined, `Left` with a list of + * failures otherwise. + */ def asConfigValue: ConfigReader.Result[ConfigValue] = { valueOpt match { case Some(value) => Right(value) @@ -55,27 +63,30 @@ sealed trait ConfigCursor { } } - /** Casts this cursor to a string. - * - * @return a `Right` with the string value pointed to by this cursor if the cast can be done, `Left` with a list of - * failures otherwise. - */ + /** + * Casts this cursor to a string. + * + * @return a `Right` with the string value pointed to by this cursor if the cast can be done, `Left` with a list of + * failures otherwise. + */ def asString: ConfigReader.Result[String] = castOrFail(STRING, v => Right(v.unwrapped.asInstanceOf[String])) - /** Casts this cursor to a boolean. - * - * @return a `Right` with the boolean value pointed to by this cursor if the cast can be done, `Left` with a list of - * failures otherwise. - */ + /** + * Casts this cursor to a boolean. + * + * @return a `Right` with the boolean value pointed to by this cursor if the cast can be done, `Left` with a list of + * failures otherwise. + */ def asBoolean: ConfigReader.Result[Boolean] = castOrFail(BOOLEAN, v => Right(v.unwrapped.asInstanceOf[Boolean])) - /** Casts this cursor to a long. - * - * @return a `Right` with the long value pointed to by this cursor if the cast can be done, `Left` with a list of - * failures otherwise. - */ + /** + * Casts this cursor to a long. + * + * @return a `Right` with the long value pointed to by this cursor if the cast can be done, `Left` with a list of + * failures otherwise. + */ def asLong: ConfigReader.Result[Long] = castOrFail( NUMBER, @@ -87,11 +98,12 @@ sealed trait ConfigCursor { } ) - /** Casts this cursor to an int. - * - * @return a `Right` with the int value pointed to by this cursor if the cast can be done, `Left` with a list of - * failures otherwise. - */ + /** + * Casts this cursor to an int. + * + * @return a `Right` with the int value pointed to by this cursor if the cast can be done, `Left` with a list of + * failures otherwise. + */ def asInt: ConfigReader.Result[Int] = castOrFail( NUMBER, @@ -103,11 +115,12 @@ sealed trait ConfigCursor { } ) - /** Casts this cursor to a short. - * - * @return a `Right` with the short value pointed to by this cursor if the cast can be done, `Left` with a list of - * failures otherwise. - */ + /** + * Casts this cursor to a short. + * + * @return a `Right` with the short value pointed to by this cursor if the cast can be done, `Left` with a list of + * failures otherwise. + */ def asShort: ConfigReader.Result[Short] = castOrFail( NUMBER, @@ -119,11 +132,12 @@ sealed trait ConfigCursor { } ) - /** Casts this cursor to a byte. - * - * @return a `Right` with the byte value pointed to by this cursor if the cast can be done, `Left` with a list of - * failures otherwise. - */ + /** + * Casts this cursor to a byte. + * + * @return a `Right` with the byte value pointed to by this cursor if the cast can be done, `Left` with a list of + * failures otherwise. + */ def asByte: ConfigReader.Result[Byte] = castOrFail( NUMBER, @@ -135,11 +149,12 @@ sealed trait ConfigCursor { } ) - /** Casts this cursor to a double. - * - * @return a `Right` with the double value pointed to by this cursor if the cast can be done, `Left` with a list of - * failures otherwise. - */ + /** + * Casts this cursor to a double. + * + * @return a `Right` with the double value pointed to by this cursor if the cast can be done, `Left` with a list of + * failures otherwise. + */ def asDouble: ConfigReader.Result[Double] = castOrFail( NUMBER, @@ -151,11 +166,12 @@ sealed trait ConfigCursor { } ) - /** Casts this cursor to a float. - * - * @return a `Right` with the float value pointed to by this cursor if the cast can be done, `Left` with a list of - * failures otherwise. - */ + /** + * Casts this cursor to a float. + * + * @return a `Right` with the float value pointed to by this cursor if the cast can be done, `Left` with a list of + * failures otherwise. + */ def asFloat: ConfigReader.Result[Float] = castOrFail( NUMBER, @@ -167,52 +183,58 @@ sealed trait ConfigCursor { } ) - /** Casts this cursor to a `ConfigListCursor`. - * - * @return a `Right` with this cursor as a list cursor if the cast can be done, `Left` with a list of failures - * otherwise. - */ + /** + * Casts this cursor to a `ConfigListCursor`. + * + * @return a `Right` with this cursor as a list cursor if the cast can be done, `Left` with a list of failures + * otherwise. + */ def asListCursor: ConfigReader.Result[ConfigListCursor] = castOrFail(LIST, v => Right(v.asInstanceOf[ConfigList])).right.map(ConfigListCursor(_, pathElems)) - /** Casts this cursor to a list of cursors. - * - * @return a `Right` with the list pointed to by this cursor if the cast can be done, `Left` with a list of failures - * otherwise. - */ + /** + * Casts this cursor to a list of cursors. + * + * @return a `Right` with the list pointed to by this cursor if the cast can be done, `Left` with a list of failures + * otherwise. + */ def asList: ConfigReader.Result[List[ConfigCursor]] = asListCursor.right.map(_.list) - /** Casts this cursor to a `ConfigObjectCursor`. - * - * @return a `Right` with this cursor as an object cursor if it points to an object, `Left` with a list of failures - * otherwise. - */ + /** + * Casts this cursor to a `ConfigObjectCursor`. + * + * @return a `Right` with this cursor as an object cursor if it points to an object, `Left` with a list of failures + * otherwise. + */ def asObjectCursor: ConfigReader.Result[ConfigObjectCursor] = castOrFail(OBJECT, v => Right(v.asInstanceOf[ConfigObject])).right.map(ConfigObjectCursor(_, pathElems)) - /** Casts this cursor to a map from config keys to cursors. - * - * @return a `Right` with the map pointed to by this cursor if the cast can be done, `Left` with a list of failures - * otherwise. - */ + /** + * Casts this cursor to a map from config keys to cursors. + * + * @return a `Right` with the map pointed to by this cursor if the cast can be done, `Left` with a list of failures + * otherwise. + */ def asMap: ConfigReader.Result[Map[String, ConfigCursor]] = asObjectCursor.right.map(_.map) - /** Returns a cursor to the config at the path composed of given path segments. - * - * @param pathSegments the path of the config for which a cursor should be returned - * @return a `Right` with a cursor to the config at `pathSegments` if such a config exists, a `Left` with a list of - * failures otherwise. - */ + /** + * Returns a cursor to the config at the path composed of given path segments. + * + * @param pathSegments the path of the config for which a cursor should be returned + * @return a `Right` with a cursor to the config at `pathSegments` if such a config exists, a `Left` with a list of + * failures otherwise. + */ @deprecated("Use `.fluent.at(pathSegments).cursor` instead", "0.10.2") final def atPath(pathSegments: PathSegment*): ConfigReader.Result[ConfigCursor] = fluent.at(pathSegments: _*).cursor - /** Casts this cursor as either a `ConfigListCursor` or a `ConfigObjectCursor`. - * - * @return a `Right` with this cursor as a list or object cursor if the cast can be done, `Left` with a list of - * failures otherwise. - */ + /** + * Casts this cursor as either a `ConfigListCursor` or a `ConfigObjectCursor`. + * + * @return a `Right` with this cursor as a list or object cursor if the cast can be done, `Left` with a list of + * failures otherwise. + */ @deprecated("Use `asListCursor` and/or `asObjectCursor` instead", "0.10.1") def asCollectionCursor: ConfigReader.Result[Either[ConfigListCursor, ConfigObjectCursor]] = { asConfigValue.right.flatMap { value => @@ -225,38 +247,41 @@ sealed trait ConfigCursor { def fluent: FluentConfigCursor = FluentConfigCursor(asConfigValue.right.map(_ => this)) - /** Returns a failed `ConfigReader` result resulting from scoping a `FailureReason` into the context of this cursor. - * - * This operation is the easiest way to return a failure from a `ConfigReader`. - * - * @param reason the reason of the failure - * @tparam A the returning type of the `ConfigReader` - * @return a failed `ConfigReader` result built by scoping `reason` into the context of this cursor. - */ + /** + * Returns a failed `ConfigReader` result resulting from scoping a `FailureReason` into the context of this cursor. + * + * This operation is the easiest way to return a failure from a `ConfigReader`. + * + * @param reason the reason of the failure + * @tparam A the returning type of the `ConfigReader` + * @return a failed `ConfigReader` result built by scoping `reason` into the context of this cursor. + */ def failed[A](reason: FailureReason): ConfigReader.Result[A] = Left(ConfigReaderFailures(failureFor(reason))) - /** Returns a `ConfigReaderFailure` resulting from scoping a `FailureReason` into the context of this cursor. - * - * This operation is useful for constructing `ConfigReaderFailures` when there are multiple `FailureReason`s. - * - * @param reason the reason of the failure - * @return a `ConfigReaderFailure` built by scoping `reason` into the context of this cursor. - */ + /** + * Returns a `ConfigReaderFailure` resulting from scoping a `FailureReason` into the context of this cursor. + * + * This operation is useful for constructing `ConfigReaderFailures` when there are multiple `FailureReason`s. + * + * @param reason the reason of the failure + * @return a `ConfigReaderFailure` built by scoping `reason` into the context of this cursor. + */ def failureFor(reason: FailureReason): ConfigReaderFailure = ConvertFailure(reason, this) - /** Returns a failed `ConfigReader` result resulting from scoping a `Either[FailureReason, A]` into the context of - * this cursor. - * - * This operation is needed when control of the reading process is passed to a place without a `ConfigCursor` - * instance providing the nexessary context (for example, when `ConfigReader.fromString` is used. In those scenarios, - * the call should be wrapped in this method in order to turn `FailureReason` instances into `ConfigReaderFailures`. - * - * @param result the result of a config reading operation - * @tparam A the returning type of the `ConfigReader` - * @return a `ConfigReader` result built by scoping `reason` into the context of this cursor. - */ + /** + * Returns a failed `ConfigReader` result resulting from scoping a `Either[FailureReason, A]` into the context of + * this cursor. + * + * This operation is needed when control of the reading process is passed to a place without a `ConfigCursor` + * instance providing the nexessary context (for example, when `ConfigReader.fromString` is used. In those scenarios, + * the call should be wrapped in this method in order to turn `FailureReason` instances into `ConfigReaderFailures`. + * + * @param result the result of a config reading operation + * @tparam A the returning type of the `ConfigReader` + * @return a `ConfigReader` result built by scoping `reason` into the context of this cursor. + */ def scopeFailure[A](result: Either[FailureReason, A]): ConfigReader.Result[A] = result.left.map { reason => ConfigReaderFailures(failureFor(reason)) } @@ -273,27 +298,30 @@ sealed trait ConfigCursor { object ConfigCursor { - /** Builds a `ConfigCursor` for a `ConfigValue` at a path. - * - * @param value the `ConfigValue` to which the cursor should point - * @param pathElems the path of `value` in the config as a list of keys - * @return a `ConfigCursor` for `value` at the path given by `pathElems`. - */ + /** + * Builds a `ConfigCursor` for a `ConfigValue` at a path. + * + * @param value the `ConfigValue` to which the cursor should point + * @param pathElems the path of `value` in the config as a list of keys + * @return a `ConfigCursor` for `value` at the path given by `pathElems`. + */ def apply(value: ConfigValue, pathElems: List[String]): ConfigCursor = SimpleConfigCursor(Option(value), pathElems) - /** Builds a `ConfigCursor` for an optional `ConfigValue` at a path. - * - * @param value the optional `ConfigValue` to which the cursor should point - * @param pathElems the path of `value` in the config as a list of keys - * @return a `ConfigCursor` for `value` at the path given by `pathElems`. - */ + /** + * Builds a `ConfigCursor` for an optional `ConfigValue` at a path. + * + * @param value the optional `ConfigValue` to which the cursor should point + * @param pathElems the path of `value` in the config as a list of keys + * @return a `ConfigCursor` for `value` at the path given by `pathElems`. + */ def apply(value: Option[ConfigValue], pathElems: List[String]): ConfigCursor = SimpleConfigCursor(value, pathElems) - /** Handle automatic type conversions of `ConfigValue`s the way the - * [[https://github.com/lightbend/config/blob/master/HOCON.md#automatic-type-conversions HOCON specification]] - * describes. This code mimics the behavior of the package-private `com.typesafe.config.impl.DefaultTransformer` class - * in Typesafe Config. - */ + /** + * Handle automatic type conversions of `ConfigValue`s the way the + * [[https://github.com/lightbend/config/blob/master/HOCON.md#automatic-type-conversions HOCON specification]] + * describes. This code mimics the behavior of the package-private `com.typesafe.config.impl.DefaultTransformer` class + * in Typesafe Config. + */ private[pureconfig] def transform( configValue: ConfigValue, requested: ConfigValueType @@ -346,12 +374,14 @@ object ConfigCursor { } } -/** A simple `ConfigCursor` providing no extra operations. - */ +/** + * A simple `ConfigCursor` providing no extra operations. + */ case class SimpleConfigCursor(valueOpt: Option[ConfigValue], pathElems: List[String]) extends ConfigCursor -/** A `ConfigCursor` pointing to a config list. - */ +/** + * A `ConfigCursor` pointing to a config list. + */ case class ConfigListCursor(listValue: ConfigList, pathElems: List[String], offset: Int = 0) extends ConfigCursor { @inline private[this] def validIndex(idx: Int) = idx >= 0 && idx < size @@ -361,20 +391,23 @@ case class ConfigListCursor(listValue: ConfigList, pathElems: List[String], offs override def asConfigValue: ConfigReader.Result[ConfigList] = Right(listValue) - /** Returns whether the config list pointed to by this cursor is empty. - */ + /** + * Returns whether the config list pointed to by this cursor is empty. + */ def isEmpty: Boolean = listValue.isEmpty - /** Returns the size of the config list pointed to by this cursor. - */ + /** + * Returns the size of the config list pointed to by this cursor. + */ def size: Int = listValue.size - /** Returns a cursor to the config at a given index. - * - * @param idx the index of the config for which a cursor should be returned - * @return a `Right` with a cursor to the config at `idx` if such a config exists, a `Left` with a list of failures - * otherwise. - */ + /** + * Returns a cursor to the config at a given index. + * + * @param idx the index of the config for which a cursor should be returned + * @return a `Right` with a cursor to the config at `idx` if such a config exists, a `Left` with a list of failures + * otherwise. + */ def atIndex(idx: Int): ConfigReader.Result[ConfigCursor] = { atIndexOrUndefined(idx) match { case idxCur if idxCur.isUndefined => failed(KeyNotFound.forKeys(indexKey(idx), Set())) @@ -382,18 +415,20 @@ case class ConfigListCursor(listValue: ConfigList, pathElems: List[String], offs } } - /** Returns a cursor to the config at a given index. An out of range index will return a cursor to an undefined value. - * - * @param idx the index of the config for which a cursor should be returned - * @return a cursor to the config at `idx` if such a config exists, a cursor to an undefined value otherwise. - */ + /** + * Returns a cursor to the config at a given index. An out of range index will return a cursor to an undefined value. + * + * @param idx the index of the config for which a cursor should be returned + * @return a cursor to the config at `idx` if such a config exists, a cursor to an undefined value otherwise. + */ def atIndexOrUndefined(idx: Int): ConfigCursor = ConfigCursor(if (validIndex(idx)) Some(listValue.get(idx)) else None, indexKey(idx) :: pathElems) - /** Returns a cursor to the tail of the config list pointed to by this cursor if non-empty. - * - * @return a `Some` with the tail of the config list if the list is not empty, `None` otherwise. - */ + /** + * Returns a cursor to the tail of the config list pointed to by this cursor if non-empty. + * + * @return a `Some` with the tail of the config list if the list is not empty, `None` otherwise. + */ def tailOption: Option[ConfigListCursor] = { if (listValue.isEmpty) None else { @@ -406,10 +441,11 @@ case class ConfigListCursor(listValue: ConfigList, pathElems: List[String], offs } } - /** Returns a list of cursors to the elements of the config list pointed to by this cursor. - * - * @return a list of cursors to the elements of the config list pointed to by this cursor. - */ + /** + * Returns a list of cursors to the elements of the config list pointed to by this cursor. + * + * @return a list of cursors to the elements of the config list pointed to by this cursor. + */ def list: List[ConfigCursor] = listValue.asScala.toList.drop(offset).zipWithIndex.map { case (cv, idx) => ConfigCursor(cv, indexKey(idx) :: pathElems) @@ -419,33 +455,38 @@ case class ConfigListCursor(listValue: ConfigList, pathElems: List[String], offs override def asListCursor: ConfigReader.Result[ConfigListCursor] = Right(this) } -/** A `ConfigCursor` pointing to a config object. - */ +/** + * A `ConfigCursor` pointing to a config object. + */ case class ConfigObjectCursor(objValue: ConfigObject, pathElems: List[String]) extends ConfigCursor { def valueOpt: Option[ConfigObject] = Some(objValue) override def asConfigValue: ConfigReader.Result[ConfigObject] = Right(objValue) - /** Returns whether the config object pointed to by this cursor is empty. - */ + /** + * Returns whether the config object pointed to by this cursor is empty. + */ def isEmpty: Boolean = objValue.isEmpty - /** Returns the size of the config object pointed to by this cursor. - */ + /** + * Returns the size of the config object pointed to by this cursor. + */ def size: Int = objValue.size - /** Returns the list of keys of the config object pointed to by this cursor. - */ + /** + * Returns the list of keys of the config object pointed to by this cursor. + */ def keys: Iterable[String] = objValue.keySet.asScala - /** Returns a cursor to the config at a given key. - * - * @param key the key of the config for which a cursor should be returned - * @return a `Right` with a cursor to the config at `key` if such a config exists, a `Left` with a list of failures - * otherwise. - */ + /** + * Returns a cursor to the config at a given key. + * + * @param key the key of the config for which a cursor should be returned + * @return a `Right` with a cursor to the config at `key` if such a config exists, a `Left` with a list of failures + * otherwise. + */ def atKey(key: String): ConfigReader.Result[ConfigCursor] = { atKeyOrUndefined(key) match { case keyCur if keyCur.isUndefined => failed(KeyNotFound.forKeys(key, keys)) @@ -453,24 +494,27 @@ case class ConfigObjectCursor(objValue: ConfigObject, pathElems: List[String]) e } } - /** Returns a cursor to the config at a given key. A missing key will return a cursor to an undefined value. - * - * @param key the key of the config for which a cursor should be returned - * @return a cursor to the config at `key` if such a config exists, a cursor to an undefined value otherwise. - */ + /** + * Returns a cursor to the config at a given key. A missing key will return a cursor to an undefined value. + * + * @param key the key of the config for which a cursor should be returned + * @return a cursor to the config at `key` if such a config exists, a cursor to an undefined value otherwise. + */ def atKeyOrUndefined(key: String): ConfigCursor = ConfigCursor(objValue.get(key), key :: pathElems) - /** Returns a cursor to the object pointed to by this cursor without a given key. - * - * @param key the key to remove on the config object - * @return a cursor to the object pointed to by this cursor without `key`. - */ + /** + * Returns a cursor to the object pointed to by this cursor without a given key. + * + * @param key the key to remove on the config object + * @return a cursor to the object pointed to by this cursor without `key`. + */ def withoutKey(key: String): ConfigObjectCursor = ConfigObjectCursor(objValue.withoutKey(key), pathElems) - /** Returns a map of cursors to the elements of the config object pointed to by this cursor. - */ + /** + * Returns a map of cursors to the elements of the config object pointed to by this cursor. + */ def map: Map[String, ConfigCursor] = objValue.asScala.toMap.map { case (key, cv) => key -> ConfigCursor(cv, key :: pathElems) } diff --git a/core/src/main/scala/pureconfig/ConfigFieldMapping.scala b/core/src/main/scala/pureconfig/ConfigFieldMapping.scala index e6a900e85..773b0d013 100644 --- a/core/src/main/scala/pureconfig/ConfigFieldMapping.scala +++ b/core/src/main/scala/pureconfig/ConfigFieldMapping.scala @@ -1,47 +1,51 @@ package pureconfig -/** A mapping between case class fields and their respective keys in the config. - */ +/** + * A mapping between case class fields and their respective keys in the config. + */ trait ConfigFieldMapping extends (String => String) { def apply(fieldName: String): String - /** Returns a `ConfigFieldMapping` that uses this mapping with some overrides. - * - * @param overrides the overrides for this mapping as pairs (field, configKey) - * @return a `ConfigFieldMapping` that maps fields using `overrides` if the field is present there and otherwise - * uses this mapping. - */ + /** + * Returns a `ConfigFieldMapping` that uses this mapping with some overrides. + * + * @param overrides the overrides for this mapping as pairs (field, configKey) + * @return a `ConfigFieldMapping` that maps fields using `overrides` if the field is present there and otherwise + * uses this mapping. + */ def withOverrides(overrides: (String, String)*) = ConfigFieldMapping(overrides.toMap.withDefault(apply)) } object ConfigFieldMapping { - /** Creates a ConfigFieldMapping from the provided function, mapping names in - * the object that will receive config values to names in the configuration - * file. - * - * @param f a function that maps names in the object that will receive config - * values to names in the configuration file - * @return a ConfigFieldMapping created from the provided function. - */ + /** + * Creates a ConfigFieldMapping from the provided function, mapping names in + * the object that will receive config values to names in the configuration + * file. + * + * @param f a function that maps names in the object that will receive config + * values to names in the configuration file + * @return a ConfigFieldMapping created from the provided function. + */ def apply(f: String => String): ConfigFieldMapping = new ConfigFieldMapping { def apply(fieldName: String): String = f(fieldName) } - /** Creates a ConfigFieldMapping according to the naming conventions specified - * both for the object that will receive config values and for the - * configuration file. - * - * @param typeFieldConvention naming convention used by the fields of the - * object which will receive config values - * @param configFieldConvention naming convention used in the configuration - * file - * @return a ConfigFieldMapping created according to the provided naming - * conventions. - */ + /** + * Creates a ConfigFieldMapping according to the naming conventions specified + * both for the object that will receive config values and for the + * configuration file. + * + * @param typeFieldConvention naming convention used by the fields of the + * object which will receive config values + * @param configFieldConvention naming convention used in the configuration + * file + * @return a ConfigFieldMapping created according to the provided naming + * conventions. + */ def apply(typeFieldConvention: NamingConvention, configFieldConvention: NamingConvention): ConfigFieldMapping = { if (typeFieldConvention == configFieldConvention) { apply(identity) diff --git a/core/src/main/scala/pureconfig/ConfigReader.scala b/core/src/main/scala/pureconfig/ConfigReader.scala index 36f9b9725..a3d4804a3 100644 --- a/core/src/main/scala/pureconfig/ConfigReader.scala +++ b/core/src/main/scala/pureconfig/ConfigReader.scala @@ -9,62 +9,69 @@ import com.typesafe.config.ConfigValue import pureconfig.ConvertHelpers._ import pureconfig.error.{ConfigReaderFailure, ConfigReaderFailures, FailureReason} -/** Trait for objects capable of reading objects of a given type from `ConfigValues`. - * - * @tparam A the type of objects readable by this `ConfigReader` - */ +/** + * Trait for objects capable of reading objects of a given type from `ConfigValues`. + * + * @tparam A the type of objects readable by this `ConfigReader` + */ trait ConfigReader[A] { import pureconfig.ConfigReader._ - /** Convert the configuration given by a cursor into an instance of `A` if possible. - * - * @param cur The cursor from which the config should be loaded - * @return either a list of failures or an object of type `A` - */ + /** + * Convert the configuration given by a cursor into an instance of `A` if possible. + * + * @param cur The cursor from which the config should be loaded + * @return either a list of failures or an object of type `A` + */ def from(cur: ConfigCursor): ConfigReader.Result[A] - /** Convert the given configuration into an instance of `A` if possible. - * - * @param config The configuration from which the config should be loaded - * @return either a list of failures or an object of type `A` - */ + /** + * Convert the given configuration into an instance of `A` if possible. + * + * @param config The configuration from which the config should be loaded + * @return either a list of failures or an object of type `A` + */ def from(config: ConfigValue): ConfigReader.Result[A] = from(ConfigCursor(config, Nil)) - /** Maps a function over the results of this reader. - * - * @param f the function to map over this reader - * @tparam B the output type of the function - * @return a `ConfigReader` returning the results of this reader mapped by `f`. - */ + /** + * Maps a function over the results of this reader. + * + * @param f the function to map over this reader + * @tparam B the output type of the function + * @return a `ConfigReader` returning the results of this reader mapped by `f`. + */ def map[B](f: A => B): ConfigReader[B] = fromCursor[B] { cur => from(cur).right.flatMap { v => cur.scopeFailure(toResult(f)(v)) } } - /** Maps a function that can possibly fail over the results of this reader. - * - * @param f the function to map over this reader - * @tparam B the value read by the function in case of success - * @return a `ConfigReader` returning the results of this reader mapped by `f`, with the resulting `Either` flattened - * as a success or failure. - */ + /** + * Maps a function that can possibly fail over the results of this reader. + * + * @param f the function to map over this reader + * @tparam B the value read by the function in case of success + * @return a `ConfigReader` returning the results of this reader mapped by `f`, with the resulting `Either` flattened + * as a success or failure. + */ def emap[B](f: A => Either[FailureReason, B]): ConfigReader[B] = fromCursor[B] { cur => from(cur).right.flatMap { v => cur.scopeFailure(f(v)) } } - /** Monadically bind a function over the results of this reader. - * - * @param f the function to bind over this reader - * @tparam B the type of the objects readable by the resulting `ConfigReader` - * @return a `ConfigReader` returning the results of this reader bound by `f`. - */ + /** + * Monadically bind a function over the results of this reader. + * + * @param f the function to bind over this reader + * @tparam B the type of the objects readable by the resulting `ConfigReader` + * @return a `ConfigReader` returning the results of this reader bound by `f`. + */ def flatMap[B](f: A => ConfigReader[B]): ConfigReader[B] = fromCursor[B] { cur => from(cur).right.flatMap(f(_).from(cur)) } - /** Combines this reader with another, returning both results as a pair. - * - * @param reader the reader to combine with this one - * @tparam B the type of the objects readable by the provided reader - * @return a `ConfigReader` returning the results of both readers as a pair. - */ + /** + * Combines this reader with another, returning both results as a pair. + * + * @param reader the reader to combine with this one + * @tparam B the type of the objects readable by the provided reader + * @return a `ConfigReader` returning the results of both readers as a pair. + */ def zip[B](reader: ConfigReader[B]): ConfigReader[(A, B)] = fromCursor[(A, B)] { cur => (from(cur), reader.from(cur)) match { @@ -75,13 +82,14 @@ trait ConfigReader[A] { } } - /** Combines this reader with another, returning the result of the first one that succeeds. - * - * @param reader the reader to combine with this one - * @tparam AA the type of the objects readable by both readers - * @return a `ConfigReader` returning the results of this reader if it succeeds and the results of `reader` - * otherwise. - */ + /** + * Combines this reader with another, returning the result of the first one that succeeds. + * + * @param reader the reader to combine with this one + * @tparam AA the type of the objects readable by both readers + * @return a `ConfigReader` returning the results of this reader if it succeeds and the results of `reader` + * otherwise. + */ def orElse[AA >: A, B <: AA](reader: => ConfigReader[B]): ConfigReader[AA] = fromCursor[AA] { cur => from(cur) match { @@ -90,39 +98,45 @@ trait ConfigReader[A] { } } - /** Applies a function to configs before passing them to this reader. - * - * @param f the function to apply to input configs - * @return a `ConfigReader` returning the results of this reader when the input configs are mapped using `f`. - */ + /** + * Applies a function to configs before passing them to this reader. + * + * @param f the function to apply to input configs + * @return a `ConfigReader` returning the results of this reader when the input configs are mapped using `f`. + */ def contramapConfig(f: ConfigValue => ConfigValue): ConfigReader[A] = fromCursor[A] { cur => from(ConfigCursor(cur.valueOpt.map(f), cur.pathElems)) } - /** Applies a function to config cursors before passing them to this reader. - * - * @param f the function to apply to input config cursors - * @return a `ConfigReader` returning the results of this reader when the input cursors are mapped using `f`. - */ + /** + * Applies a function to config cursors before passing them to this reader. + * + * @param f the function to apply to input config cursors + * @return a `ConfigReader` returning the results of this reader when the input cursors are mapped using `f`. + */ def contramapCursor(f: ConfigCursor => ConfigCursor): ConfigReader[A] = fromCursor[A] { cur => from(f(cur)) } } -/** Provides methods to create [[ConfigReader]] instances. - */ +/** + * Provides methods to create [[ConfigReader]] instances. + */ object ConfigReader extends BasicReaders with CollectionReaders with ProductReaders with ExportedReaders { - /** The type of most config PureConfig reading methods. - * - * @tparam A the type of the result - */ + /** + * The type of most config PureConfig reading methods. + * + * @tparam A the type of the result + */ type Result[A] = Either[ConfigReaderFailures, A] - /** Object containing useful constructors and utility methods for `Result`s. - */ + /** + * Object containing useful constructors and utility methods for `Result`s. + */ object Result { - /** Sequences a collection of `Result`s into a `Result` of a collection. - */ + /** + * Sequences a collection of `Result`s into a `Result` of a collection. + */ def sequence[A, CC[X] <: TraversableOnce[X]]( rs: CC[ConfigReader.Result[A]] )(implicit cbf: FactoryCompat[A, CC[A]]): ConfigReader.Result[CC[A]] = { @@ -135,8 +149,9 @@ object ConfigReader extends BasicReaders with CollectionReaders with ProductRead .map(_.result()) } - /** Merges two `Result`s using a given function. - */ + /** + * Merges two `Result`s using a given function. + */ def zipWith[A, B, C](first: ConfigReader.Result[A], second: ConfigReader.Result[B])( f: (A, B) => C ): ConfigReader.Result[C] = @@ -147,30 +162,33 @@ object ConfigReader extends BasicReaders with CollectionReaders with ProductRead case (l: Left[_, _], _) => l.asInstanceOf[Left[ConfigReaderFailures, Nothing]] } - /** Returns a `Result` containing a single failure. - */ + /** + * Returns a `Result` containing a single failure. + */ def fail[A](failure: ConfigReaderFailure): ConfigReader.Result[A] = Left(ConfigReaderFailures(failure)) } def apply[A](implicit reader: Derivation[ConfigReader[A]]): ConfigReader[A] = reader.value - /** Creates a `ConfigReader` from a function reading a `ConfigCursor`. - * - * @param fromF the function used to read config cursors to values - * @tparam A the type of the objects readable by the returned reader - * @return a `ConfigReader` for reading objects of type `A` using `fromF`. - */ + /** + * Creates a `ConfigReader` from a function reading a `ConfigCursor`. + * + * @param fromF the function used to read config cursors to values + * @tparam A the type of the objects readable by the returned reader + * @return a `ConfigReader` for reading objects of type `A` using `fromF`. + */ def fromCursor[A](fromF: ConfigCursor => ConfigReader.Result[A]) = new ConfigReader[A] { def from(cur: ConfigCursor) = fromF(cur) } - /** Creates a `ConfigReader` from a function. - * - * @param fromF the function used to read configs to values - * @tparam A the type of the objects readable by the returned reader - * @return a `ConfigReader` for reading objects of type `A` using `fromF`. - */ + /** + * Creates a `ConfigReader` from a function. + * + * @param fromF the function used to read configs to values + * @tparam A the type of the objects readable by the returned reader + * @return a `ConfigReader` for reading objects of type `A` using `fromF`. + */ def fromFunction[A](fromF: ConfigValue => ConfigReader.Result[A]) = fromCursor(_.asConfigValue.right.flatMap(fromF)) diff --git a/core/src/main/scala/pureconfig/ConfigSource.scala b/core/src/main/scala/pureconfig/ConfigSource.scala index f9a164e17..cd5fdb4f8 100644 --- a/core/src/main/scala/pureconfig/ConfigSource.scala +++ b/core/src/main/scala/pureconfig/ConfigSource.scala @@ -12,60 +12,67 @@ import pureconfig.backend.ConfigWrapper._ import pureconfig.backend.{ConfigFactoryWrapper, PathUtil} import pureconfig.error.{CannotRead, ConfigReaderException, ConfigReaderFailures} -/** A representation of a source from which `ConfigValue`s can be loaded, such as a file or a URL. - * - * A source allows users to load configs from this source as any type for which a `ConfigReader` is - * available. Raw configs can also be retrieved as a `ConfigValue`, a `ConfigCursor` or a - * `FluentConfigCursor`. Before using any of the loading methods described, Users can opt to focus - * on a specific part of a config by specifying a namespace. - * - * All config loading methods are lazy and defer resolution of references until needed. - */ +/** + * A representation of a source from which `ConfigValue`s can be loaded, such as a file or a URL. + * + * A source allows users to load configs from this source as any type for which a `ConfigReader` is + * available. Raw configs can also be retrieved as a `ConfigValue`, a `ConfigCursor` or a + * `FluentConfigCursor`. Before using any of the loading methods described, Users can opt to focus + * on a specific part of a config by specifying a namespace. + * + * All config loading methods are lazy and defer resolution of references until needed. + */ trait ConfigSource { - /** Retrieves a `ConfigValue` from this source. This forces the config to be resolved, if needed. - * - * @return a `ConfigValue` retrieved from this source. - */ + /** + * Retrieves a `ConfigValue` from this source. This forces the config to be resolved, if needed. + * + * @return a `ConfigValue` retrieved from this source. + */ def value(): Result[ConfigValue] - /** Returns a cursor for a `ConfigValue` retrieved from this source. - * - * @return a cursor for a `ConfigValue` retrieved from this source. - */ + /** + * Returns a cursor for a `ConfigValue` retrieved from this source. + * + * @return a cursor for a `ConfigValue` retrieved from this source. + */ def cursor(): Result[ConfigCursor] = value().right.map(ConfigCursor(_, Nil)) - /** Returns a fluent cursor for a `ConfigValue` retrieved from this source. - * - * @return a fluent cursor for a `ConfigValue` retrieved from this source. - */ + /** + * Returns a fluent cursor for a `ConfigValue` retrieved from this source. + * + * @return a fluent cursor for a `ConfigValue` retrieved from this source. + */ def fluentCursor(): FluentConfigCursor = FluentConfigCursor(cursor()) - /** Navigates through the config to focus on a namespace. - * - * @param namespace the namespace to focus on - * @return a new `ConfigSource` focused on the given namespace. - */ + /** + * Navigates through the config to focus on a namespace. + * + * @param namespace the namespace to focus on + * @return a new `ConfigSource` focused on the given namespace. + */ def at(namespace: String): ConfigSource = ConfigSource.fromCursor(fluentCursor().at(PathUtil.splitPath(namespace).map(p => p: PathSegment): _*)) - /** Loads a configuration of type `A` from this source. - * - * @tparam A the type of the config to be loaded - * @return A `Right` with the configuration if it is possible to create an instance of type - * `A` from this source, a `Failure` with details on why it isn't possible otherwise - */ + /** + * Loads a configuration of type `A` from this source. + * + * @tparam A the type of the config to be loaded + * @return A `Right` with the configuration if it is possible to create an instance of type + * `A` from this source, a `Failure` with details on why it isn't possible otherwise + */ final def load[A](implicit reader: Derivation[ConfigReader[A]]): Result[A] = cursor().right.flatMap(reader.value.from) - /** Loads a configuration of type `A` from this source. If it is not possible to create an - * instance of `A`, this method throws a `ConfigReaderException`. - * - * @tparam A the type of the config to be loaded - * @return The configuration of type `A` loaded from this source. - */ + /** + * Loads a configuration of type `A` from this source. If it is not possible to create an + * instance of `A`, this method throws a `ConfigReaderException`. + * + * @tparam A the type of the config to be loaded + * @return The configuration of type `A` loaded from this source. + */ @throws[ConfigReaderException[_]] final def loadOrThrow[A: ClassTag](implicit reader: Derivation[ConfigReader[A]]): A = { load[A] match { @@ -75,11 +82,12 @@ trait ConfigSource { } } -/** A `ConfigSource` which is guaranteed to generate config objects (maps) as root values. - * - * @param getConf the thunk to generate a `Config` instance. This parameter won't be memoized so it - * can be used with dynamic sources (e.g. URLs) - */ +/** + * A `ConfigSource` which is guaranteed to generate config objects (maps) as root values. + * + * @param getConf the thunk to generate a `Config` instance. This parameter won't be memoized so it + * can be used with dynamic sources (e.g. URLs) + */ final class ConfigObjectSource private (getConf: () => Result[Config]) extends ConfigSource { def value(): Result[ConfigObject] = @@ -89,42 +97,46 @@ final class ConfigObjectSource private (getConf: () => Result[Config]) extends C override def cursor(): Result[ConfigCursor] = value().right.map(ConfigObjectCursor(_, Nil)) - /** Reads a `Config` from this config source. The returned config is usually unresolved, unless - * the source forces it otherwise. - * - * @return a `Config` provided by this source. - */ + /** + * Reads a `Config` from this config source. The returned config is usually unresolved, unless + * the source forces it otherwise. + * + * @return a `Config` provided by this source. + */ def config(): Result[Config] = getConf() - /** Merges this source with another one, with the latter being used as a fallback (e.g. the - * source on which this method is called takes priority). Both sources are required to produce - * a config object successfully. - * - * @param cs the config source to use as fallback - * @return a new `ConfigObjectSource` that loads configs from both sources and uses `cs` as a - * fallback for this source - */ + /** + * Merges this source with another one, with the latter being used as a fallback (e.g. the + * source on which this method is called takes priority). Both sources are required to produce + * a config object successfully. + * + * @param cs the config source to use as fallback + * @return a new `ConfigObjectSource` that loads configs from both sources and uses `cs` as a + * fallback for this source + */ def withFallback(cs: ConfigObjectSource): ConfigObjectSource = ConfigObjectSource(Result.zipWith(config(), cs.config())(_.withFallback(_))) - /** Returns a `ConfigObjectSource` that provides the same config as this one, but falls back to - * providing an empty config when the source cannot be read. It can be used together with - * `.withFallback` to specify optional config files to be merged (like `reference.conf`). - * - * @return a new `ConfigObjectSource` that provides the same config as this one, but falls back - * to an empty config if it cannot be read. - */ + /** + * Returns a `ConfigObjectSource` that provides the same config as this one, but falls back to + * providing an empty config when the source cannot be read. It can be used together with + * `.withFallback` to specify optional config files to be merged (like `reference.conf`). + * + * @return a new `ConfigObjectSource` that provides the same config as this one, but falls back + * to an empty config if it cannot be read. + */ def optional: ConfigObjectSource = recoverWith { case ConfigReaderFailures(_: CannotRead) => ConfigSource.empty } - /** Applies a function `f` if this source returns a failure, returning an alternative config - * source in those cases. - * - * @param f the function to apply if this source returns a failure - * @return a new `ConfigObjectSource` that provides an alternative config in case this source - * fails - */ + /** + * Applies a function `f` if this source returns a failure, returning an alternative config + * source in those cases. + * + * @param f the function to apply if this source returns a failure + * @return a new `ConfigObjectSource` that provides an alternative config in case this source + * fails + */ def recoverWith(f: PartialFunction[ConfigReaderFailures, ConfigObjectSource]): ConfigObjectSource = ConfigObjectSource(getConf().left.flatMap { failures => f.lift(failures) match { @@ -136,169 +148,189 @@ final class ConfigObjectSource private (getConf: () => Result[Config]) extends C object ConfigObjectSource { - /** Creates a `ConfigObjectSource` from a `Result[Config]`. The provided argument is allowed - * to change value over time. - * - * @param conf the config to be provided by this source - * @return a `ConfigObjectSource` providing the given config. - */ + /** + * Creates a `ConfigObjectSource` from a `Result[Config]`. The provided argument is allowed + * to change value over time. + * + * @param conf the config to be provided by this source + * @return a `ConfigObjectSource` providing the given config. + */ def apply(conf: => Result[Config]): ConfigObjectSource = new ConfigObjectSource(() => conf) } -/** Object containing factory methods for building `ConfigSource`s. - * - * The sources provided here use Typesafe Config configs created from files, resources, URLs or - * strings. It also provides sources that delegate the loading component to Typesafe Config, to - * leverage reference configs and overrides, making it easy to switch from using `ConfigFactory` - * to `ConfigSource`. - * - * Other PureConfig modules may provide other ways or building config sources (e.g. for different - * config formats or data sources). - */ +/** + * Object containing factory methods for building `ConfigSource`s. + * + * The sources provided here use Typesafe Config configs created from files, resources, URLs or + * strings. It also provides sources that delegate the loading component to Typesafe Config, to + * leverage reference configs and overrides, making it easy to switch from using `ConfigFactory` + * to `ConfigSource`. + * + * Other PureConfig modules may provide other ways or building config sources (e.g. for different + * config formats or data sources). + */ object ConfigSource { - /** A config source for the default loading process in Typesafe Config. Typesafe Config stacks - * `reference.conf` resources provided by libraries, application configs (by default - * `application.conf` in resources) and system property overrides, resolves them and merges them - * into a single config. This source is equivalent to - * `defaultOverrides.withFallback(defaultApplication).withFallback(defaultReference)`. - */ + /** + * A config source for the default loading process in Typesafe Config. Typesafe Config stacks + * `reference.conf` resources provided by libraries, application configs (by default + * `application.conf` in resources) and system property overrides, resolves them and merges them + * into a single config. This source is equivalent to + * `defaultOverrides.withFallback(defaultApplication).withFallback(defaultReference)`. + */ val default = ConfigObjectSource(ConfigFactoryWrapper.load()) - /** A config source for the default loading process in Typesafe Config with a custom application - * config source. Typesafe Config stacks `reference.conf` resources provided by libraries, the - * given file and system property overrides, resolves them and merges them into a single config. - * - * This method is provided here to support use cases that previously depended on - * `ConfigFactory.load(config)`. Creating a custom source by merging the layers manually is - * usually recommended as it makes the config priorities more transparent. - * - * @param appSource the source providing the application config - * @return a `ConfigObjectSource` for the default loading process in Typesafe Config with a - * custom application config source. - */ + /** + * A config source for the default loading process in Typesafe Config with a custom application + * config source. Typesafe Config stacks `reference.conf` resources provided by libraries, the + * given file and system property overrides, resolves them and merges them into a single config. + * + * This method is provided here to support use cases that previously depended on + * `ConfigFactory.load(config)`. Creating a custom source by merging the layers manually is + * usually recommended as it makes the config priorities more transparent. + * + * @param appSource the source providing the application config + * @return a `ConfigObjectSource` for the default loading process in Typesafe Config with a + * custom application config source. + */ def default(appSource: ConfigObjectSource): ConfigObjectSource = ConfigObjectSource(appSource.config().right.flatMap(ConfigFactoryWrapper.load)) - /** A config source that always provides empty configs. - */ + /** + * A config source that always provides empty configs. + */ val empty = ConfigObjectSource(Right(ConfigFactory.empty)) - /** A config source for the default reference config in Typesafe Config (`reference.conf` - * resources provided by libraries). Like Typesafe Config, it provides an empty object if - * `reference.conf` files are not found. - * - * As required by - * [[https://github.com/lightbend/config/blob/master/HOCON.md#conventional-configuration-files-for-jvm-apps the HOCON spec]], - * the default reference files are pre-emptively resolved - substitutions in the reference config - * aren't affected by application configs. - */ + /** + * A config source for the default reference config in Typesafe Config (`reference.conf` + * resources provided by libraries). Like Typesafe Config, it provides an empty object if + * `reference.conf` files are not found. + * + * As required by + * [[https://github.com/lightbend/config/blob/master/HOCON.md#conventional-configuration-files-for-jvm-apps the HOCON spec]], + * the default reference files are pre-emptively resolved - substitutions in the reference config + * aren't affected by application configs. + */ val defaultReference = ConfigObjectSource(ConfigFactoryWrapper.defaultReference()) - /** A config source for the default reference config in Typesafe Config (`reference.conf` - * resources provided by libraries) before being resolved. This can be used as an alternative - * to `defaultReference` for use cases that require `reference.conf` to depend on - * `application.conf`. Like Typesafe Config, it provides an empty object if `reference.conf` - * files are not found. - */ + /** + * A config source for the default reference config in Typesafe Config (`reference.conf` + * resources provided by libraries) before being resolved. This can be used as an alternative + * to `defaultReference` for use cases that require `reference.conf` to depend on + * `application.conf`. Like Typesafe Config, it provides an empty object if `reference.conf` + * files are not found. + */ val defaultReferenceUnresolved = resources("reference.conf").optional - /** A config source for the default application config in Typesafe Config (by default - * `application.conf` in resources). Like Typesafe Config, it provides an empty object if - * application config files are not found. - */ + /** + * A config source for the default application config in Typesafe Config (by default + * `application.conf` in resources). Like Typesafe Config, it provides an empty object if + * application config files are not found. + */ val defaultApplication = ConfigObjectSource(ConfigFactoryWrapper.defaultApplication()) - /** A config source for the default overrides in Typesafe Config (by default a map of system - * properties). - */ + /** + * A config source for the default overrides in Typesafe Config (by default a map of system + * properties). + */ val defaultOverrides = ConfigObjectSource(ConfigFactoryWrapper.defaultOverrides()) - /** A config source for Java system properties. - */ + /** + * A config source for Java system properties. + */ val systemProperties = ConfigObjectSource(ConfigFactoryWrapper.systemProperties()) - /** Returns a config source that provides configs read from a file. - * - * @param path the path to the file as a string - * @return a config source that provides configs read from a file. - */ + /** + * Returns a config source that provides configs read from a file. + * + * @param path the path to the file as a string + * @return a config source that provides configs read from a file. + */ def file(path: String) = ConfigObjectSource(ConfigFactoryWrapper.parseFile(new File(path))) - /** Returns a config source that provides configs read from a file. - * - * @param path the path to the file - * @return a config source that provides configs read from a file. - */ + /** + * Returns a config source that provides configs read from a file. + * + * @param path the path to the file + * @return a config source that provides configs read from a file. + */ def file(path: Path) = ConfigObjectSource(ConfigFactoryWrapper.parseFile(path.toFile)) - /** Returns a config source that provides configs read from a file. - * - * @param file the file - * @return a config source that provides configs read from a file. - */ + /** + * Returns a config source that provides configs read from a file. + * + * @param file the file + * @return a config source that provides configs read from a file. + */ def file(file: File) = ConfigObjectSource(ConfigFactoryWrapper.parseFile(file)) - /** Returns a config source that provides configs read from a URL. The URL can either point to a - * local file or to a remote HTTP location. - * - * @param url the URL - * @return a config source that provides configs read from a URL. - */ + /** + * Returns a config source that provides configs read from a URL. The URL can either point to a + * local file or to a remote HTTP location. + * + * @param url the URL + * @return a config source that provides configs read from a URL. + */ def url(url: URL) = ConfigObjectSource(ConfigFactoryWrapper.parseURL(url)) - /** Returns a config source that provides configs read from JVM resource files. If multiple files - * are found, they are merged in no specific order. This method uses Typesafe Config's default - * class loader (`Thread.currentThread().getContextClassLoader()`). - * - * @param name the resource name - * @return a config source that provides configs read from JVM resource files. - */ + /** + * Returns a config source that provides configs read from JVM resource files. If multiple files + * are found, they are merged in no specific order. This method uses Typesafe Config's default + * class loader (`Thread.currentThread().getContextClassLoader()`). + * + * @param name the resource name + * @return a config source that provides configs read from JVM resource files. + */ def resources(name: String) = ConfigObjectSource(ConfigFactoryWrapper.parseResources(name, null)) - /** Returns a config source that provides configs read from JVM resource files. If multiple files - * are found, they are merged in no specific order. The given class loader will be used to look - * for resources. - * - * @param name the resource name - * @param classLoader the class loader to use to look for resources - * @return a config source that provides configs read from JVM resource files. - */ + /** + * Returns a config source that provides configs read from JVM resource files. If multiple files + * are found, they are merged in no specific order. The given class loader will be used to look + * for resources. + * + * @param name the resource name + * @param classLoader the class loader to use to look for resources + * @return a config source that provides configs read from JVM resource files. + */ def resources(name: String, classLoader: ClassLoader) = ConfigObjectSource(ConfigFactoryWrapper.parseResources(name, classLoader)) - /** Returns a config source that provides a config parsed from a string. - * - * @param confStr the config content - * @return a config source that provides a config parsed from a string. - */ + /** + * Returns a config source that provides a config parsed from a string. + * + * @param confStr the config content + * @return a config source that provides a config parsed from a string. + */ def string(confStr: String) = ConfigObjectSource(ConfigFactoryWrapper.parseString(confStr)) - /** Returns a config source that provides a fixed `Config`. - * - * @param conf the config to be provided - * @return a config source that provides the given config. - */ + /** + * Returns a config source that provides a fixed `Config`. + * + * @param conf the config to be provided + * @return a config source that provides the given config. + */ def fromConfig(conf: Config) = ConfigObjectSource(Right(conf)) - /** Creates a `ConfigSource` from a `ConfigCursor`. - * - * @param cur the cursor to be provided by this source - * @return a `ConfigSource` providing the given cursor. - */ + /** + * Creates a `ConfigSource` from a `ConfigCursor`. + * + * @param cur the cursor to be provided by this source + * @return a `ConfigSource` providing the given cursor. + */ private[pureconfig] def fromCursor(cur: ConfigCursor): ConfigSource = new ConfigSource { def value(): Result[ConfigValue] = cur.asConfigValue override def cursor() = Right(cur) } - /** Creates a `ConfigSource` from a `FluentConfigCursor`. - * - * @param cur the cursor to be provided by this source - * @return a `ConfigSource` providing the given cursor. - */ + /** + * Creates a `ConfigSource` from a `FluentConfigCursor`. + * + * @param cur the cursor to be provided by this source + * @return a `ConfigSource` providing the given cursor. + */ private[pureconfig] def fromCursor(cur: FluentConfigCursor): ConfigSource = new ConfigSource { def value(): Result[ConfigValue] = cur.cursor.right.flatMap(_.asConfigValue) diff --git a/core/src/main/scala/pureconfig/ConfigWriter.scala b/core/src/main/scala/pureconfig/ConfigWriter.scala index 6b5744f1a..83d7d6ed0 100644 --- a/core/src/main/scala/pureconfig/ConfigWriter.scala +++ b/core/src/main/scala/pureconfig/ConfigWriter.scala @@ -2,82 +2,91 @@ package pureconfig import com.typesafe.config.{ConfigValue, ConfigValueFactory} -/** Trait for objects capable of writing objects of a given type to `ConfigValues`. - * - * @tparam A the type of objects writable by this `ConfigWriter` - */ +/** + * Trait for objects capable of writing objects of a given type to `ConfigValues`. + * + * @tparam A the type of objects writable by this `ConfigWriter` + */ trait ConfigWriter[A] { import pureconfig.ConfigWriter._ - /** Converts a type `A` to a `ConfigValue`. - * - * @param a The instance of `A` to convert - * @return The `ConfigValue` obtained from the `A` instance - */ + /** + * Converts a type `A` to a `ConfigValue`. + * + * @param a The instance of `A` to convert + * @return The `ConfigValue` obtained from the `A` instance + */ def to(a: A): ConfigValue - /** Applies a function to values before passing them to this writer. - * - * @param f the function to apply to input values - * @tparam B the input type of the function - * @return a `ConfigWriter` that writes the results of this writer when the input values are mapped using `f`. - */ + /** + * Applies a function to values before passing them to this writer. + * + * @param f the function to apply to input values + * @tparam B the input type of the function + * @return a `ConfigWriter` that writes the results of this writer when the input values are mapped using `f`. + */ def contramap[B](f: B => A): ConfigWriter[B] = fromFunction[B] { a => to(f(a)) } - /** Maps a function over the results of this writer. - * - * @param f the function to map over this writer - * @return a `ConfigWriter` returning the results of this writer mapped by `f`. - */ + /** + * Maps a function over the results of this writer. + * + * @param f the function to map over this writer + * @return a `ConfigWriter` returning the results of this writer mapped by `f`. + */ def mapConfig(f: ConfigValue => ConfigValue): ConfigWriter[A] = fromFunction[A] { a => f(to(a)) } } -/** Provides methods to create [[ConfigWriter]] instances. - */ +/** + * Provides methods to create [[ConfigWriter]] instances. + */ object ConfigWriter extends BasicWriters with CollectionWriters with ProductWriters with ExportedWriters { def apply[A](implicit writer: Derivation[ConfigWriter[A]]): ConfigWriter[A] = writer.value - /** Creates a `ConfigWriter` from a function. - * - * @param toF the function used to write values to configs - * @tparam A the type of the objects writable by the returned writer - * @return a `ConfigWriter` for writing objects of type `A` using `toF`. - */ + /** + * Creates a `ConfigWriter` from a function. + * + * @param toF the function used to write values to configs + * @tparam A the type of the objects writable by the returned writer + * @return a `ConfigWriter` for writing objects of type `A` using `toF`. + */ def fromFunction[A](toF: A => ConfigValue) = new ConfigWriter[A] { def to(a: A) = toF(a) } - /** Returns a `ConfigWriter` for types supported by `ConfigValueFactory.fromAnyRef`. This method should be used - * carefully, as a runtime exception is thrown if the type passed as argument is not supported. - * - * @tparam A the primitive type for which a `ConfigWriter` is to be created - * @return a `ConfigWriter` for the type `A`. - */ + /** + * Returns a `ConfigWriter` for types supported by `ConfigValueFactory.fromAnyRef`. This method should be used + * carefully, as a runtime exception is thrown if the type passed as argument is not supported. + * + * @tparam A the primitive type for which a `ConfigWriter` is to be created + * @return a `ConfigWriter` for the type `A`. + */ def forPrimitive[A]: ConfigWriter[A] = new ConfigWriter[A] { def to(t: A) = ConfigValueFactory.fromAnyRef(t) } - /** Returns a `ConfigWriter` that writes objects of a given type as strings created by `.toString`. - * - * @tparam A the type for which a `ConfigWriter` is to be created - * @return a `ConfigWriter` for the type `A`. - */ + /** + * Returns a `ConfigWriter` that writes objects of a given type as strings created by `.toString`. + * + * @tparam A the type for which a `ConfigWriter` is to be created + * @return a `ConfigWriter` for the type `A`. + */ def toDefaultString[A]: ConfigWriter[A] = new ConfigWriter[A] { def to(t: A) = ConfigValueFactory.fromAnyRef(t.toString) } - /** Returns a `ConfigWriter` that writes objects of a given type as strings created by a function. - * - * @param toF the function converting an object of type `A` to a string - * @tparam A the type for which a `ConfigWriter` is to be created - * @return a `ConfigWriter` for the type `A`. - */ + /** + * Returns a `ConfigWriter` that writes objects of a given type as strings created by a function. + * + * @param toF the function converting an object of type `A` to a string + * @tparam A the type for which a `ConfigWriter` is to be created + * @return a `ConfigWriter` for the type `A`. + */ def toString[A](toF: A => String): ConfigWriter[A] = new ConfigWriter[A] { def to(t: A) = ConfigValueFactory.fromAnyRef(toF(t)) diff --git a/core/src/main/scala/pureconfig/ConvertHelpers.scala b/core/src/main/scala/pureconfig/ConvertHelpers.scala index bf6db6e70..97331c635 100644 --- a/core/src/main/scala/pureconfig/ConvertHelpers.scala +++ b/core/src/main/scala/pureconfig/ConvertHelpers.scala @@ -6,8 +6,9 @@ import scala.util.{Failure, Success, Try} import pureconfig.error._ -/** Useful helpers for building `ConfigConvert` instances and dealing with results. - */ +/** + * Useful helpers for building `ConfigConvert` instances and dealing with results. + */ trait ConvertHelpers { @deprecated("Use `ConfigReader.Result.zipWith` instead", "0.10.2") @@ -40,10 +41,11 @@ trait ConvertHelpers { } } - /** Convert a `String => Try` into a `String => Option[ConfigValueLocation] => Either` such that after application - * - `Success(t)` becomes `_ => Right(t)` - * - `Failure(e)` becomes `location => Left(CannotConvert(value, type, e.getMessage, location)` - */ + /** + * Convert a `String => Try` into a `String => Option[ConfigValueLocation] => Either` such that after application + * - `Success(t)` becomes `_ => Right(t)` + * - `Failure(e)` becomes `location => Left(CannotConvert(value, type, e.getMessage, location)` + */ def tryF[A](f: String => Try[A])(implicit ct: ClassTag[A]): String => Either[FailureReason, A] = { string => f(string) match { case Success(t) => Right(t) @@ -51,10 +53,11 @@ trait ConvertHelpers { } } - /** Convert a `String => Option` into a `String => Option[ConfigValueLocation] => Either` such that after application - * - `Some(t)` becomes `_ => Right(t)` - * - `None` becomes `location => Left(CannotConvert(value, type, "", location)` - */ + /** + * Convert a `String => Option` into a `String => Option[ConfigValueLocation] => Either` such that after application + * - `Some(t)` becomes `_ => Right(t)` + * - `None` becomes `location => Left(CannotConvert(value, type, "", location)` + */ def optF[A](f: String => Option[A])(implicit ct: ClassTag[A]): String => Either[FailureReason, A] = { string => f(string) match { case Some(t) => Right(t) diff --git a/core/src/main/scala/pureconfig/DurationUtils.scala b/core/src/main/scala/pureconfig/DurationUtils.scala index 24f81db4b..c01b2046b 100644 --- a/core/src/main/scala/pureconfig/DurationUtils.scala +++ b/core/src/main/scala/pureconfig/DurationUtils.scala @@ -21,13 +21,15 @@ import scala.util.control.NonFatal import pureconfig.error.{CannotConvert, ExceptionThrown, FailureReason} -/** Utility functions for converting a `String` to a `Duration` and vice versa. The parser accepts the HOCON unit - * syntax. - */ +/** + * Utility functions for converting a `String` to a `Duration` and vice versa. The parser accepts the HOCON unit + * syntax. + */ private[pureconfig] object DurationUtils { - /** Convert a string to a Duration while trying to maintain compatibility with Typesafe's abbreviations. - */ + /** + * Convert a string to a Duration while trying to maintain compatibility with Typesafe's abbreviations. + */ val fromString: String => Either[FailureReason, Duration] = { string => if (string == UndefinedDuration) Right(Duration.Undefined) else @@ -105,9 +107,10 @@ private[pureconfig] object DurationUtils { private val justAMinute = shortMinuteRegex.replaceSomeIn(_: String, m => Some(s"${m.group(1)}${m.group(2)}minutes${m.group(3)}")) - /** Format a possibily infinite duration as a string with a suitable time unit using units TypesafeConfig understands. - * Caveat: TypesafeConfig doesn't undersand infinite durations - */ + /** + * Format a possibily infinite duration as a string with a suitable time unit using units TypesafeConfig understands. + * Caveat: TypesafeConfig doesn't undersand infinite durations + */ def fromDuration(d: Duration): String = { d match { case f: FiniteDuration => fromFiniteDuration(f) @@ -121,8 +124,9 @@ private[pureconfig] object DurationUtils { /// which is inconsistent with the `Inf` and `Minus` `toString` provided by other special `Duration`s. private final val UndefinedDuration = "Undefined" - /** Format a FiniteDuration as a string with a suitable time unit using units TypesafeConfig understands. - */ + /** + * Format a FiniteDuration as a string with a suitable time unit using units TypesafeConfig understands. + */ def fromFiniteDuration(d: FiniteDuration): String = { d.toNanos match { case 0L => "0" diff --git a/core/src/main/scala/pureconfig/Exported.scala b/core/src/main/scala/pureconfig/Exported.scala index 3ad9c2d46..2ffdf080f 100644 --- a/core/src/main/scala/pureconfig/Exported.scala +++ b/core/src/main/scala/pureconfig/Exported.scala @@ -1,11 +1,12 @@ package pureconfig -/** A wrapper for type class instances intended to allow implicits in scope by `import` statements to have lower - * priority than implicits in the relevant companion objects. This behavior requires type classes to provide a bridge - * in their companion objects, as done by `ConfigReader` (see [[pureconfig.ExportedReaders]]) and `ConfigWriter` (see - * [[pureconfig.ExportedWriters]]). - * - * @param instance the type class instance to wrap - * @tparam A the type class - */ +/** + * A wrapper for type class instances intended to allow implicits in scope by `import` statements to have lower + * priority than implicits in the relevant companion objects. This behavior requires type classes to provide a bridge + * in their companion objects, as done by `ConfigReader` (see [[pureconfig.ExportedReaders]]) and `ConfigWriter` (see + * [[pureconfig.ExportedWriters]]). + * + * @param instance the type class instance to wrap + * @tparam A the type class + */ case class Exported[A](instance: A) extends AnyVal diff --git a/core/src/main/scala/pureconfig/ExportedReaders.scala b/core/src/main/scala/pureconfig/ExportedReaders.scala index b7514ccb1..c4d151782 100644 --- a/core/src/main/scala/pureconfig/ExportedReaders.scala +++ b/core/src/main/scala/pureconfig/ExportedReaders.scala @@ -1,10 +1,11 @@ package pureconfig -/** Trait allowing `ConfigReader` instances exported via `Exported` to be used. - * - * This trait should be the last to be mixed into `ConfigReader`'s companion object so that exported readers will - * always have lower precedence than `ConfigReader` instances exposed as implicits through the usual means. - */ +/** + * Trait allowing `ConfigReader` instances exported via `Exported` to be used. + * + * This trait should be the last to be mixed into `ConfigReader`'s companion object so that exported readers will + * always have lower precedence than `ConfigReader` instances exposed as implicits through the usual means. + */ trait ExportedReaders { implicit def exportedReader[A](implicit exported: Exported[ConfigReader[A]]): ConfigReader[A] = exported.instance } diff --git a/core/src/main/scala/pureconfig/ExportedWriters.scala b/core/src/main/scala/pureconfig/ExportedWriters.scala index 09a0f4e35..0d6645260 100644 --- a/core/src/main/scala/pureconfig/ExportedWriters.scala +++ b/core/src/main/scala/pureconfig/ExportedWriters.scala @@ -1,10 +1,11 @@ package pureconfig -/** Trait allowing `ConfigWriter` instances exported via `Exported` to be used. - * - * This trait should be the last to be mixed into `ConfigWriter`'s companion object so that exported writers will - * always have lower precedence than `ConfigWriter` instances exposed as implicits through the usual means. - */ +/** + * Trait allowing `ConfigWriter` instances exported via `Exported` to be used. + * + * This trait should be the last to be mixed into `ConfigWriter`'s companion object so that exported writers will + * always have lower precedence than `ConfigWriter` instances exposed as implicits through the usual means. + */ trait ExportedWriters { implicit def exportedWriter[A](implicit exported: Exported[ConfigWriter[A]]): ConfigWriter[A] = exported.instance } diff --git a/core/src/main/scala/pureconfig/FluentConfigCursor.scala b/core/src/main/scala/pureconfig/FluentConfigCursor.scala index 3446159aa..b3501e45d 100644 --- a/core/src/main/scala/pureconfig/FluentConfigCursor.scala +++ b/core/src/main/scala/pureconfig/FluentConfigCursor.scala @@ -1,84 +1,95 @@ package pureconfig -/** A version of `ConfigCursor` with a more fluent interface, focused on config navigation instead of error handling. - * - * The `at` method, used to access object and list values, is available without a previous need to cast the cursor and - * always returns another cursor instead of a `ConfigReader.Result`. The error handling is left for the last step, where users - * can opt to cast to a primitive value using one of the `as` methods or by requesting a regular cursor with `cursor`. - * - * @param cursor the regular cursor pointed to by this object, wrapped itself into a `Right`, or a `Left` with a list of - * failures in case an error occurred during navigation - */ +/** + * A version of `ConfigCursor` with a more fluent interface, focused on config navigation instead of error handling. + * + * The `at` method, used to access object and list values, is available without a previous need to cast the cursor and + * always returns another cursor instead of a `ConfigReader.Result`. The error handling is left for the last step, where users + * can opt to cast to a primitive value using one of the `as` methods or by requesting a regular cursor with `cursor`. + * + * @param cursor the regular cursor pointed to by this object, wrapped itself into a `Right`, or a `Left` with a list of + * failures in case an error occurred during navigation + */ case class FluentConfigCursor(cursor: ConfigReader.Result[ConfigCursor]) { - /** Casts this cursor to a string. - * - * @return a `Right` with the string value pointed to by this cursor if the cast can be done, `Left` with a list of - * failures otherwise. - */ + /** + * Casts this cursor to a string. + * + * @return a `Right` with the string value pointed to by this cursor if the cast can be done, `Left` with a list of + * failures otherwise. + */ def asString: ConfigReader.Result[String] = cursor.right.flatMap(_.asString) - /** Casts this cursor to a boolean. - * - * @return a `Right` with the boolean value pointed to by this cursor if the cast can be done, `Left` with a list of - * failures otherwise. - */ + /** + * Casts this cursor to a boolean. + * + * @return a `Right` with the boolean value pointed to by this cursor if the cast can be done, `Left` with a list of + * failures otherwise. + */ def asBoolean: ConfigReader.Result[Boolean] = cursor.right.flatMap(_.asBoolean) - /** Casts this cursor to a long. - * - * @return a `Right` with the long value pointed to by this cursor if the cast can be done, `Left` with a list of - * failures otherwise. - */ + /** + * Casts this cursor to a long. + * + * @return a `Right` with the long value pointed to by this cursor if the cast can be done, `Left` with a list of + * failures otherwise. + */ def asLong: ConfigReader.Result[Long] = cursor.right.flatMap(_.asLong) - /** Casts this cursor to an int. - * - * @return a `Right` with the int value pointed to by this cursor if the cast can be done, `Left` with a list of - * failures otherwise. - */ + /** + * Casts this cursor to an int. + * + * @return a `Right` with the int value pointed to by this cursor if the cast can be done, `Left` with a list of + * failures otherwise. + */ def asInt: ConfigReader.Result[Int] = cursor.right.flatMap(_.asInt) - /** Casts this cursor to a short. - * - * @return a `Right` with the short value pointed to by this cursor if the cast can be done, `Left` with a list of - * failures otherwise. - */ + /** + * Casts this cursor to a short. + * + * @return a `Right` with the short value pointed to by this cursor if the cast can be done, `Left` with a list of + * failures otherwise. + */ def asShort: ConfigReader.Result[Short] = cursor.right.flatMap(_.asShort) - /** Casts this cursor to a double. - * - * @return a `Right` with the double value pointed to by this cursor if the cast can be done, `Left` with a list of - * failures otherwise. - */ + /** + * Casts this cursor to a double. + * + * @return a `Right` with the double value pointed to by this cursor if the cast can be done, `Left` with a list of + * failures otherwise. + */ def asDouble: ConfigReader.Result[Double] = cursor.right.flatMap(_.asDouble) - /** Casts this cursor to a float. - * - * @return a `Right` with the float value pointed to by this cursor if the cast can be done, `Left` with a list of - * failures otherwise. - */ + /** + * Casts this cursor to a float. + * + * @return a `Right` with the float value pointed to by this cursor if the cast can be done, `Left` with a list of + * failures otherwise. + */ def asFloat: ConfigReader.Result[Float] = cursor.right.flatMap(_.asFloat) - /** Casts this cursor to a `ConfigListCursor`. - * - * @return a `Right` with this cursor as a list cursor if the cast can be done, `Left` with a list of failures - * otherwise. - */ + /** + * Casts this cursor to a `ConfigListCursor`. + * + * @return a `Right` with this cursor as a list cursor if the cast can be done, `Left` with a list of failures + * otherwise. + */ def asListCursor: ConfigReader.Result[ConfigListCursor] = cursor.right.flatMap(_.asListCursor) - /** Casts this cursor to a `ConfigObjectCursor`. - * - * @return a `Right` with this cursor as an object cursor if it points to an object, `Left` with a list of failures - * otherwise. - */ + /** + * Casts this cursor to a `ConfigObjectCursor`. + * + * @return a `Right` with this cursor as an object cursor if it points to an object, `Left` with a list of failures + * otherwise. + */ def asObjectCursor: ConfigReader.Result[ConfigObjectCursor] = cursor.right.flatMap(_.asObjectCursor) - /** Returns a cursor to the config at a given path. - * - * @param segments the path of the config for which a cursor should be returned - * @return a `FluentConfigCursor` pointing to the provided path. - */ + /** + * Returns a cursor to the config at a given path. + * + * @param segments the path of the config for which a cursor should be returned + * @return a `FluentConfigCursor` pointing to the provided path. + */ def at(segments: PathSegment*): FluentConfigCursor = FluentConfigCursor { segments.foldLeft(this.cursor) { @@ -88,25 +99,27 @@ case class FluentConfigCursor(cursor: ConfigReader.Result[ConfigCursor]) { } } - /** Casts this cursor to a `ConfigListCursor` and maps each element to a result. This method tries to map all - * elements, combining failures from all of them if more than one exists. - * - * @param f the function used to map elements - * @tparam A the result type of the elements - * @return a `Right` with the list obtained by mapping all elements of the list pointed to by this cursor if all - * casts and mappings can be done, `Left` with a list of failures otherwise. - */ + /** + * Casts this cursor to a `ConfigListCursor` and maps each element to a result. This method tries to map all + * elements, combining failures from all of them if more than one exists. + * + * @param f the function used to map elements + * @tparam A the result type of the elements + * @return a `Right` with the list obtained by mapping all elements of the list pointed to by this cursor if all + * casts and mappings can be done, `Left` with a list of failures otherwise. + */ def mapList[A](f: ConfigCursor => ConfigReader.Result[A]): ConfigReader.Result[List[A]] = asListCursor.right.flatMap { listCur => ConfigReader.Result.sequence(listCur.list.map(f)) } - /** Casts this cursor to a `ConfigObjectCursor` and maps each value to a result. This method tries to map all - * elements, combining failures from all of them if more than one exists. - * - * @param f the function used to map values - * @tparam A the result type of the values - * @return a `Right` with the map obtained by mapping all values of the object pointed to by this cursor if all - * casts and mappings can be done, `Left` with a list of failures otherwise. - */ + /** + * Casts this cursor to a `ConfigObjectCursor` and maps each value to a result. This method tries to map all + * elements, combining failures from all of them if more than one exists. + * + * @param f the function used to map values + * @tparam A the result type of the values + * @return a `Right` with the map obtained by mapping all values of the object pointed to by this cursor if all + * casts and mappings can be done, `Left` with a list of failures otherwise. + */ def mapObject[A](f: ConfigCursor => ConfigReader.Result[A]): ConfigReader.Result[Map[String, A]] = asObjectCursor.right.flatMap { objCur => val kvResults = objCur.map.map { case (key, cur) => f(cur).right.map((key, _)) } diff --git a/core/src/main/scala/pureconfig/NamingConvention.scala b/core/src/main/scala/pureconfig/NamingConvention.scala index a08b38c1b..7f19acb21 100644 --- a/core/src/main/scala/pureconfig/NamingConvention.scala +++ b/core/src/main/scala/pureconfig/NamingConvention.scala @@ -16,9 +16,10 @@ object CapitalizedWordsNamingConvention { String.format("%s|%s|%s", "(?<=[A-Z])(?=[A-Z][a-z])", "(?<=[^A-Z])(?=[A-Z])", "(?<=[A-Za-z])(?=[^A-Za-z])").r } -/** CamelCase identifiers look like `camelCase` and `useMorePureconfig` - * @see https://en.wikipedia.org/wiki/Camel_case - */ +/** + * CamelCase identifiers look like `camelCase` and `useMorePureconfig` + * @see https://en.wikipedia.org/wiki/Camel_case + */ object CamelCase extends CapitalizedWordsNamingConvention { def fromTokens(l: Seq[String]): String = { l match { @@ -29,9 +30,10 @@ object CamelCase extends CapitalizedWordsNamingConvention { } } -/** PascalCase identifiers look like e.g.`PascalCase` and `UseMorePureconfig` - * @see https://en.wikipedia.org/wiki/PascalCase - */ +/** + * PascalCase identifiers look like e.g.`PascalCase` and `UseMorePureconfig` + * @see https://en.wikipedia.org/wiki/PascalCase + */ object PascalCase extends CapitalizedWordsNamingConvention { def fromTokens(l: Seq[String]): String = l.map(_.capitalize).mkString } @@ -44,19 +46,22 @@ class StringDelimitedNamingConvention(d: String) extends NamingConvention { l.map(_.toLowerCase).mkString(d) } -/** KebabCase identifiers look like `kebab-case` and `use-more-pureconfig` - * @see http://wiki.c2.com/?KebabCase - */ +/** + * KebabCase identifiers look like `kebab-case` and `use-more-pureconfig` + * @see http://wiki.c2.com/?KebabCase + */ object KebabCase extends StringDelimitedNamingConvention("-") -/** SnakeCase identifiers look like `snake_case` and `use_more_pureconfig` - * @see https://en.wikipedia.org/wiki/Snake_case - */ +/** + * SnakeCase identifiers look like `snake_case` and `use_more_pureconfig` + * @see https://en.wikipedia.org/wiki/Snake_case + */ object SnakeCase extends StringDelimitedNamingConvention("_") -/** SnakeCase identifiers look like `SCREAMING_SNAKE_CASE` and `USE_MORE_PURECONFIG` - * @see https://en.wikipedia.org/wiki/Snake_case (and search for SCREAMING_SNAKE_CASE) - */ +/** + * SnakeCase identifiers look like `SCREAMING_SNAKE_CASE` and `USE_MORE_PURECONFIG` + * @see https://en.wikipedia.org/wiki/Snake_case (and search for SCREAMING_SNAKE_CASE) + */ object ScreamingSnakeCase extends NamingConvention { def toTokens(s: String): Seq[String] = SnakeCase.toTokens(s) def fromTokens(l: Seq[String]): String = l.map(_.toUpperCase).mkString("_") diff --git a/core/src/main/scala/pureconfig/PeriodUtils.scala b/core/src/main/scala/pureconfig/PeriodUtils.scala index 62163481a..03d36ee21 100644 --- a/core/src/main/scala/pureconfig/PeriodUtils.scala +++ b/core/src/main/scala/pureconfig/PeriodUtils.scala @@ -7,12 +7,14 @@ import scala.util.{Success, Try} import com.typesafe.config.impl.ConfigImplUtil import pureconfig.error.{CannotConvert, FailureReason} -/** Utility functions for converting a `String` to a `Period`. The parser accepts the HOCON unit syntax. - */ +/** + * Utility functions for converting a `String` to a `Period`. The parser accepts the HOCON unit syntax. + */ private[pureconfig] object PeriodUtils { - /** Convert a string to a Period while trying to maintain compatibility with Typesafe's abbreviations. - */ + /** + * Convert a string to a Period while trying to maintain compatibility with Typesafe's abbreviations. + */ val fromString: String => Either[FailureReason, Period] = { str => Try(Right(Period.parse(str))).getOrElse(typesafeConfigParsePeriod(str)) } diff --git a/core/src/main/scala/pureconfig/backend/ConfigFactoryWrapper.scala b/core/src/main/scala/pureconfig/backend/ConfigFactoryWrapper.scala index 5fd0aaecc..51d515679 100644 --- a/core/src/main/scala/pureconfig/backend/ConfigFactoryWrapper.scala +++ b/core/src/main/scala/pureconfig/backend/ConfigFactoryWrapper.scala @@ -9,9 +9,10 @@ import pureconfig._ import pureconfig.backend.ErrorUtil._ import pureconfig.error._ -/** A wrapper of `com.typesafe.config.ConfigFactory` whose methods return [[scala.Either]] instead - * of throwing exceptions - */ +/** + * A wrapper of `com.typesafe.config.ConfigFactory` whose methods return [[scala.Either]] instead + * of throwing exceptions + */ object ConfigFactoryWrapper { private[this] val strictSettings = ConfigParseOptions.defaults.setAllowMissing(false) diff --git a/core/src/main/scala/pureconfig/backend/ConfigWrapper.scala b/core/src/main/scala/pureconfig/backend/ConfigWrapper.scala index eabe97711..549e85eb7 100644 --- a/core/src/main/scala/pureconfig/backend/ConfigWrapper.scala +++ b/core/src/main/scala/pureconfig/backend/ConfigWrapper.scala @@ -4,9 +4,10 @@ import com.typesafe.config._ import pureconfig.ConfigReader.Result import pureconfig.backend.ErrorUtil._ -/** Provides extension methods for `com.typesafe.config.Config` that return [[scala.Either]] instead - * of throwing exceptions. - */ +/** + * Provides extension methods for `com.typesafe.config.Config` that return [[scala.Either]] instead + * of throwing exceptions. + */ object ConfigWrapper { implicit class SafeConfig(val conf: Config) extends AnyVal { diff --git a/core/src/main/scala/pureconfig/backend/ErrorUtil.scala b/core/src/main/scala/pureconfig/backend/ErrorUtil.scala index 76f505cff..69877cbe5 100644 --- a/core/src/main/scala/pureconfig/backend/ErrorUtil.scala +++ b/core/src/main/scala/pureconfig/backend/ErrorUtil.scala @@ -6,8 +6,9 @@ import com.typesafe.config._ import pureconfig._ import pureconfig.error._ -/** Contains common utilities to deal with exceptions in unsafe methods. - */ +/** + * Contains common utilities to deal with exceptions in unsafe methods. + */ object ErrorUtil { def unsafeToReaderResult[A]( diff --git a/core/src/main/scala/pureconfig/backend/PathUtil.scala b/core/src/main/scala/pureconfig/backend/PathUtil.scala index 864bf90e9..4295623b0 100644 --- a/core/src/main/scala/pureconfig/backend/PathUtil.scala +++ b/core/src/main/scala/pureconfig/backend/PathUtil.scala @@ -4,24 +4,27 @@ import scala.collection.JavaConverters._ import com.typesafe.config.ConfigUtil -/** An utility class to convert Typesafe Config path expressions to lists of keys and vice-versa, accepting empty path - * expressions and lists in addition to the values supported by `ConfigUtil`. - */ +/** + * An utility class to convert Typesafe Config path expressions to lists of keys and vice-versa, accepting empty path + * expressions and lists in addition to the values supported by `ConfigUtil`. + */ object PathUtil { - /** Parses a path expression into a list of keys from the root to the leaf value. - * - * @param path the path to parse - * @return a list of keys, from the root to the leaf value, representing the given namespace. - */ + /** + * Parses a path expression into a list of keys from the root to the leaf value. + * + * @param path the path to parse + * @return a list of keys, from the root to the leaf value, representing the given namespace. + */ def splitPath(path: String): List[String] = if (path.isEmpty) Nil else ConfigUtil.splitPath(path).asScala.toList - /** Converts a list of keys to a path expression compatible with the `get` methods in `Config`. - * - * @param elements the list of keys to convert to a string - * @return a path string compatible with the `get` methods in `Config`. - */ + /** + * Converts a list of keys to a path expression compatible with the `get` methods in `Config`. + * + * @param elements the list of keys to convert to a string + * @return a path string compatible with the `get` methods in `Config`. + */ def joinPath(elements: List[String]): String = if (elements.isEmpty) "" else ConfigUtil.joinPath(elements: _*) } diff --git a/core/src/main/scala/pureconfig/configurable/package.scala b/core/src/main/scala/pureconfig/configurable/package.scala index 7e5c6960b..cdbaeb183 100644 --- a/core/src/main/scala/pureconfig/configurable/package.scala +++ b/core/src/main/scala/pureconfig/configurable/package.scala @@ -9,19 +9,20 @@ import pureconfig.error.FailureReason import scala.collection.JavaConverters._ -/** Provides methods that create [[ConfigConvert]] instances from a set of parameters used to configure the instances. - * - * The result of calling one of the methods can be assigned to an `implicit val` so that `pureconfig` will be able to - * use it: - * {{{ - * implicit val localDateConfigConvert = makeLocalDateConfigConvert(DateTimeFormatter.ISO_TIME) - * }}} - * - * @example we cannot provide a [[ConfigConvert]] for [[java.time.LocalDate]] because traditionally there are many different - * [[java.time.format.DateTimeFormatter]]s to parse a [[java.time.LocalDate]] from a [[java.lang.String]]. This package - * provides a method that takes an input [[java.time.format.DateTimeFormatter]] and returns a [[ConfigConvert]] for - * [[java.time.LocalDate]] which will use that [[java.time.format.DateTimeFormatter]] to parse a [[java.time.LocalDate]]. - */ +/** + * Provides methods that create [[ConfigConvert]] instances from a set of parameters used to configure the instances. + * + * The result of calling one of the methods can be assigned to an `implicit val` so that `pureconfig` will be able to + * use it: + * {{{ + * implicit val localDateConfigConvert = makeLocalDateConfigConvert(DateTimeFormatter.ISO_TIME) + * }}} + * + * @example we cannot provide a [[ConfigConvert]] for [[java.time.LocalDate]] because traditionally there are many different + * [[java.time.format.DateTimeFormatter]]s to parse a [[java.time.LocalDate]] from a [[java.lang.String]]. This package + * provides a method that takes an input [[java.time.format.DateTimeFormatter]] and returns a [[ConfigConvert]] for + * [[java.time.LocalDate]] which will use that [[java.time.format.DateTimeFormatter]] to parse a [[java.time.LocalDate]]. + */ package object configurable { def localDateConfigConvert(formatter: DateTimeFormatter): ConfigConvert[LocalDate] = diff --git a/core/src/main/scala/pureconfig/error/ConfigReaderFailure.scala b/core/src/main/scala/pureconfig/error/ConfigReaderFailure.scala index 4849f9de9..b315c9c39 100644 --- a/core/src/main/scala/pureconfig/error/ConfigReaderFailure.scala +++ b/core/src/main/scala/pureconfig/error/ConfigReaderFailure.scala @@ -10,27 +10,31 @@ import java.nio.file.Path import com.typesafe.config.ConfigOrigin import pureconfig.ConfigCursor -/** A representation of a failure raised from reading a config. The failure contains an optional file system location of - * the configuration that raised the failure. - */ +/** + * A representation of a failure raised from reading a config. The failure contains an optional file system location of + * the configuration that raised the failure. + */ trait ConfigReaderFailure { - /** A human-readable description of the failure. - */ + /** + * A human-readable description of the failure. + */ def description: String - /** The optional origin of the failure. - */ + /** + * The optional origin of the failure. + */ def origin: Option[ConfigOrigin] } -/** A failure occurred when converting from a `ConfigValue` to a given type. The failure contains a path to the - * `ConfigValue` that raised the error. - * - * @param reason the reason for the conversion failure - * @param origin the optional origin of the failure - * @param path the path to the `ConfigValue` that raised the error - */ +/** + * A failure occurred when converting from a `ConfigValue` to a given type. The failure contains a path to the + * `ConfigValue` that raised the error. + * + * @param reason the reason for the conversion failure + * @param origin the optional origin of the failure + * @param path the path to the `ConfigValue` that raised the error + */ case class ConvertFailure(reason: FailureReason, origin: Option[ConfigOrigin], path: String) extends ConfigReaderFailure { @@ -39,49 +43,56 @@ case class ConvertFailure(reason: FailureReason, origin: Option[ConfigOrigin], p object ConvertFailure { - /** Constructs a `ConvertFailure` from a reason and a `ConfigCursor`. - * - * @param reason the reason for the conversion failure - * @param cur the cursor where the failure ocurred - * @return a `ConvertFailure` for the given reason at the given cursor. - */ + /** + * Constructs a `ConvertFailure` from a reason and a `ConfigCursor`. + * + * @param reason the reason for the conversion failure + * @param cur the cursor where the failure ocurred + * @return a `ConvertFailure` for the given reason at the given cursor. + */ def apply(reason: FailureReason, cur: ConfigCursor): ConvertFailure = ConvertFailure(reason, cur.origin, cur.path) } -/** A failure occurred because a list of files to load was empty. - */ +/** + * A failure occurred because a list of files to load was empty. + */ @deprecated("`loadConfigFromFiles` won't return this failure anymore", "0.10.1") case object NoFilesToRead extends ConfigReaderFailure { def description = "The config files to load must not be empty." def origin = None } -/** A failure occurred because an exception was thrown during the reading process. - * - * @param throwable the exception thrown - * @param origin the optional origin of the failure - */ +/** + * A failure occurred because an exception was thrown during the reading process. + * + * @param throwable the exception thrown + * @param origin the optional origin of the failure + */ final case class ThrowableFailure(throwable: Throwable, origin: Option[ConfigOrigin]) extends ConfigReaderFailure { def description = s"${throwable.getMessage}." } -/** A failure occurred due to the inability to read a requested source (such as a file, a resource or a network - * location). - */ +/** + * A failure occurred due to the inability to read a requested source (such as a file, a resource or a network + * location). + */ trait CannotRead extends ConfigReaderFailure { - /** The source name (like a file path or a URL) - */ + /** + * The source name (like a file path or a URL) + */ def sourceName: String - /** The source type - */ + /** + * The source type + */ def sourceType: String - /** An optional exception thrown when trying to read the source - */ + /** + * An optional exception thrown when trying to read the source + */ def reason: Option[Throwable] def description = @@ -95,41 +106,45 @@ trait CannotRead extends ConfigReaderFailure { def origin = None } -/** A failure occurred due to the inability to read a requested file. - * - * @param path the file system path of the file that couldn't be read - * @param reason an optional exception thrown when trying to read the file - */ +/** + * A failure occurred due to the inability to read a requested file. + * + * @param path the file system path of the file that couldn't be read + * @param reason an optional exception thrown when trying to read the file + */ final case class CannotReadFile(path: Path, reason: Option[Throwable]) extends CannotRead { val sourceType = "file" def sourceName = path.toString } -/** A failure occurred due to the inability to read a requested URL. - * - * @param url the URL that couldn't be read - * @param reason an optional exception thrown when trying to read the URL - */ +/** + * A failure occurred due to the inability to read a requested URL. + * + * @param url the URL that couldn't be read + * @param reason an optional exception thrown when trying to read the URL + */ final case class CannotReadUrl(url: URL, reason: Option[Throwable]) extends CannotRead { val sourceType = "URL" def sourceName = url.toString } -/** A failure occurred due to the inability to read a requested resource. - * - * @param resourceName the resource that couldn't be read - * @param reason an optional exception thrown when trying to read the resource - */ +/** + * A failure occurred due to the inability to read a requested resource. + * + * @param resourceName the resource that couldn't be read + * @param reason an optional exception thrown when trying to read the resource + */ final case class CannotReadResource(resourceName: String, reason: Option[Throwable]) extends CannotRead { val sourceType = "resource" def sourceName = resourceName } -/** A failure occurred due to the inability to parse the configuration. - * - * @param msg the error message from the parser - * @param origin the optional origin of the failure - */ +/** + * A failure occurred due to the inability to parse the configuration. + * + * @param msg the error message from the parser + * @param origin the optional origin of the failure + */ final case class CannotParse(msg: String, origin: Option[ConfigOrigin]) extends ConfigReaderFailure { def description = s"Unable to parse the configuration: $msg." } diff --git a/core/src/main/scala/pureconfig/error/ConfigReaderFailures.scala b/core/src/main/scala/pureconfig/error/ConfigReaderFailures.scala index 7eb2d909d..751acc811 100644 --- a/core/src/main/scala/pureconfig/error/ConfigReaderFailures.scala +++ b/core/src/main/scala/pureconfig/error/ConfigReaderFailures.scala @@ -5,8 +5,9 @@ package pureconfig.error import scala.collection.mutable -/** A non-empty list of ConfigReader failures - */ +/** + * A non-empty list of ConfigReader failures + */ case class ConfigReaderFailures(head: ConfigReaderFailure, tail: ConfigReaderFailure*) { def toList: List[ConfigReaderFailure] = head :: tail.toList diff --git a/core/src/main/scala/pureconfig/error/FailureReason.scala b/core/src/main/scala/pureconfig/error/FailureReason.scala index a7ceb956f..be6a2d03f 100644 --- a/core/src/main/scala/pureconfig/error/FailureReason.scala +++ b/core/src/main/scala/pureconfig/error/FailureReason.scala @@ -5,42 +5,47 @@ import scala.collection.mutable import com.typesafe.config.{ConfigValue, ConfigValueType} -/** A representation of a reason why a value failed to be converted. - */ +/** + * A representation of a reason why a value failed to be converted. + */ trait FailureReason { - /** A human-readable description of the failure. - */ + /** + * A human-readable description of the failure. + */ def description: String } -/** A general reason given for the failure of a value to be converted to a desired type. - * - * @param value the value that was requested to be converted - * @param toType the target type that the value was requested to be converted to - * @param because the reason why the conversion was not possible - */ +/** + * A general reason given for the failure of a value to be converted to a desired type. + * + * @param value the value that was requested to be converted + * @param toType the target type that the value was requested to be converted to + * @param because the reason why the conversion was not possible + */ final case class CannotConvert(value: String, toType: String, because: String) extends FailureReason { def description = s"Cannot convert '$value' to $toType: $because." } -/** A failure reason given when there is a collision of keys with different semantics. This error is raised when a key - * that should be used to disambiguate a coproduct is mapped to a field in a product. - * - * @param key the colliding key - * @param existingValue the value of the key - */ +/** + * A failure reason given when there is a collision of keys with different semantics. This error is raised when a key + * that should be used to disambiguate a coproduct is mapped to a field in a product. + * + * @param key the colliding key + * @param existingValue the value of the key + */ final case class CollidingKeys(key: String, existingValue: ConfigValue) extends FailureReason { def description = s"Key with value '{$existingValue.render(ConfigRenderOptions.concise)}' collides with a key necessary to disambiguate a coproduct." } -/** A failure reason given when a key is missing from a `ConfigObject` or `ConfigList`. - * - * @param key the key that is missing - * @param candidates a set of candidate keys that might correspond to the - * desired key in case of a misconfigured ProductHint - */ +/** + * A failure reason given when a key is missing from a `ConfigObject` or `ConfigList`. + * + * @param key the key that is missing + * @param candidates a set of candidate keys that might correspond to the + * desired key in case of a misconfigured ProductHint + */ final case class KeyNotFound(key: String, candidates: Set[String] = Set()) extends FailureReason { def description = { if (candidates.nonEmpty) { @@ -77,46 +82,51 @@ object KeyNotFound { } } -/** A failure reason given when an unknown key is found in a `ConfigObject`. The failure is raised when a key of a - * `ConfigObject` is not mapped into a field of a given type and the `allowUnknownKeys` property of the `ProductHint` - * for the type in question is `false`. - * - * @param key the unknown key - */ +/** + * A failure reason given when an unknown key is found in a `ConfigObject`. The failure is raised when a key of a + * `ConfigObject` is not mapped into a field of a given type and the `allowUnknownKeys` property of the `ProductHint` + * for the type in question is `false`. + * + * @param key the unknown key + */ final case class UnknownKey(key: String) extends FailureReason { def description = s"Unknown key." } -/** A failure reason given when a `ConfigValue` has the wrong type. - * - * @param foundType the `ConfigValueType` that was found - * @param expectedTypes the `ConfigValueType`s that were expected - */ +/** + * A failure reason given when a `ConfigValue` has the wrong type. + * + * @param foundType the `ConfigValueType` that was found + * @param expectedTypes the `ConfigValueType`s that were expected + */ final case class WrongType(foundType: ConfigValueType, expectedTypes: Set[ConfigValueType]) extends FailureReason { def description = s"""Expected type ${expectedTypes.mkString(" or ")}. Found $foundType instead.""" } -/** A failure reason given when an exception is thrown during a conversion. - * - * @param throwable the `Throwable` that was raised - */ +/** + * A failure reason given when an exception is thrown during a conversion. + * + * @param throwable the `Throwable` that was raised + */ final case class ExceptionThrown(throwable: Throwable) extends FailureReason { def description = s"${throwable.getMessage}." } -/** A failure reason given when an unexpected empty string is found. - * - * @param typ the type that was attempted to be converted to from an empty string - */ +/** + * A failure reason given when an unexpected empty string is found. + * + * @param typ the type that was attempted to be converted to from an empty string + */ final case class EmptyStringFound(typ: String) extends FailureReason { def description = s"Empty string found when trying to convert to $typ." } -/** A failure reason given when an unexpected non-empty object is found. The failure happens when using - * `EnumCoproductHint` to write a config. - * - * @param typ the type for which a non-empty object was attempted to be written - */ +/** + * A failure reason given when an unexpected non-empty object is found. The failure happens when using + * `EnumCoproductHint` to write a config. + * + * @param typ the type for which a non-empty object was attempted to be written + */ @deprecated( "`EnumCoproductHint` is deprecated in favor of the `pureconfig.generic.semiauto.deriveEnumeration(Reader|Writer|Convert)[A]` methods", "0.11.0" @@ -125,20 +135,22 @@ final case class NonEmptyObjectFound(typ: String) extends FailureReason { def description = s"Non-empty object found when using EnumCoproductHint to write a $typ." } -/** A failure reason given when a list of an unexpected size is found when attempting to read into an `HList`. - * - * @param expected the expected number of elements - * @param found the number of elements found - */ +/** + * A failure reason given when a list of an unexpected size is found when attempting to read into an `HList`. + * + * @param expected the expected number of elements + * @param found the number of elements found + */ final case class WrongSizeList(expected: Int, found: Int) extends FailureReason { def description = s"List of wrong size found. Expected $expected elements. Found $found elements instead." } -/** A failure reason given when a string is not of the expected size. - * - * @param expected the expected number of characters - * @param found the number of characters found - */ +/** + * A failure reason given when a string is not of the expected size. + * + * @param expected the expected number of characters + * @param found the number of characters found + */ final case class WrongSizeString(expected: Int, found: Int) extends FailureReason { def description = s"String of wrong size found. Expected $expected characters. Found $found characters instead." } diff --git a/core/src/main/scala/pureconfig/package.scala b/core/src/main/scala/pureconfig/package.scala index 300c8439e..13f0c0ac5 100644 --- a/core/src/main/scala/pureconfig/package.scala +++ b/core/src/main/scala/pureconfig/package.scala @@ -1,8 +1,9 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/** @author Mario Pastorelli - */ +/** + * @author Mario Pastorelli + */ import java.io.{OutputStream, OutputStreamWriter} import java.nio.charset.StandardCharsets.UTF_8 @@ -15,46 +16,50 @@ import pureconfig.error._ package object pureconfig { - /** Load a configuration of type `A` from the standard configuration files - * - * @return A `Success` with the configuration if it is possible to create an instance of type - * `A` from the configuration files, else a `Failure` with details on why it - * isn't possible - */ + /** + * Load a configuration of type `A` from the standard configuration files + * + * @return A `Success` with the configuration if it is possible to create an instance of type + * `A` from the configuration files, else a `Failure` with details on why it + * isn't possible + */ @deprecated("Use `ConfigSource.default.load[A]` instead", "0.12.0") def loadConfig[A](implicit reader: Derivation[ConfigReader[A]]): ConfigReader.Result[A] = ConfigSource.default.load[A] - /** Load a configuration of type `A` from the standard configuration files - * - * @param namespace the base namespace from which the configuration should be load - * @return A `Success` with the configuration if it is possible to create an instance of type - * `A` from the configuration files, else a `Failure` with details on why it - * isn't possible - */ + /** + * Load a configuration of type `A` from the standard configuration files + * + * @param namespace the base namespace from which the configuration should be load + * @return A `Success` with the configuration if it is possible to create an instance of type + * `A` from the configuration files, else a `Failure` with details on why it + * isn't possible + */ @deprecated("Use `ConfigSource.default.at(namespace).load[A]` instead", "0.12.0") def loadConfig[A](namespace: String)(implicit reader: Derivation[ConfigReader[A]]): ConfigReader.Result[A] = ConfigSource.default.at(namespace).load[A] - /** Load a configuration of type `A` from the given file. Note that standard configuration - * files are still loaded but can be overridden from the given configuration file - * - * @return A `Success` with the configuration if it is possible to create an instance of type - * `A` from the configuration files, else a `Failure` with details on why it - * isn't possible - */ + /** + * Load a configuration of type `A` from the given file. Note that standard configuration + * files are still loaded but can be overridden from the given configuration file + * + * @return A `Success` with the configuration if it is possible to create an instance of type + * `A` from the configuration files, else a `Failure` with details on why it + * isn't possible + */ @deprecated("Use `ConfigSource.default(ConfigSource.file(path)).load[A]` instead", "0.12.0") def loadConfig[A](path: Path)(implicit reader: Derivation[ConfigReader[A]]): ConfigReader.Result[A] = ConfigSource.default(ConfigSource.file(path)).load[A] - /** Load a configuration of type `A` from the given file. Note that standard configuration - * files are still loaded but can be overridden from the given configuration file - * - * @param namespace the base namespace from which the configuration should be load - * @return A `Success` with the configuration if it is possible to create an instance of type - * `A` from the configuration files, else a `Failure` with details on why it - * isn't possible - */ + /** + * Load a configuration of type `A` from the given file. Note that standard configuration + * files are still loaded but can be overridden from the given configuration file + * + * @param namespace the base namespace from which the configuration should be load + * @return A `Success` with the configuration if it is possible to create an instance of type + * `A` from the configuration files, else a `Failure` with details on why it + * isn't possible + */ @deprecated("Use `ConfigSource.default(ConfigSource.file(path)).at(namespace).load[A]` instead", "0.12.0") def loadConfig[A](path: Path, namespace: String)(implicit reader: Derivation[ConfigReader[A]] @@ -73,25 +78,27 @@ package object pureconfig { ): ConfigReader.Result[A] = ConfigSource.fromConfig(conf).at(namespace).load[A] - /** Load a configuration of type `A` from the given `Config`, falling back to the default configuration - * - * @param conf Typesafe configuration to load - * @return A `Success` with the configuration if it is possible to create an instance of type - * `A` from the configuration files, else a `Failure` with details on why it - * isn't possible - */ + /** + * Load a configuration of type `A` from the given `Config`, falling back to the default configuration + * + * @param conf Typesafe configuration to load + * @return A `Success` with the configuration if it is possible to create an instance of type + * `A` from the configuration files, else a `Failure` with details on why it + * isn't possible + */ @deprecated("Use `ConfigSource.fromConfig(conf).withFallback(ConfigSource.default).load[A]` instead", "0.12.0") def loadConfigWithFallback[A](conf: Config)(implicit reader: Derivation[ConfigReader[A]]): ConfigReader.Result[A] = ConfigSource.fromConfig(conf).withFallback(ConfigSource.default).load[A] - /** Load a configuration of type `A` from the given `Config`, falling back to the default configuration - * - * @param conf Typesafe configuration to load - * @param namespace the base namespace from which the configuration should be load - * @return A `Success` with the configuration if it is possible to create an instance of type - * `A` from the configuration files, else a `Failure` with details on why it - * isn't possible - */ + /** + * Load a configuration of type `A` from the given `Config`, falling back to the default configuration + * + * @param conf Typesafe configuration to load + * @param namespace the base namespace from which the configuration should be load + * @return A `Success` with the configuration if it is possible to create an instance of type + * `A` from the configuration files, else a `Failure` with details on why it + * isn't possible + */ @deprecated( "Use `ConfigSource.fromConfig(conf).withFallback(ConfigSource.default).at(namespace).load[A]` instead", "0.12.0" @@ -101,83 +108,91 @@ package object pureconfig { ): ConfigReader.Result[A] = ConfigSource.fromConfig(conf).withFallback(ConfigSource.default).at(namespace).load[A] - /** Load a configuration of type `A` from the standard configuration files - * - * @return the configuration - */ + /** + * Load a configuration of type `A` from the standard configuration files + * + * @return the configuration + */ @throws[ConfigReaderException[_]] @deprecated("Use `ConfigSource.default.loadOrThrow[A]` instead", "0.12.0") def loadConfigOrThrow[A: ClassTag](implicit reader: Derivation[ConfigReader[A]]): A = ConfigSource.default.loadOrThrow[A] - /** Load a configuration of type `A` from the standard configuration files - * - * @param namespace the base namespace from which the configuration should be load - * @return the configuration - */ + /** + * Load a configuration of type `A` from the standard configuration files + * + * @param namespace the base namespace from which the configuration should be load + * @return the configuration + */ @throws[ConfigReaderException[_]] @deprecated("Use `ConfigSource.default.at(namespace).loadOrThrow[A]` instead", "0.12.0") def loadConfigOrThrow[A: ClassTag](namespace: String)(implicit reader: Derivation[ConfigReader[A]]): A = ConfigSource.default.at(namespace).loadOrThrow[A] - /** Load a configuration of type `A` from the given file. Note that standard configuration - * files are still loaded but can be overridden from the given configuration file - * - * @return the configuration - */ + /** + * Load a configuration of type `A` from the given file. Note that standard configuration + * files are still loaded but can be overridden from the given configuration file + * + * @return the configuration + */ @throws[ConfigReaderException[_]] @deprecated("Use `ConfigSource.default(ConfigSource.file(path)).loadOrThrow[A]` instead", "0.12.0") def loadConfigOrThrow[A: ClassTag](path: Path)(implicit reader: Derivation[ConfigReader[A]]): A = ConfigSource.default(ConfigSource.file(path)).loadOrThrow[A] - /** Load a configuration of type `A` from the given file. Note that standard configuration - * files are still loaded but can be overridden from the given configuration file - * - * @param namespace the base namespace from which the configuration should be load - * @return the configuration - */ + /** + * Load a configuration of type `A` from the given file. Note that standard configuration + * files are still loaded but can be overridden from the given configuration file + * + * @param namespace the base namespace from which the configuration should be load + * @return the configuration + */ @throws[ConfigReaderException[_]] @deprecated("Use `ConfigSource.default(ConfigSource.file(path)).at(namespace).loadOrThrow[A]` instead", "0.12.0") def loadConfigOrThrow[A: ClassTag](path: Path, namespace: String)(implicit reader: Derivation[ConfigReader[A]]): A = ConfigSource.default(ConfigSource.file(path)).at(namespace).loadOrThrow[A] - /** Load a configuration of type `A` from the given `Config` - * - * @param conf Typesafe configuration to load - * @return the configuration - */ + /** + * Load a configuration of type `A` from the given `Config` + * + * @param conf Typesafe configuration to load + * @return the configuration + */ @throws[ConfigReaderException[_]] @deprecated("Use `ConfigSource.fromConfig(conf).loadOrThrow[A]` instead", "0.12.0") def loadConfigOrThrow[A: ClassTag](conf: Config)(implicit reader: Derivation[ConfigReader[A]]): A = ConfigSource.fromConfig(conf).loadOrThrow[A] - /** Load a configuration of type `A` from the given `Config` - * - * @param conf Typesafe configuration to load - * @param namespace the base namespace from which the configuration should be load - * @return the configuration - */ + /** + * Load a configuration of type `A` from the given `Config` + * + * @param conf Typesafe configuration to load + * @param namespace the base namespace from which the configuration should be load + * @return the configuration + */ @throws[ConfigReaderException[_]] @deprecated("Use `ConfigSource.fromConfig(conf).at(namespace).loadOrThrow[A]` instead", "0.12.0") def loadConfigOrThrow[A: ClassTag](conf: Config, namespace: String)(implicit reader: Derivation[ConfigReader[A]]): A = ConfigSource.fromConfig(conf).at(namespace).loadOrThrow[A] - /** Load a configuration of type `A` from the given `Config`, falling back to the default configuration - * - * @param conf Typesafe configuration to load - * @return the configuration - */ + /** + * Load a configuration of type `A` from the given `Config`, falling back to the default configuration + * + * @param conf Typesafe configuration to load + * @return the configuration + */ @throws[ConfigReaderException[_]] @deprecated("Use `ConfigSource.fromConfig(conf).withFallback(ConfigSource.default).loadOrThrow[A]` instead", "0.12.0") def loadConfigWithFallbackOrThrow[A: ClassTag](conf: Config)(implicit reader: Derivation[ConfigReader[A]]): A = ConfigSource.fromConfig(conf).withFallback(ConfigSource.default).loadOrThrow[A] - /** Load a configuration of type `A` from the given `Config`, falling back to the default configuration - * - * @param conf Typesafe configuration to load - * @param namespace the base namespace from which the configuration should be load - * @return the configuration - */ + /** + * Load a configuration of type `A` from the given `Config`, falling back to the default configuration + * + * @param conf Typesafe configuration to load + * @param namespace the base namespace from which the configuration should be load + * @return the configuration + */ @throws[ConfigReaderException[_]] @deprecated( "Use `ConfigSource.fromConfig(conf).withFallback(ConfigSource.default).at(namespace).loadOrThrow[A]` instead", @@ -188,13 +203,14 @@ package object pureconfig { ): A = ConfigSource.fromConfig(conf).withFallback(ConfigSource.default).at(namespace).loadOrThrow[A] - /** Save the given configuration into a property file - * - * @param conf The configuration to save - * @param outputPath Where to write the configuration - * @param overrideOutputPath Override the path if it already exists - * @param options the config rendering options - */ + /** + * Save the given configuration into a property file + * + * @param conf The configuration to save + * @param outputPath Where to write the configuration + * @param overrideOutputPath Override the path if it already exists + * @param options the config rendering options + */ @throws[IllegalArgumentException] def saveConfigAsPropertyFile[A]( conf: A, @@ -215,12 +231,13 @@ package object pureconfig { saveConfigToStream(conf, Files.newOutputStream(outputPath), options) } - /** Writes the configuration to the output stream and closes the stream - * - * @param conf The configuration to write - * @param outputStream The stream in which the configuration should be written - * @param options the config rendering options - */ + /** + * Writes the configuration to the output stream and closes the stream + * + * @param conf The configuration to write + * @param outputStream The stream in which the configuration should be written + * @param options the config rendering options + */ def saveConfigToStream[A]( conf: A, outputStream: OutputStream, @@ -235,19 +252,20 @@ package object pureconfig { printOutputStream.close() } - /** Loads `files` in order, allowing values in later files to backstop missing values from prior, and converts them - * into a `Config`. - * - * This is a convenience method which enables having default configuration which backstops local configuration. - * - * The behavior of the method if an element of `files` references a file which doesn't exist or can't be read is - * defined by the `failOnReadError` flag. With `failOnReadError = false`, such files will silently be ignored while - * otherwise they would yield a failure (a `Left` value). - * - * @param files Files ordered in decreasing priority containing part or all of a `Config` - * @param failOnReadError Where to return an error if any files fail to read - * @param namespace the base namespace from which the configuration should be load - */ + /** + * Loads `files` in order, allowing values in later files to backstop missing values from prior, and converts them + * into a `Config`. + * + * This is a convenience method which enables having default configuration which backstops local configuration. + * + * The behavior of the method if an element of `files` references a file which doesn't exist or can't be read is + * defined by the `failOnReadError` flag. With `failOnReadError = false`, such files will silently be ignored while + * otherwise they would yield a failure (a `Left` value). + * + * @param files Files ordered in decreasing priority containing part or all of a `Config` + * @param failOnReadError Where to return an error if any files fail to read + * @param namespace the base namespace from which the configuration should be load + */ @deprecated("Construct a custom `ConfigSource` pipeline instead", "0.12.0") def loadConfigFromFiles[A](files: Traversable[Path], failOnReadError: Boolean = false, namespace: String = "")( implicit reader: Derivation[ConfigReader[A]] @@ -263,9 +281,10 @@ package object pureconfig { .load[A] } - /** @see [[loadConfigFromFiles]] - * @return the configuration - */ + /** + * @see [[loadConfigFromFiles]] + * @return the configuration + */ @throws[ConfigReaderException[_]] @deprecated("Construct a custom `ConfigSource` pipeline instead", "0.12.0") def loadConfigFromFilesOrThrow[A: ClassTag]( diff --git a/macros/src/main/scala-2.13-/pureconfig/derivation/LazyContextParser.scala b/macros/src/main/scala-2.13-/pureconfig/derivation/LazyContextParser.scala index 55e4fc19c..3a3754087 100644 --- a/macros/src/main/scala-2.13-/pureconfig/derivation/LazyContextParser.scala +++ b/macros/src/main/scala-2.13-/pureconfig/derivation/LazyContextParser.scala @@ -2,31 +2,34 @@ package pureconfig.derivation import scala.reflect.macros.whitebox -/** Encapsulates the logic to parse Scala syntax trees genetrated by `Lazy`, providing a high-level way to navigate - * through such a tree. The code on this class is heavily-dependent on the implementation details of `Lazy`. - */ +/** + * Encapsulates the logic to parse Scala syntax trees genetrated by `Lazy`, providing a high-level way to navigate + * through such a tree. The code on this class is heavily-dependent on the implementation details of `Lazy`. + */ trait LazyContextParser { val c: whitebox.Context import c.universe._ - /** A representation of all the relevant information of a `Lazy`-generated tree. - * - * @param anonClass the name of the anonymous class containing lazy value definitions - * @param defs a map from lazy value names to their definition - * @param entrypoint the tree serving as entrypoint to a lazy implicit - */ + /** + * A representation of all the relevant information of a `Lazy`-generated tree. + * + * @param anonClass the name of the anonymous class containing lazy value definitions + * @param defs a map from lazy value names to their definition + * @param entrypoint the tree serving as entrypoint to a lazy implicit + */ case class LazyContext(anonClass: TypeName, defs: Map[TermName, Tree], entrypoint: Tree) { - /** Checks if a `Tree` is a reference to a lazy value generated by `Lazy`. If it is a valid reference, it returns - * a `Tree` with the corresponding definition and a new `LazyContext` to be used in inner searches. The new - * `LazyContext` does not have the followed reference in order to prevent infinite loops when searching (the - * original use case for `Lazy`). - * - * @param tree the tree to be checked - * @return if `tree` is a reference to a `Lazy`-generated value, a `Some` with the respective definition and a new - * `LazyContext`; `None` otherwise. - */ + /** + * Checks if a `Tree` is a reference to a lazy value generated by `Lazy`. If it is a valid reference, it returns + * a `Tree` with the corresponding definition and a new `LazyContext` to be used in inner searches. The new + * `LazyContext` does not have the followed reference in order to prevent infinite loops when searching (the + * original use case for `Lazy`). + * + * @param tree the tree to be checked + * @return if `tree` is a reference to a `Lazy`-generated value, a `Some` with the respective definition and a new + * `LazyContext`; `None` otherwise. + */ def followRef(tree: Tree): Option[(LazyContext, Tree)] = tree match { case q"${`anonClass`}.this.$lazyRef" => @@ -36,12 +39,14 @@ trait LazyContextParser { } } - /** An object containing an extractor of `LazyContext` instances from Scala trees. - */ + /** + * An object containing an extractor of `LazyContext` instances from Scala trees. + */ object LazyContextTree { - /** Extracts a `LazyContext` from a `Tree`. - */ + /** + * Extracts a `LazyContext` from a `Tree`. + */ def unapply(tree: Tree): Option[LazyContext] = tree match { case q"""{ diff --git a/macros/src/main/scala-2.13-/pureconfig/derivation/MacroCompat.scala b/macros/src/main/scala-2.13-/pureconfig/derivation/MacroCompat.scala index f12d346e9..e51484e3b 100644 --- a/macros/src/main/scala-2.13-/pureconfig/derivation/MacroCompat.scala +++ b/macros/src/main/scala-2.13-/pureconfig/derivation/MacroCompat.scala @@ -4,9 +4,10 @@ import scala.reflect.macros.{TypecheckException, whitebox} import pureconfig.Derivation -/** An API for macro operations that require access to macro or even compiler internals. Since they rely on - * non-public APIs, the code may be distinct between Scala major versions and even between minor versions. - */ +/** + * An API for macro operations that require access to macro or even compiler internals. Since they rely on + * non-public APIs, the code may be distinct between Scala major versions and even between minor versions. + */ trait MacroCompat { val c: whitebox.Context diff --git a/modules/akka/src/main/scala/pureconfig/module/akka/package.scala b/modules/akka/src/main/scala/pureconfig/module/akka/package.scala index 7f1182a37..8fba2e4e4 100644 --- a/modules/akka/src/main/scala/pureconfig/module/akka/package.scala +++ b/modules/akka/src/main/scala/pureconfig/module/akka/package.scala @@ -8,8 +8,9 @@ import pureconfig.ConfigConvert import pureconfig.ConfigConvert.viaString import pureconfig.ConvertHelpers.catchReadError -/** ConfigConvert instances for Akka value classes. - */ +/** + * ConfigConvert instances for Akka value classes. + */ package object akka { implicit val timeoutCC: ConfigConvert[Timeout] = ConfigConvert[FiniteDuration].xmap(new Timeout(_), _.duration) diff --git a/modules/cats-effect/src/main/scala/pureconfig/module/catseffect/package.scala b/modules/cats-effect/src/main/scala/pureconfig/module/catseffect/package.scala index 6e16bbaf4..9f7e290d6 100644 --- a/modules/cats-effect/src/main/scala/pureconfig/module/catseffect/package.scala +++ b/modules/cats-effect/src/main/scala/pureconfig/module/catseffect/package.scala @@ -19,13 +19,14 @@ package object catseffect { @deprecated("Root will be treated as the default namespace", "0.12.0") val defaultNameSpace = "" - /** Load a configuration of type `A` from a config source - * - * @param cs the config source from where the configuration will be loaded - * @return The returned action will complete with `A` if it is possible to create an instance of type - * `A` from the configuration source, or fail with a ConfigReaderException which in turn contains - * details on why it isn't possible - */ + /** + * Load a configuration of type `A` from a config source + * + * @param cs the config source from where the configuration will be loaded + * @return The returned action will complete with `A` if it is possible to create an instance of type + * `A` from the configuration source, or fail with a ConfigReaderException which in turn contains + * details on why it isn't possible + */ @deprecated("Use `loadF[F, A](cs, blocker)` instead", "0.12.3") def loadF[F[_], A]( cs: ConfigSource @@ -36,14 +37,15 @@ package object catseffect { delayedLoad.rethrow } - /** Load a configuration of type `A` from a config source - * - * @param cs the config source from where the configuration will be loaded - * @param blocker the blocking context which will be used to load the configuration. - * @return The returned action will complete with `A` if it is possible to create an instance of type - * `A` from the configuration source, or fail with a ConfigReaderException which in turn contains - * details on why it isn't possible - */ + /** + * Load a configuration of type `A` from a config source + * + * @param cs the config source from where the configuration will be loaded + * @param blocker the blocking context which will be used to load the configuration. + * @return The returned action will complete with `A` if it is possible to create an instance of type + * `A` from the configuration source, or fail with a ConfigReaderException which in turn contains + * details on why it isn't possible + */ def loadF[F[_], A]( cs: ConfigSource, blocker: Blocker @@ -53,64 +55,69 @@ package object catseffect { .leftMap(ConfigReaderException[A]) .rethrowT - /** Load a configuration of type `A` from the standard configuration files - * - * @return The returned action will complete with `A` if it is possible to create an instance of type - * `A` from the configuration files, or fail with a ConfigReaderException which in turn contains - * details on why it isn't possible - */ + /** + * Load a configuration of type `A` from the standard configuration files + * + * @return The returned action will complete with `A` if it is possible to create an instance of type + * `A` from the configuration files, or fail with a ConfigReaderException which in turn contains + * details on why it isn't possible + */ @deprecated("Use `loadConfigF[F, A](blocker)` instead", "0.12.3") def loadConfigF[F[_], A](implicit F: Sync[F], reader: Derivation[ConfigReader[A]], ct: ClassTag[A]): F[A] = loadF[F, A](ConfigSource.default) - /** Load a configuration of type `A` from the standard configuration files - * - * @param blocker the blocking context which will be used to load the configuration. - * @return The returned action will complete with `A` if it is possible to create an instance of type - * `A` from the configuration files, or fail with a ConfigReaderException which in turn contains - * details on why it isn't possible - */ + /** + * Load a configuration of type `A` from the standard configuration files + * + * @param blocker the blocking context which will be used to load the configuration. + * @return The returned action will complete with `A` if it is possible to create an instance of type + * `A` from the configuration files, or fail with a ConfigReaderException which in turn contains + * details on why it isn't possible + */ def loadConfigF[F[_], A]( blocker: Blocker )(implicit F: Sync[F], csf: ContextShift[F], reader: Derivation[ConfigReader[A]], ct: ClassTag[A]): F[A] = loadF(ConfigSource.default, blocker) - /** Load a configuration of type `A` from the standard configuration files - * - * @param namespace the base namespace from which the configuration should be load - * @return The returned action will complete with `A` if it is possible to create an instance of type - * `A` from the configuration files, or fail with a ConfigReaderException which in turn contains - * details on why it isn't possible - */ + /** + * Load a configuration of type `A` from the standard configuration files + * + * @param namespace the base namespace from which the configuration should be load + * @return The returned action will complete with `A` if it is possible to create an instance of type + * `A` from the configuration files, or fail with a ConfigReaderException which in turn contains + * details on why it isn't possible + */ @deprecated("Use `ConfigSource.default.at(namespace).loadF[F, A]` instead", "0.12.0") def loadConfigF[F[_], A]( namespace: String )(implicit F: Sync[F], reader: Derivation[ConfigReader[A]], ct: ClassTag[A]): F[A] = loadF[F, A](ConfigSource.default.at(namespace)) - /** Load a configuration of type `A` from the given file. Note that standard configuration - * files are still loaded but can be overridden from the given configuration file - * - * @param path the path of the configuration file from which to load - * @return The returned action will complete with `A` if it is possible to create an instance of type - * `A` from the configuration file, or fail with a ConfigReaderException which in turn contains - * details on why it isn't possible - */ + /** + * Load a configuration of type `A` from the given file. Note that standard configuration + * files are still loaded but can be overridden from the given configuration file + * + * @param path the path of the configuration file from which to load + * @return The returned action will complete with `A` if it is possible to create an instance of type + * `A` from the configuration file, or fail with a ConfigReaderException which in turn contains + * details on why it isn't possible + */ @deprecated("Use `ConfigSource.default(ConfigSource.file(path)).loadF[F, A]` instead", "0.12.0") def loadConfigF[F[_], A]( path: Path )(implicit F: Sync[F], reader: Derivation[ConfigReader[A]], ct: ClassTag[A]): F[A] = loadF[F, A](ConfigSource.default(ConfigSource.file(path))) - /** Load a configuration of type `A` from the given file. Note that standard configuration - * files are still loaded but can be overridden from the given configuration file - * - * @param path the path of the configuration file from which to load - * @param namespace the base namespace from which the configuration should be load - * @return The returned action will complete with `A` if it is possible to create an instance of type - * `A` from the configuration file, or fail with a ConfigReaderException which in turn contains - * details on why it isn't possible - */ + /** + * Load a configuration of type `A` from the given file. Note that standard configuration + * files are still loaded but can be overridden from the given configuration file + * + * @param path the path of the configuration file from which to load + * @param namespace the base namespace from which the configuration should be load + * @return The returned action will complete with `A` if it is possible to create an instance of type + * `A` from the configuration file, or fail with a ConfigReaderException which in turn contains + * details on why it isn't possible + */ @deprecated("Use `ConfigSource.default(ConfigSource.file(path)).at(namespace).loadF[F, A]` instead", "0.12.0") def loadConfigF[F[_], A](path: Path, namespace: String)(implicit F: Sync[F], @@ -119,22 +126,24 @@ package object catseffect { ): F[A] = loadF[F, A](ConfigSource.default(ConfigSource.file(path)).at(namespace)) - /** Load a configuration of type `A` from the given `Config` - * @return The returned action will complete with `A` if it is possible to create an instance of type - * `A` from the configuration object, or fail with a ConfigReaderException which in turn contains - * details on why it isn't possible - */ + /** + * Load a configuration of type `A` from the given `Config` + * @return The returned action will complete with `A` if it is possible to create an instance of type + * `A` from the configuration object, or fail with a ConfigReaderException which in turn contains + * details on why it isn't possible + */ @deprecated("Use `ConfigSource.fromConfig(conf).loadF[F, A]` instead", "0.12.0") def loadConfigF[F[_], A]( conf: TypesafeConfig )(implicit F: Sync[F], reader: Derivation[ConfigReader[A]], ct: ClassTag[A]): F[A] = loadF[F, A](ConfigSource.fromConfig(conf)) - /** Load a configuration of type `A` from the given `Config` - * @return The returned action will complete with `A` if it is possible to create an instance of type - * `A` from the configuration object, or fail with a ConfigReaderException which in turn contains - * details on why it isn't possible - */ + /** + * Load a configuration of type `A` from the given `Config` + * @return The returned action will complete with `A` if it is possible to create an instance of type + * `A` from the configuration object, or fail with a ConfigReaderException which in turn contains + * details on why it isn't possible + */ @deprecated("Use `ConfigSource.fromConfig(conf).at(namespace).loadF[F, A]` instead", "0.12.0") def loadConfigF[F[_], A](conf: TypesafeConfig, namespace: String)(implicit F: Sync[F], @@ -143,14 +152,15 @@ package object catseffect { ): F[A] = loadF[F, A](ConfigSource.fromConfig(conf).at(namespace)) - /** Save the given configuration into a property file - * - * @param conf The configuration to save - * @param outputPath Where to write the configuration - * @param overrideOutputPath Override the path if it already exists - * @param options the config rendering options - * @return The return action will save out the supplied configuration upon invocation - */ + /** + * Save the given configuration into a property file + * + * @param conf The configuration to save + * @param outputPath Where to write the configuration + * @param overrideOutputPath Override the path if it already exists + * @param options the config rendering options + * @return The return action will save out the supplied configuration upon invocation + */ @deprecated( "Use `blockingSaveConfigAsPropertyFileF[IO, A](conf, outputPat, blocker, overrideOutputPath, options)` instead", "0.12.3" @@ -165,15 +175,16 @@ package object catseffect { pureconfig.saveConfigAsPropertyFile(conf, outputPath, overrideOutputPath, options) } - /** Save the given configuration into a property file - * - * @param conf The configuration to save - * @param outputPath Where to write the configuration - * @param blocker the blocking context which will be used to load the configuration. - * @param overrideOutputPath Override the path if it already exists - * @param options the config rendering options - * @return The return action will save out the supplied configuration upon invocation - */ + /** + * Save the given configuration into a property file + * + * @param conf The configuration to save + * @param outputPath Where to write the configuration + * @param blocker the blocking context which will be used to load the configuration. + * @param overrideOutputPath Override the path if it already exists + * @param options the config rendering options + * @return The return action will save out the supplied configuration upon invocation + */ def blockingSaveConfigAsPropertyFileF[F[_], A]( conf: A, outputPath: Path, @@ -208,13 +219,14 @@ package object catseffect { } } - /** Writes the configuration to the output stream and closes the stream - * - * @param conf The configuration to write - * @param outputStream The stream in which the configuration should be written - * @param options the config rendering options - * @return The return action will save out the supplied configuration upon invocation - */ + /** + * Writes the configuration to the output stream and closes the stream + * + * @param conf The configuration to write + * @param outputStream The stream in which the configuration should be written + * @param options the config rendering options + * @return The return action will save out the supplied configuration upon invocation + */ @deprecated("Use `blockingSaveConfigToStreamF[IO, A](conf, outputStream, blocker, options)` instead", "0.12.3") def saveConfigToStreamF[F[_], A]( conf: A, @@ -225,14 +237,15 @@ package object catseffect { pureconfig.saveConfigToStream(conf, outputStream, options) } - /** Writes the configuration to the output stream and closes the stream - * - * @param conf The configuration to write - * @param outputStream The stream in which the configuration should be written - * @param blocker the blocking context which will be used to load the configuration. - * @param options the config rendering options - * @return The return action will save out the supplied configuration upon invocation - */ + /** + * Writes the configuration to the output stream and closes the stream + * + * @param conf The configuration to write + * @param outputStream The stream in which the configuration should be written + * @param blocker the blocking context which will be used to load the configuration. + * @param options the config rendering options + * @return The return action will save out the supplied configuration upon invocation + */ def blockingSaveConfigToStreamF[F[_], A]( conf: A, outputStream: OutputStream, @@ -250,14 +263,15 @@ package object catseffect { } } - /** Loads `files` in order, allowing values in later files to backstop missing values from prior, and converts them into a `A`. - * - * This is a convenience method which enables having default configuration which backstops local configuration. - * - * Note: If an element of `files` references a file which doesn't exist or can't be read, it will silently be ignored. - * - * @param files Files ordered in decreasing priority containing part or all of a `A`. Must not be empty. - */ + /** + * Loads `files` in order, allowing values in later files to backstop missing values from prior, and converts them into a `A`. + * + * This is a convenience method which enables having default configuration which backstops local configuration. + * + * Note: If an element of `files` references a file which doesn't exist or can't be read, it will silently be ignored. + * + * @param files Files ordered in decreasing priority containing part or all of a `A`. Must not be empty. + */ @deprecated("Construct a custom `ConfigSource` pipeline instead", "0.12.0") def loadConfigFromFilesF[F[_], A]( files: NonEmptyList[Path] diff --git a/modules/cats/src/main/scala/pureconfig/module/cats/EmptyTraversableFound.scala b/modules/cats/src/main/scala/pureconfig/module/cats/EmptyTraversableFound.scala index af1afd107..a298d3650 100644 --- a/modules/cats/src/main/scala/pureconfig/module/cats/EmptyTraversableFound.scala +++ b/modules/cats/src/main/scala/pureconfig/module/cats/EmptyTraversableFound.scala @@ -2,10 +2,11 @@ package pureconfig.module.cats import pureconfig.error.FailureReason -/** A failure representing an unexpected empty traversable - * - * @param typ the type that was attempted to be converted to from an empty string - */ +/** + * A failure representing an unexpected empty traversable + * + * @param typ the type that was attempted to be converted to from an empty string + */ final case class EmptyTraversableFound(typ: String) extends FailureReason { def description = s"Empty collection found when trying to convert to $typ." } diff --git a/modules/cats/src/main/scala/pureconfig/module/cats/package.scala b/modules/cats/src/main/scala/pureconfig/module/cats/package.scala index f0982f4a9..f995a321f 100644 --- a/modules/cats/src/main/scala/pureconfig/module/cats/package.scala +++ b/modules/cats/src/main/scala/pureconfig/module/cats/package.scala @@ -10,8 +10,9 @@ import scala.collection.immutable.{SortedMap, SortedSet} import scala.language.higherKinds import scala.reflect.ClassTag -/** `ConfigReader` and `ConfigWriter` instances for cats data structures. - */ +/** + * `ConfigReader` and `ConfigWriter` instances for cats data structures. + */ package object cats { private[pureconfig] def fromNonEmpty[A, B]( diff --git a/modules/cats/src/main/scala/pureconfig/module/cats/syntax/package.scala b/modules/cats/src/main/scala/pureconfig/module/cats/syntax/package.scala index d15da58fc..a72e401c2 100644 --- a/modules/cats/src/main/scala/pureconfig/module/cats/syntax/package.scala +++ b/modules/cats/src/main/scala/pureconfig/module/cats/syntax/package.scala @@ -7,10 +7,11 @@ package object syntax { implicit class ConfigConvertFailureOps(val failures: ConfigReaderFailures) extends AnyVal { - /** Converts this into a non-empty list of failures. - * - * @return a non-empty list of failures. - */ + /** + * Converts this into a non-empty list of failures. + * + * @return a non-empty list of failures. + */ def toNonEmptyList: NonEmptyList[ConfigReaderFailure] = NonEmptyList(failures.head, failures.tail.toList) } } diff --git a/modules/fs2/src/main/scala/pureconfig/module/fs2/package.scala b/modules/fs2/src/main/scala/pureconfig/module/fs2/package.scala index 3a010f219..ccc82aecd 100644 --- a/modules/fs2/src/main/scala/pureconfig/module/fs2/package.scala +++ b/modules/fs2/src/main/scala/pureconfig/module/fs2/package.scala @@ -15,14 +15,15 @@ import pureconfig.{ConfigReader, ConfigSource, ConfigWriter, Derivation} package object fs2 { - /** Load a configuration of type `A` from the given byte stream. - * - * @param configStream a stream of bytes representing the contents of a configuration file - * @return The returned action will complete with `A` if it is possible to create an instance of type - * `A` from the configuration stream, or fail with a ConfigReaderException which in turn contains - * details on why it isn't possible - * It can also raise any exception that the stream can raise. - */ + /** + * Load a configuration of type `A` from the given byte stream. + * + * @param configStream a stream of bytes representing the contents of a configuration file + * @return The returned action will complete with `A` if it is possible to create an instance of type + * `A` from the configuration stream, or fail with a ConfigReaderException which in turn contains + * details on why it isn't possible + * It can also raise any exception that the stream can raise. + */ def streamConfig[F[_], A]( configStream: Stream[F, Byte] )(implicit F: Sync[F], reader: Derivation[ConfigReader[A]], ct: ClassTag[A]): F[A] = { @@ -36,12 +37,13 @@ package object fs2 { } yield a } - /** Writes the configuration to a fs2 byte stream - * - * @param config The configuration to write - * @param options the config rendering options - * @return the configuration as a stream of utf-8 bytes - */ + /** + * Writes the configuration to a fs2 byte stream + * + * @param config The configuration to write + * @param options the config rendering options + * @return the configuration as a stream of utf-8 bytes + */ def saveConfigToStream[F[_], A](config: A, options: ConfigRenderOptions = ConfigRenderOptions.defaults())(implicit writer: Derivation[ConfigWriter[A]] ): Stream[F, Byte] = { diff --git a/modules/generic-base/src/main/scala/pureconfig/generic/CoproductHint.scala b/modules/generic-base/src/main/scala/pureconfig/generic/CoproductHint.scala index 2431b4cb3..17ae1460d 100644 --- a/modules/generic-base/src/main/scala/pureconfig/generic/CoproductHint.scala +++ b/modules/generic-base/src/main/scala/pureconfig/generic/CoproductHint.scala @@ -11,51 +11,56 @@ import pureconfig.generic.error.{ } import pureconfig.syntax._ -/** A trait that can be implemented to disambiguate between the different options of a coproduct or sealed family. - * - * @tparam A the type of the coproduct or sealed family for which this hint applies - */ +/** + * A trait that can be implemented to disambiguate between the different options of a coproduct or sealed family. + * + * @tparam A the type of the coproduct or sealed family for which this hint applies + */ trait CoproductHint[A] { - /** Given a `ConfigCursor` for the sealed family, disambiguate and return what should be performed when trying to read - * one of the provided coproduct options. This method can decide either to: - * - use the `ConfigCursor` with a single option ([[CoproductHint.Use]]); - * - or attempt different options in a given order ([[CoproductHint.Attempt]]). - * - * This method can return a `Left` if the hint fails to produce a valid [[CoproductHint.Action]]. - * - * @param cursor a `ConfigCursor` at the sealed family option - * @param options the names of the coproduct options for the given type - * @return a `ConfigReader.Result` of [[CoproductHint.Action]] as defined above. - */ + /** + * Given a `ConfigCursor` for the sealed family, disambiguate and return what should be performed when trying to read + * one of the provided coproduct options. This method can decide either to: + * - use the `ConfigCursor` with a single option ([[CoproductHint.Use]]); + * - or attempt different options in a given order ([[CoproductHint.Attempt]]). + * + * This method can return a `Left` if the hint fails to produce a valid [[CoproductHint.Action]]. + * + * @param cursor a `ConfigCursor` at the sealed family option + * @param options the names of the coproduct options for the given type + * @return a `ConfigReader.Result` of [[CoproductHint.Action]] as defined above. + */ def from(cursor: ConfigCursor, options: Seq[String]): ConfigReader.Result[CoproductHint.Action] - /** Given the `ConfigValue` for a specific class or coproduct option, encode disambiguation information and return a - * config for the sealed family or coproduct. - * - * @param value the `ConfigValue` of the class or coproduct option - * @param name the name of the class or coproduct option - * @return the config for the sealed family or coproduct wrapped in a `Right`, or a `Left` with the failure if some - * error occurred. - */ + /** + * Given the `ConfigValue` for a specific class or coproduct option, encode disambiguation information and return a + * config for the sealed family or coproduct. + * + * @param value the `ConfigValue` of the class or coproduct option + * @param name the name of the class or coproduct option + * @return the config for the sealed family or coproduct wrapped in a `Right`, or a `Left` with the failure if some + * error occurred. + */ def to(value: ConfigValue, name: String): ConfigValue } -/** Hint where the options are disambiguated by a `key = "value"` field inside the config. - * - * This hint will cause derived `ConfigConvert` instance to fail to convert configs to objects if the object has a - * field with the same name as the disambiguation key. - * - * By default, the field value written is the class or coproduct option name converted to kebab case. This mapping can - * be changed by overriding the method `fieldValue` of this class. - */ +/** + * Hint where the options are disambiguated by a `key = "value"` field inside the config. + * + * This hint will cause derived `ConfigConvert` instance to fail to convert configs to objects if the object has a + * field with the same name as the disambiguation key. + * + * By default, the field value written is the class or coproduct option name converted to kebab case. This mapping can + * be changed by overriding the method `fieldValue` of this class. + */ class FieldCoproductHint[A](key: String) extends CoproductHint[A] { - /** Returns the field value for a class or coproduct option name. - * - * @param name the name of the class or coproduct option - * @return the field value associated with the given class or coproduct option name. - */ + /** + * Returns the field value for a class or coproduct option name. + * + * @param name the name of the class or coproduct option + * @return the field value associated with the given class or coproduct option name. + */ protected def fieldValue(name: String): String = FieldCoproductHint.defaultMapping(name) def from(cursor: ConfigCursor, options: Seq[String]): ConfigReader.Result[CoproductHint.Action] = { @@ -89,9 +94,10 @@ object FieldCoproductHint { val defaultMapping: String => String = ConfigFieldMapping(PascalCase, KebabCase) } -/** Hint where all coproduct options are tried in order. `from` will choose the first option able to deserialize - * the config without errors, while `to` will write the config as is, with no disambiguation information. - */ +/** + * Hint where all coproduct options are tried in order. `from` will choose the first option able to deserialize + * the config without errors, while `to` will write the config as is, with no disambiguation information. + */ class FirstSuccessCoproductHint[A] extends CoproductHint[A] { def from(cursor: ConfigCursor, options: Seq[String]): ConfigReader.Result[CoproductHint.Action] = Right( @@ -110,29 +116,33 @@ class FirstSuccessCoproductHint[A] extends CoproductHint[A] { object CoproductHint { - /** What should be done when reading a given coproduct option. - */ + /** + * What should be done when reading a given coproduct option. + */ sealed trait Action { - /** The `ConfigCursor` to use when trying to read the coproduct option. - */ + /** + * The `ConfigCursor` to use when trying to read the coproduct option. + */ def cursor: ConfigCursor } - /** An action to only use the provided `ConfigCursor` and not try other options. - * - * @param cursor the `ConfigCursor` to use when reading the coproduct option - * @param option the coproduct option to consider when reading from the provider cursor - */ + /** + * An action to only use the provided `ConfigCursor` and not try other options. + * + * @param cursor the `ConfigCursor` to use when reading the coproduct option + * @param option the coproduct option to consider when reading from the provider cursor + */ case class Use(cursor: ConfigCursor, option: String) extends Action - /** An action to attempt to use the provided coproduct options, in the specified order, stopping at the first one that - * reads successfully. - * - * @param cursor the `ConfigCursor` to use when reading the coproduct option - * @param options the coproduct options to attempt reading, in order - * @param combineFailures the function to combine all failures in case all attempts to read fail - */ + /** + * An action to attempt to use the provided coproduct options, in the specified order, stopping at the first one that + * reads successfully. + * + * @param cursor the `ConfigCursor` to use when reading the coproduct option + * @param options the coproduct options to attempt reading, in order + * @param combineFailures the function to combine all failures in case all attempts to read fail + */ case class Attempt( cursor: ConfigCursor, options: Seq[String], diff --git a/modules/generic-base/src/main/scala/pureconfig/generic/ProductHint.scala b/modules/generic-base/src/main/scala/pureconfig/generic/ProductHint.scala index 01f8655fb..64969fc28 100644 --- a/modules/generic-base/src/main/scala/pureconfig/generic/ProductHint.scala +++ b/modules/generic-base/src/main/scala/pureconfig/generic/ProductHint.scala @@ -4,39 +4,43 @@ import com.typesafe.config.ConfigValue import pureconfig._ import pureconfig.error.{ConfigReaderFailures, UnknownKey} -/** A trait that can be implemented to customize how case classes are read from and written to a config. - * - * @tparam A the type of case class for which this hint applies - */ +/** + * A trait that can be implemented to customize how case classes are read from and written to a config. + * + * @tparam A the type of case class for which this hint applies + */ trait ProductHint[A] { - /** Returns what should be used when attempting to read a case class field with name `fieldName` from the provided - * `ConfigObjectCursor`. - * - * @param cursor the cursor from which to read a value - * @param fieldName the name of the field in `T` - * @return a [[ProductHint.Action]] object that signals which cursor to use in order to read this field, the name - * of the corresponding field in the config object, whether the field should be removed from the object after - * read, and whether to use default values for this particular field. - */ + /** + * Returns what should be used when attempting to read a case class field with name `fieldName` from the provided + * `ConfigObjectCursor`. + * + * @param cursor the cursor from which to read a value + * @param fieldName the name of the field in `T` + * @return a [[ProductHint.Action]] object that signals which cursor to use in order to read this field, the name + * of the corresponding field in the config object, whether the field should be removed from the object after + * read, and whether to use default values for this particular field. + */ def from(cursor: ConfigObjectCursor, fieldName: String): ProductHint.Action - /** Returns optional failures given the provided `ConfigObjectCursor`. - * - * @param cursor a `ConfigObjectCursor` at the configuration root from where the product was read - * @param usedFields a set of all the used fields when reading the product - * @return an optional non-empty list of failures. - */ + /** + * Returns optional failures given the provided `ConfigObjectCursor`. + * + * @param cursor a `ConfigObjectCursor` at the configuration root from where the product was read + * @param usedFields a set of all the used fields when reading the product + * @return an optional non-empty list of failures. + */ def bottom(cursor: ConfigObjectCursor, usedFields: Set[String]): Option[ConfigReaderFailures] - /** Returns an optional key-value pair that should be used for the field with name `fieldName` in the `ConfigObject` - * representation of `T`. - * - * @param value the optional serialized value of the field - * @param fieldName the name of the field in `T` - * @return an optional key-value pair to be used in the `ConfigObject` representation of `T`. If `None`, the field is - * omitted from the `ConfigObject` representation. - */ + /** + * Returns an optional key-value pair that should be used for the field with name `fieldName` in the `ConfigObject` + * representation of `T`. + * + * @param value the optional serialized value of the field + * @param fieldName the name of the field in `T` + * @return an optional key-value pair to be used in the `ConfigObject` representation of `T`. If `None`, the field is + * omitted from the `ConfigObject` representation. + */ def to(value: Option[ConfigValue], fieldName: String): Option[(String, ConfigValue)] } @@ -76,32 +80,37 @@ private[pureconfig] case class ProductHintImpl[A]( object ProductHint { - /** What should be done when attempting to read a given field from a product. - */ + /** + * What should be done when attempting to read a given field from a product. + */ sealed trait Action { - /** The `ConfigCursor` to use when trying to read the field. - */ + /** + * The `ConfigCursor` to use when trying to read the field. + */ def cursor: ConfigCursor - /** The name of the field in the `ConfigObject` representation of the product. - */ + /** + * The name of the field in the `ConfigObject` representation of the product. + */ def field: String } - /** An action to use the provided `ConfigCursor` when trying to read a given field. - * - * @param cursor the `ConfigCursor` to use when trying to read the field - * @param field the name of the field in the `ConfigObject` representation of the product - */ + /** + * An action to use the provided `ConfigCursor` when trying to read a given field. + * + * @param cursor the `ConfigCursor` to use when trying to read the field + * @param field the name of the field in the `ConfigObject` representation of the product + */ case class Use(cursor: ConfigCursor, field: String) extends Action - /** An action to either use the provided `ConfigCursor` (if it isn't null or undefined) or fallback to the default - * value in the product's constructor. - * - * @param cursor the `ConfigCursor` to use when trying to read the field - * @param field the name of the field in the `ConfigObject` representation of the product - */ + /** + * An action to either use the provided `ConfigCursor` (if it isn't null or undefined) or fallback to the default + * value in the product's constructor. + * + * @param cursor the `ConfigCursor` to use when trying to read the field + * @param field the name of the field in the `ConfigObject` representation of the product + */ case class UseOrDefault(cursor: ConfigCursor, field: String) extends Action def apply[A]( diff --git a/modules/generic-base/src/main/scala/pureconfig/generic/error/CoproductHintException.scala b/modules/generic-base/src/main/scala/pureconfig/generic/error/CoproductHintException.scala index b81f4b823..b348dba0e 100644 --- a/modules/generic-base/src/main/scala/pureconfig/generic/error/CoproductHintException.scala +++ b/modules/generic-base/src/main/scala/pureconfig/generic/error/CoproductHintException.scala @@ -2,10 +2,11 @@ package pureconfig.generic.error import pureconfig.error.FailureReason -/** An exception to be thrown on operations inside CoproductHints. - * - * @param failure the reason for the exception - */ +/** + * An exception to be thrown on operations inside CoproductHints. + * + * @param failure the reason for the exception + */ final case class CoproductHintException(failure: FailureReason) extends RuntimeException { override def getMessage: String = failure.description } diff --git a/modules/generic-base/src/main/scala/pureconfig/generic/error/InvalidCoproductOption.scala b/modules/generic-base/src/main/scala/pureconfig/generic/error/InvalidCoproductOption.scala index 0342ca7e2..c9330d924 100644 --- a/modules/generic-base/src/main/scala/pureconfig/generic/error/InvalidCoproductOption.scala +++ b/modules/generic-base/src/main/scala/pureconfig/generic/error/InvalidCoproductOption.scala @@ -2,11 +2,12 @@ package pureconfig.generic.error import pureconfig.error.FailureReason -/** A failure reason given when a provided coproduct option is invalid. This likely signals a bug in a CoproductHint - * implementation, since the provided option isn't a valid one for the CoproductHint's type. - * - * @param option the coproduct option that is invalid - */ +/** + * A failure reason given when a provided coproduct option is invalid. This likely signals a bug in a CoproductHint + * implementation, since the provided option isn't a valid one for the CoproductHint's type. + * + * @param option the coproduct option that is invalid + */ final case class InvalidCoproductOption(option: String) extends FailureReason { def description = s"""|The provided option '$option' is invalid for the CoproductHint's type. There's likely a bug in the diff --git a/modules/generic-base/src/main/scala/pureconfig/generic/error/NoValidCoproductOptionFound.scala b/modules/generic-base/src/main/scala/pureconfig/generic/error/NoValidCoproductOptionFound.scala index 2a35366c2..a325b5013 100644 --- a/modules/generic-base/src/main/scala/pureconfig/generic/error/NoValidCoproductOptionFound.scala +++ b/modules/generic-base/src/main/scala/pureconfig/generic/error/NoValidCoproductOptionFound.scala @@ -3,11 +3,12 @@ package pureconfig.generic.error import com.typesafe.config.{ConfigRenderOptions, ConfigValue} import pureconfig.error.{ConfigReaderFailures, FailureReason} -/** A failure reason given when a valid option for a coproduct cannot be found. - * - * @param value the ConfigValue that was unable to be mapped to a coproduct option - * @param optionFailures the failures produced when attempting to read coproduct options - */ +/** + * A failure reason given when a valid option for a coproduct cannot be found. + * + * @param value the ConfigValue that was unable to be mapped to a coproduct option + * @param optionFailures the failures produced when attempting to read coproduct options + */ final case class NoValidCoproductOptionFound(value: ConfigValue, optionFailures: Seq[(String, ConfigReaderFailures)]) extends FailureReason { def description = { diff --git a/modules/generic-base/src/main/scala/pureconfig/generic/error/UnexpectedValueForFieldCoproductHint.scala b/modules/generic-base/src/main/scala/pureconfig/generic/error/UnexpectedValueForFieldCoproductHint.scala index c708ccfb0..b320799d4 100644 --- a/modules/generic-base/src/main/scala/pureconfig/generic/error/UnexpectedValueForFieldCoproductHint.scala +++ b/modules/generic-base/src/main/scala/pureconfig/generic/error/UnexpectedValueForFieldCoproductHint.scala @@ -3,11 +3,12 @@ package pureconfig.generic.error import com.typesafe.config.{ConfigRenderOptions, ConfigValue} import pureconfig.error.FailureReason -/** A failure reason given when an unknown value was found in the discriminating field of a config value, when using a - * `FieldCoproductHint`. - * - * @param value the value found in the discriminating field of a config value - */ +/** + * A failure reason given when an unknown value was found in the discriminating field of a config value, when using a + * `FieldCoproductHint`. + * + * @param value the value found in the discriminating field of a config value + */ final case class UnexpectedValueForFieldCoproductHint(value: ConfigValue) extends FailureReason { def description = s"Unexpected value ${value.render(ConfigRenderOptions.concise())} found. Note that the default transformation " + diff --git a/modules/generic/src/main/scala/pureconfig/generic/CoproductConfigWriter.scala b/modules/generic/src/main/scala/pureconfig/generic/CoproductConfigWriter.scala index feda04465..040a8ef7b 100644 --- a/modules/generic/src/main/scala/pureconfig/generic/CoproductConfigWriter.scala +++ b/modules/generic/src/main/scala/pureconfig/generic/CoproductConfigWriter.scala @@ -5,11 +5,12 @@ import pureconfig.{ConfigWriter, Derivation} import shapeless.labelled._ import shapeless._ -/** A `ConfigWriter` for generic representations of coproducts. - * - * @tparam Original the original type for which `Repr` is the coproduct representation - * @tparam Repr the generic representation - */ +/** + * A `ConfigWriter` for generic representations of coproducts. + * + * @tparam Original the original type for which `Repr` is the coproduct representation + * @tparam Repr the generic representation + */ private[generic] trait CoproductConfigWriter[Original, Repr <: Coproduct] extends ConfigWriter[Repr] object CoproductConfigWriter { diff --git a/modules/generic/src/main/scala/pureconfig/generic/CoproductReaderOptions.scala b/modules/generic/src/main/scala/pureconfig/generic/CoproductReaderOptions.scala index f256f4e2a..9aab13c24 100644 --- a/modules/generic/src/main/scala/pureconfig/generic/CoproductReaderOptions.scala +++ b/modules/generic/src/main/scala/pureconfig/generic/CoproductReaderOptions.scala @@ -4,8 +4,9 @@ import pureconfig._ import shapeless._ import shapeless.labelled._ -/** A typeclass to collect the `ConfigReader` options for a given coproduct, indexed by the coproduct name. - */ +/** + * A typeclass to collect the `ConfigReader` options for a given coproduct, indexed by the coproduct name. + */ private[generic] trait CoproductReaderOptions[Repr <: Coproduct] { def options: Map[String, ConfigReader[Repr]] } diff --git a/modules/generic/src/main/scala/pureconfig/generic/DerivedConfigReader.scala b/modules/generic/src/main/scala/pureconfig/generic/DerivedConfigReader.scala index 057eb3fb0..7c25427c6 100644 --- a/modules/generic/src/main/scala/pureconfig/generic/DerivedConfigReader.scala +++ b/modules/generic/src/main/scala/pureconfig/generic/DerivedConfigReader.scala @@ -5,10 +5,11 @@ import pureconfig.error.ConfigReaderFailures import pureconfig.generic.error.InvalidCoproductOption import shapeless._ -/** A `ConfigReader` derived with `shapeless`. - * - * @tparam A the type of objects readable by this `ConfigReader` - */ +/** + * A `ConfigReader` derived with `shapeless`. + * + * @tparam A the type of objects readable by this `ConfigReader` + */ trait DerivedConfigReader[A] extends ConfigReader[A] object DerivedConfigReader extends DerivedConfigReader1 { diff --git a/modules/generic/src/main/scala/pureconfig/generic/DerivedConfigWriter.scala b/modules/generic/src/main/scala/pureconfig/generic/DerivedConfigWriter.scala index a5bd2ce64..c6c570201 100644 --- a/modules/generic/src/main/scala/pureconfig/generic/DerivedConfigWriter.scala +++ b/modules/generic/src/main/scala/pureconfig/generic/DerivedConfigWriter.scala @@ -4,10 +4,11 @@ import com.typesafe.config._ import pureconfig._ import shapeless._ -/** A `ConfigWriter` derived with `shapeless`. - * - * @tparam A the type of objects writable by this `ConfigWriter` - */ +/** + * A `ConfigWriter` derived with `shapeless`. + * + * @tparam A the type of objects writable by this `ConfigWriter` + */ trait DerivedConfigWriter[A] extends ConfigWriter[A] object DerivedConfigWriter extends DerivedConfigWriter1 { diff --git a/modules/generic/src/main/scala/pureconfig/generic/EnumCoproductHint.scala b/modules/generic/src/main/scala/pureconfig/generic/EnumCoproductHint.scala index 664fda391..4be476109 100644 --- a/modules/generic/src/main/scala/pureconfig/generic/EnumCoproductHint.scala +++ b/modules/generic/src/main/scala/pureconfig/generic/EnumCoproductHint.scala @@ -7,22 +7,24 @@ import pureconfig.generic.CoproductHint.Use import pureconfig.generic.error.{CoproductHintException, NoValidCoproductOptionFound} import pureconfig.syntax._ -/** Hint applicable to sealed families of case objects where objects are written and read as strings with their type - * names. Trying to read or write values that are not case objects results in failure. - * - * @tparam A the type of the coproduct or sealed family for which this hint applies - */ +/** + * Hint applicable to sealed families of case objects where objects are written and read as strings with their type + * names. Trying to read or write values that are not case objects results in failure. + * + * @tparam A the type of the coproduct or sealed family for which this hint applies + */ @deprecated( "Use `pureconfig.generic.semiauto.deriveEnumerationReader[A]`, `pureconfig.generic.semiauto.deriveEnumerationWriter[A]` and `pureconfig.generic.semiauto.deriveEnumerationConvert[A]` instead", "0.11.0" ) class EnumCoproductHint[A] extends CoproductHint[A] { - /** Returns the field value for a class or coproduct option name. - * - * @param name the name of the class or coproduct option - * @return the field value associated with the given class or coproduct option name. - */ + /** + * Returns the field value for a class or coproduct option name. + * + * @param name the name of the class or coproduct option + * @return the field value associated with the given class or coproduct option name. + */ protected def fieldValue(name: String): String = name.toLowerCase def from(cursor: ConfigCursor, options: Seq[String]): ConfigReader.Result[CoproductHint.Action] = diff --git a/modules/generic/src/main/scala/pureconfig/generic/EnumerationConfigReaderBuilder.scala b/modules/generic/src/main/scala/pureconfig/generic/EnumerationConfigReaderBuilder.scala index ca3d35ad0..4d536e5bb 100644 --- a/modules/generic/src/main/scala/pureconfig/generic/EnumerationConfigReaderBuilder.scala +++ b/modules/generic/src/main/scala/pureconfig/generic/EnumerationConfigReaderBuilder.scala @@ -6,11 +6,12 @@ import pureconfig.{ConfigCursor, ConfigReader} import shapeless._ import shapeless.labelled._ -/** A type class to build `ConfigReader`s for sealed families of case objects where each type is encoded as a - * `ConfigString` based on the type name. - * - * @tparam A the type of objects capable of being read as an enumeration - */ +/** + * A type class to build `ConfigReader`s for sealed families of case objects where each type is encoded as a + * `ConfigString` based on the type name. + * + * @tparam A the type of objects capable of being read as an enumeration + */ trait EnumerationConfigReaderBuilder[A] { def build(transformName: String => String): ConfigReader[A] } diff --git a/modules/generic/src/main/scala/pureconfig/generic/EnumerationConfigWriterBuilder.scala b/modules/generic/src/main/scala/pureconfig/generic/EnumerationConfigWriterBuilder.scala index 3ee5e17ea..c9d01cd8a 100644 --- a/modules/generic/src/main/scala/pureconfig/generic/EnumerationConfigWriterBuilder.scala +++ b/modules/generic/src/main/scala/pureconfig/generic/EnumerationConfigWriterBuilder.scala @@ -5,11 +5,12 @@ import pureconfig.ConfigWriter import shapeless._ import shapeless.labelled._ -/** A type class to build `ConfigWriter`s for sealed families of case objects where each type is encoded as a - * `ConfigString` based on the type name. - * - * @tparam A the type of objects capable of being written as an enumeration - */ +/** + * A type class to build `ConfigWriter`s for sealed families of case objects where each type is encoded as a + * `ConfigString` based on the type name. + * + * @tparam A the type of objects capable of being written as an enumeration + */ trait EnumerationConfigWriterBuilder[A] { def build(transformName: String => String): ConfigWriter[A] } diff --git a/modules/generic/src/main/scala/pureconfig/generic/ExportMacros.scala b/modules/generic/src/main/scala/pureconfig/generic/ExportMacros.scala index ff88fe8b0..b5de91df0 100644 --- a/modules/generic/src/main/scala/pureconfig/generic/ExportMacros.scala +++ b/modules/generic/src/main/scala/pureconfig/generic/ExportMacros.scala @@ -4,8 +4,9 @@ import scala.reflect.macros.blackbox import pureconfig._ -/** Macros used to circumvent divergence checker restrictions in the compiler. - */ +/** + * Macros used to circumvent divergence checker restrictions in the compiler. + */ class ExportMacros(val c: blackbox.Context) { import c.universe._ diff --git a/modules/generic/src/main/scala/pureconfig/generic/MapShapedReader.scala b/modules/generic/src/main/scala/pureconfig/generic/MapShapedReader.scala index ee07a025a..50c706c6e 100644 --- a/modules/generic/src/main/scala/pureconfig/generic/MapShapedReader.scala +++ b/modules/generic/src/main/scala/pureconfig/generic/MapShapedReader.scala @@ -6,13 +6,14 @@ import pureconfig.generic.ProductHint.UseOrDefault import shapeless._ import shapeless.labelled.{FieldType, field} -/** A specialized reader for generic representations that reads values in the shape of a config object, and is capable - * of handling default values. - * - * @tparam Original the original type for which `Repr` is a generic sub-representation - * @tparam Repr the generic representation - * @tparam DefaultRepr the default representation of the original type - */ +/** + * A specialized reader for generic representations that reads values in the shape of a config object, and is capable + * of handling default values. + * + * @tparam Original the original type for which `Repr` is a generic sub-representation + * @tparam Repr the generic representation + * @tparam DefaultRepr the default representation of the original type + */ private[generic] trait MapShapedReader[Original, Repr, DefaultRepr] { def from(cur: ConfigObjectCursor, default: DefaultRepr, usedFields: Set[String]): ConfigReader.Result[Repr] } diff --git a/modules/generic/src/main/scala/pureconfig/generic/MapShapedWriter.scala b/modules/generic/src/main/scala/pureconfig/generic/MapShapedWriter.scala index 34ed474c2..c1a5d29f4 100644 --- a/modules/generic/src/main/scala/pureconfig/generic/MapShapedWriter.scala +++ b/modules/generic/src/main/scala/pureconfig/generic/MapShapedWriter.scala @@ -7,11 +7,12 @@ import pureconfig._ import shapeless._ import shapeless.labelled.FieldType -/** A `ConfigWriter` for generic representations that writes values in the shape of a config object. - * - * @tparam Original the original type for which `Repr` is a generic sub-representation - * @tparam Repr the generic representation - */ +/** + * A `ConfigWriter` for generic representations that writes values in the shape of a config object. + * + * @tparam Original the original type for which `Repr` is a generic sub-representation + * @tparam Repr the generic representation + */ private[generic] trait MapShapedWriter[Original, Repr] extends ConfigWriter[Repr] object MapShapedWriter { diff --git a/modules/generic/src/main/scala/pureconfig/generic/SeqShapedReader.scala b/modules/generic/src/main/scala/pureconfig/generic/SeqShapedReader.scala index ba81b1c69..ac989afd7 100644 --- a/modules/generic/src/main/scala/pureconfig/generic/SeqShapedReader.scala +++ b/modules/generic/src/main/scala/pureconfig/generic/SeqShapedReader.scala @@ -5,10 +5,11 @@ import pureconfig.error._ import shapeless._ import shapeless.ops.hlist.HKernelAux -/** A `ConfigReader` for generic representations that reads values in the shape of a sequence. - * - * @tparam Repr the generic representation - */ +/** + * A `ConfigReader` for generic representations that reads values in the shape of a sequence. + * + * @tparam Repr the generic representation + */ private[generic] trait SeqShapedReader[Repr] extends ConfigReader[Repr] object SeqShapedReader { diff --git a/modules/generic/src/main/scala/pureconfig/generic/SeqShapedWriter.scala b/modules/generic/src/main/scala/pureconfig/generic/SeqShapedWriter.scala index 02127053c..d5e8a087c 100644 --- a/modules/generic/src/main/scala/pureconfig/generic/SeqShapedWriter.scala +++ b/modules/generic/src/main/scala/pureconfig/generic/SeqShapedWriter.scala @@ -6,10 +6,11 @@ import com.typesafe.config.{ConfigList, ConfigValue, ConfigValueFactory} import pureconfig.{ConfigWriter, Derivation} import shapeless._ -/** A `ConfigWriter` for generic representations that writes values in the shape of a sequence. - * - * @tparam Repr the generic representation - */ +/** + * A `ConfigWriter` for generic representations that writes values in the shape of a sequence. + * + * @tparam Repr the generic representation + */ private[generic] trait SeqShapedWriter[Repr] extends ConfigWriter[Repr] object SeqShapedWriter { diff --git a/modules/generic/src/main/scala/pureconfig/generic/auto.scala b/modules/generic/src/main/scala/pureconfig/generic/auto.scala index 678cd6e05..2095c82d5 100644 --- a/modules/generic/src/main/scala/pureconfig/generic/auto.scala +++ b/modules/generic/src/main/scala/pureconfig/generic/auto.scala @@ -4,9 +4,10 @@ import scala.language.experimental.macros import pureconfig._ -/** An object that, when imported, provides implicit `ConfigReader` and `ConfigWriter` instances for value classes, - * tuples, case classes and sealed traits. - */ +/** + * An object that, when imported, provides implicit `ConfigReader` and `ConfigWriter` instances for value classes, + * tuples, case classes and sealed traits. + */ object auto { implicit def exportReader[A]: Exported[ConfigReader[A]] = macro ExportMacros.exportDerivedReader[A] implicit def exportWriter[A]: Exported[ConfigWriter[A]] = macro ExportMacros.exportDerivedWriter[A] diff --git a/modules/generic/src/main/scala/pureconfig/generic/hlist.scala b/modules/generic/src/main/scala/pureconfig/generic/hlist.scala index 38d477712..fb9c299c9 100644 --- a/modules/generic/src/main/scala/pureconfig/generic/hlist.scala +++ b/modules/generic/src/main/scala/pureconfig/generic/hlist.scala @@ -2,8 +2,9 @@ package pureconfig.generic import pureconfig.{ConfigReader, ConfigWriter} -/** An object that, when imported, provides readers and writers for shapeless `HList` instances. - */ +/** + * An object that, when imported, provides readers and writers for shapeless `HList` instances. + */ object hlist { implicit def hListReader[HL](implicit seqReader: SeqShapedReader[HL]): ConfigReader[HL] = seqReader implicit def hListWriter[HL](implicit seqWriter: SeqShapedWriter[HL]): ConfigWriter[HL] = seqWriter diff --git a/modules/generic/src/main/scala/pureconfig/generic/semiauto.scala b/modules/generic/src/main/scala/pureconfig/generic/semiauto.scala index 2986a229b..091adc849 100644 --- a/modules/generic/src/main/scala/pureconfig/generic/semiauto.scala +++ b/modules/generic/src/main/scala/pureconfig/generic/semiauto.scala @@ -3,9 +3,10 @@ package pureconfig.generic import pureconfig._ import shapeless._ -/** An object that provides methods for deriving `ConfigReader` and `ConfigWriter` instances on demand for value - * classes, tuples, case classes and sealed traits. - */ +/** + * An object that provides methods for deriving `ConfigReader` and `ConfigWriter` instances on demand for value + * classes, tuples, case classes and sealed traits. + */ object semiauto { final def deriveReader[A](implicit reader: Lazy[DerivedConfigReader[A]]): ConfigReader[A] = reader.value final def deriveWriter[A](implicit writer: Lazy[DerivedConfigWriter[A]]): ConfigWriter[A] = writer.value @@ -16,48 +17,54 @@ object semiauto { ): ConfigConvert[A] = ConfigConvert.fromReaderAndWriter(Derivation.Successful(reader.value), Derivation.Successful(writer.value)) - /** Derive a `ConfigReader` for a sealed family of case objects where each type is encoded as the kebab-case - * representation of the type name. - */ + /** + * Derive a `ConfigReader` for a sealed family of case objects where each type is encoded as the kebab-case + * representation of the type name. + */ final def deriveEnumerationReader[A](implicit readerBuilder: Lazy[EnumerationConfigReaderBuilder[A]] ): ConfigReader[A] = deriveEnumerationReader(ConfigFieldMapping(PascalCase, KebabCase)) - /** Derive a `ConfigWriter` for a sealed family of case objects where each type is encoded as the kebab-case - * representation of the type name. - */ + /** + * Derive a `ConfigWriter` for a sealed family of case objects where each type is encoded as the kebab-case + * representation of the type name. + */ final def deriveEnumerationWriter[A](implicit writerBuilder: Lazy[EnumerationConfigWriterBuilder[A]] ): ConfigWriter[A] = deriveEnumerationWriter(ConfigFieldMapping(PascalCase, KebabCase)) - /** Derive a `ConfigConvert` for a sealed family of case objects where each type is encoded as the kebab-case - * representation of the type name. - */ + /** + * Derive a `ConfigConvert` for a sealed family of case objects where each type is encoded as the kebab-case + * representation of the type name. + */ final def deriveEnumerationConvert[A](implicit readerBuilder: Lazy[EnumerationConfigReaderBuilder[A]], writerBuilder: Lazy[EnumerationConfigWriterBuilder[A]] ): ConfigConvert[A] = deriveEnumerationConvert(ConfigFieldMapping(PascalCase, KebabCase)) - /** Derive a `ConfigReader` for a sealed family of case objects where each type is encoded with the `transformName` - * function applied to the type name. - */ + /** + * Derive a `ConfigReader` for a sealed family of case objects where each type is encoded with the `transformName` + * function applied to the type name. + */ final def deriveEnumerationReader[A](transformName: String => String)(implicit readerBuilder: Lazy[EnumerationConfigReaderBuilder[A]] ): ConfigReader[A] = readerBuilder.value.build(transformName) - /** Derive a `ConfigWriter` for a sealed family of case objects where each type is encoded with the `transformName` - * function applied to the type name. - */ + /** + * Derive a `ConfigWriter` for a sealed family of case objects where each type is encoded with the `transformName` + * function applied to the type name. + */ final def deriveEnumerationWriter[A](transformName: String => String)(implicit writerBuilder: Lazy[EnumerationConfigWriterBuilder[A]] ): ConfigWriter[A] = writerBuilder.value.build(transformName) - /** Derive a `ConfigConvert` for a sealed family of case objects where each type is encoded with the `transformName` - * function applied to the type name. - */ + /** + * Derive a `ConfigConvert` for a sealed family of case objects where each type is encoded with the `transformName` + * function applied to the type name. + */ final def deriveEnumerationConvert[A](transformName: String => String)(implicit readerBuilder: Lazy[EnumerationConfigReaderBuilder[A]], writerBuilder: Lazy[EnumerationConfigWriterBuilder[A]] diff --git a/modules/hadoop/src/main/scala/pureconfig/module/hadoop/package.scala b/modules/hadoop/src/main/scala/pureconfig/module/hadoop/package.scala index 9a2e7b8d9..959a68732 100644 --- a/modules/hadoop/src/main/scala/pureconfig/module/hadoop/package.scala +++ b/modules/hadoop/src/main/scala/pureconfig/module/hadoop/package.scala @@ -5,8 +5,9 @@ import pureconfig.ConfigConvert import scala.util.Try -/** `ConfigConvert` instances for Hadoop data structures. - */ +/** + * `ConfigConvert` instances for Hadoop data structures. + */ package object hadoop { implicit val pathConvert: ConfigConvert[Path] = diff --git a/modules/javax/src/main/scala/pureconfig/module/javax/package.scala b/modules/javax/src/main/scala/pureconfig/module/javax/package.scala index 7f9a21733..40701228a 100644 --- a/modules/javax/src/main/scala/pureconfig/module/javax/package.scala +++ b/modules/javax/src/main/scala/pureconfig/module/javax/package.scala @@ -5,8 +5,9 @@ import _root_.javax.security.auth.x500.X500Principal import pureconfig.ConfigConvert import pureconfig.ConfigConvert.{catchReadError, viaString} -/** ConfigConvert instances for javax value classes. - */ +/** + * ConfigConvert instances for javax value classes. + */ package object javax { implicit val readKerberosPrincipal: ConfigConvert[KerberosPrincipal] = viaString[KerberosPrincipal](catchReadError(s => new KerberosPrincipal(s)), _.toString) diff --git a/modules/joda/src/main/scala/pureconfig/module/joda/configurable/package.scala b/modules/joda/src/main/scala/pureconfig/module/joda/configurable/package.scala index d27ab3f20..b49a4b286 100644 --- a/modules/joda/src/main/scala/pureconfig/module/joda/configurable/package.scala +++ b/modules/joda/src/main/scala/pureconfig/module/joda/configurable/package.scala @@ -5,19 +5,20 @@ import org.joda.time.format._ import pureconfig.ConfigConvert import pureconfig.ConfigConvert._ -/** Provides methods that create [[ConfigConvert]] instances from a set of parameters used to configure the instances. - * - * The result of calling one of the methods can be assigned to an `implicit val` so that `pureconfig` will be able to - * use it: - * {{{ - * implicit val localDateConfigConvert = makeLocalDateConfigConvert(ISODateTimeFormat) - * }}} - * - * @example we cannot provide a [[ConfigConvert]] for [[org.joda.time.LocalDate]] because traditionally there are many different - * [[org.joda.time.format.DateTimeFormatter]]s to parse a [[org.joda.time.LocalDate]] from a [[java.lang.String]]. This package - * provides a method that takes an input [[org.joda.time.format.DateTimeFormatter]] and returns a [[ConfigConvert]] for - * [[org.joda.time.LocalDate]] which will use that [[org.joda.time.format.DateTimeFormatter]] to parse a [[org.joda.time.LocalDate]]. - */ +/** + * Provides methods that create [[ConfigConvert]] instances from a set of parameters used to configure the instances. + * + * The result of calling one of the methods can be assigned to an `implicit val` so that `pureconfig` will be able to + * use it: + * {{{ + * implicit val localDateConfigConvert = makeLocalDateConfigConvert(ISODateTimeFormat) + * }}} + * + * @example we cannot provide a [[ConfigConvert]] for [[org.joda.time.LocalDate]] because traditionally there are many different + * [[org.joda.time.format.DateTimeFormatter]]s to parse a [[org.joda.time.LocalDate]] from a [[java.lang.String]]. This package + * provides a method that takes an input [[org.joda.time.format.DateTimeFormatter]] and returns a [[ConfigConvert]] for + * [[org.joda.time.LocalDate]] which will use that [[org.joda.time.format.DateTimeFormatter]] to parse a [[org.joda.time.LocalDate]]. + */ package object configurable { def dateTimeConfigConvert(formatter: DateTimeFormatter): ConfigConvert[DateTime] = viaNonEmptyString[DateTime](catchReadError(DateTime.parse(_, formatter)), formatter.print) diff --git a/modules/magnolia/src/main/scala/pureconfig/module/magnolia/EnumerationConfigReaderBuilder.scala b/modules/magnolia/src/main/scala/pureconfig/module/magnolia/EnumerationConfigReaderBuilder.scala index 9fb0d318b..e85522a8a 100644 --- a/modules/magnolia/src/main/scala/pureconfig/module/magnolia/EnumerationConfigReaderBuilder.scala +++ b/modules/magnolia/src/main/scala/pureconfig/module/magnolia/EnumerationConfigReaderBuilder.scala @@ -9,11 +9,12 @@ import pureconfig.error.CannotConvert import pureconfig.generic.error.NoValidCoproductOptionFound import pureconfig.{ConfigCursor, ConfigReader} -/** A type class to build `ConfigReader`s for sealed families of case objects where each type is encoded as a - * `ConfigString` based on the type name. - * - * @tparam A the type of objects capable of being read as an enumeration - */ +/** + * A type class to build `ConfigReader`s for sealed families of case objects where each type is encoded as a + * `ConfigString` based on the type name. + * + * @tparam A the type of objects capable of being read as an enumeration + */ private[magnolia] trait EnumerationConfigReaderBuilder[A] { def build(transformName: String => String): ConfigReader[A] } diff --git a/modules/magnolia/src/main/scala/pureconfig/module/magnolia/EnumerationConfigWriterBuilder.scala b/modules/magnolia/src/main/scala/pureconfig/module/magnolia/EnumerationConfigWriterBuilder.scala index c2f2ceac7..2cfd8a027 100644 --- a/modules/magnolia/src/main/scala/pureconfig/module/magnolia/EnumerationConfigWriterBuilder.scala +++ b/modules/magnolia/src/main/scala/pureconfig/module/magnolia/EnumerationConfigWriterBuilder.scala @@ -6,11 +6,12 @@ import com.typesafe.config.{ConfigValue, ConfigValueFactory} import magnolia._ import pureconfig.ConfigWriter -/** A type class to build `ConfigWriter`s for sealed families of case objects where each type is encoded as a - * `ConfigString` based on the type name. - * - * @tparam A the type of objects capable of being written as an enumeration - */ +/** + * A type class to build `ConfigWriter`s for sealed families of case objects where each type is encoded as a + * `ConfigString` based on the type name. + * + * @tparam A the type of objects capable of being written as an enumeration + */ private[magnolia] trait EnumerationConfigWriterBuilder[A] { def build(transformName: String => String): ConfigWriter[A] } diff --git a/modules/magnolia/src/main/scala/pureconfig/module/magnolia/MagnoliaConfigReader.scala b/modules/magnolia/src/main/scala/pureconfig/module/magnolia/MagnoliaConfigReader.scala index ab18058a4..eb182d640 100644 --- a/modules/magnolia/src/main/scala/pureconfig/module/magnolia/MagnoliaConfigReader.scala +++ b/modules/magnolia/src/main/scala/pureconfig/module/magnolia/MagnoliaConfigReader.scala @@ -7,8 +7,9 @@ import pureconfig.generic.ProductHint.UseOrDefault import pureconfig.generic.error.InvalidCoproductOption import pureconfig.generic.{CoproductHint, ProductHint} -/** An object containing Magnolia `combine` and `dispatch` methods to generate `ConfigReader` instances. - */ +/** + * An object containing Magnolia `combine` and `dispatch` methods to generate `ConfigReader` instances. + */ object MagnoliaConfigReader { def combine[A](ctx: CaseClass[ConfigReader, A])(implicit hint: ProductHint[A]): ConfigReader[A] = diff --git a/modules/magnolia/src/main/scala/pureconfig/module/magnolia/MagnoliaConfigWriter.scala b/modules/magnolia/src/main/scala/pureconfig/module/magnolia/MagnoliaConfigWriter.scala index 3f8ac6def..378ba49dc 100644 --- a/modules/magnolia/src/main/scala/pureconfig/module/magnolia/MagnoliaConfigWriter.scala +++ b/modules/magnolia/src/main/scala/pureconfig/module/magnolia/MagnoliaConfigWriter.scala @@ -8,8 +8,9 @@ import com.typesafe.config.{ConfigValue, ConfigValueFactory} import pureconfig._ import pureconfig.generic.{CoproductHint, ProductHint} -/** An object containing Magnolia `combine` and `dispatch` methods to generate `ConfigWriter` instances. - */ +/** + * An object containing Magnolia `combine` and `dispatch` methods to generate `ConfigWriter` instances. + */ object MagnoliaConfigWriter { def combine[A](ctx: CaseClass[ConfigWriter, A])(implicit hint: ProductHint[A]): ConfigWriter[A] = diff --git a/modules/magnolia/src/main/scala/pureconfig/module/magnolia/auto/reader.scala b/modules/magnolia/src/main/scala/pureconfig/module/magnolia/auto/reader.scala index e73ed7b7a..795f2427d 100644 --- a/modules/magnolia/src/main/scala/pureconfig/module/magnolia/auto/reader.scala +++ b/modules/magnolia/src/main/scala/pureconfig/module/magnolia/auto/reader.scala @@ -7,9 +7,10 @@ import pureconfig.{ConfigReader, Exported} import pureconfig.generic.{CoproductHint, ProductHint} import pureconfig.module.magnolia.{ExportedMagnolia, MagnoliaConfigReader} -/** An object that, when imported, provides implicit `ConfigReader` instances for value classes, tuples, case classes and - * sealed traits. The generation of `ConfigReader`s is done by Magnolia. - */ +/** + * An object that, when imported, provides implicit `ConfigReader` instances for value classes, tuples, case classes and + * sealed traits. The generation of `ConfigReader`s is done by Magnolia. + */ object reader { type Typeclass[A] = ConfigReader[A] diff --git a/modules/magnolia/src/main/scala/pureconfig/module/magnolia/auto/writer.scala b/modules/magnolia/src/main/scala/pureconfig/module/magnolia/auto/writer.scala index a7d872f64..398f57ee4 100644 --- a/modules/magnolia/src/main/scala/pureconfig/module/magnolia/auto/writer.scala +++ b/modules/magnolia/src/main/scala/pureconfig/module/magnolia/auto/writer.scala @@ -8,9 +8,10 @@ import pureconfig.{ConfigWriter, Exported} import pureconfig.generic.{CoproductHint, ProductHint} import pureconfig.module.magnolia.{ExportedMagnolia, MagnoliaConfigWriter} -/** An object that, when imported, provides implicit `ConfigWriter` instances for value classes, tuples, case classes and - * sealed traits. The generation of `ConfigWriter`s is done by Magnolia. - */ +/** + * An object that, when imported, provides implicit `ConfigWriter` instances for value classes, tuples, case classes and + * sealed traits. The generation of `ConfigWriter`s is done by Magnolia. + */ object writer { type Typeclass[A] = ConfigWriter[A] diff --git a/modules/magnolia/src/main/scala/pureconfig/module/magnolia/semiauto/reader.scala b/modules/magnolia/src/main/scala/pureconfig/module/magnolia/semiauto/reader.scala index 4072fa993..47eef4474 100644 --- a/modules/magnolia/src/main/scala/pureconfig/module/magnolia/semiauto/reader.scala +++ b/modules/magnolia/src/main/scala/pureconfig/module/magnolia/semiauto/reader.scala @@ -7,9 +7,10 @@ import pureconfig.generic.{CoproductHint, ProductHint} import pureconfig.module.magnolia.{EnumerationConfigReaderBuilder, MagnoliaConfigReader} import pureconfig.{ConfigFieldMapping, ConfigReader, KebabCase, PascalCase} -/** An object that, when imported, provides methods for deriving `ConfigReader` instances on demand for value classes, - * tuples, case classes and sealed traits. The generation of `ConfigReader`s is done by Magnolia. - */ +/** + * An object that, when imported, provides methods for deriving `ConfigReader` instances on demand for value classes, + * tuples, case classes and sealed traits. The generation of `ConfigReader`s is done by Magnolia. + */ object reader { type Typeclass[A] = ConfigReader[A] @@ -21,15 +22,17 @@ object reader { def deriveReader[A]: ConfigReader[A] = macro Magnolia.gen[A] - /** Derive a `ConfigReader` for a sealed family of case objects where each type is encoded as the kebab-case - * representation of the type name. - */ + /** + * Derive a `ConfigReader` for a sealed family of case objects where each type is encoded as the kebab-case + * representation of the type name. + */ def deriveEnumerationReader[A: EnumerationConfigReaderBuilder]: ConfigReader[A] = deriveEnumerationReader[A](ConfigFieldMapping(PascalCase, KebabCase)) - /** Derive a `ConfigReader` for a sealed family of case objects where each type is encoded with the `transformName` - * function applied to the type name. - */ + /** + * Derive a `ConfigReader` for a sealed family of case objects where each type is encoded with the `transformName` + * function applied to the type name. + */ def deriveEnumerationReader[A]( transformName: String => String )(implicit builder: EnumerationConfigReaderBuilder[A]): ConfigReader[A] = builder.build(transformName) diff --git a/modules/magnolia/src/main/scala/pureconfig/module/magnolia/semiauto/writer.scala b/modules/magnolia/src/main/scala/pureconfig/module/magnolia/semiauto/writer.scala index d0b8397b4..36afb309c 100644 --- a/modules/magnolia/src/main/scala/pureconfig/module/magnolia/semiauto/writer.scala +++ b/modules/magnolia/src/main/scala/pureconfig/module/magnolia/semiauto/writer.scala @@ -8,9 +8,10 @@ import pureconfig.generic.{CoproductHint, ProductHint} import pureconfig.module.magnolia.{EnumerationConfigWriterBuilder, MagnoliaConfigWriter} import pureconfig.{ConfigFieldMapping, ConfigWriter, KebabCase, PascalCase} -/** An object that, when imported, provides methods for deriving `ConfigWriter` instances on demand for value classes, - * tuples, case classes and sealed traits. The generation of `ConfigWriter`s is done by Magnolia. - */ +/** + * An object that, when imported, provides methods for deriving `ConfigWriter` instances on demand for value classes, + * tuples, case classes and sealed traits. The generation of `ConfigWriter`s is done by Magnolia. + */ object writer { type Typeclass[A] = ConfigWriter[A] @@ -22,15 +23,17 @@ object writer { def deriveWriter[A]: ConfigWriter[A] = macro Magnolia.gen[A] - /** Derive a `ConfigWriter` for a sealed family of case objects where each type is encoded as the kebab-case - * representation of the type name. - */ + /** + * Derive a `ConfigWriter` for a sealed family of case objects where each type is encoded as the kebab-case + * representation of the type name. + */ def deriveEnumerationWriter[A: EnumerationConfigWriterBuilder]: ConfigWriter[A] = deriveEnumerationWriter[A](ConfigFieldMapping(PascalCase, KebabCase)) - /** Derive a `ConfigWriter` for a sealed family of case objects where each type is encoded with the `transformName` - * function applied to the type name. - */ + /** + * Derive a `ConfigWriter` for a sealed family of case objects where each type is encoded with the `transformName` + * function applied to the type name. + */ def deriveEnumerationWriter[A]( transformName: String => String )(implicit builder: EnumerationConfigWriterBuilder[A]): ConfigWriter[A] = builder.build(transformName) diff --git a/modules/scala-xml/src/main/scala/pureconfig/module/scalaxml/package.scala b/modules/scala-xml/src/main/scala/pureconfig/module/scalaxml/package.scala index 6a470e3e1..e6dc243e1 100644 --- a/modules/scala-xml/src/main/scala/pureconfig/module/scalaxml/package.scala +++ b/modules/scala-xml/src/main/scala/pureconfig/module/scalaxml/package.scala @@ -5,8 +5,9 @@ import scala.xml.{Elem, XML} import pureconfig.ConvertHelpers.catchReadError import pureconfig.{ConfigReader, ConfigWriter} -/** [[ConfigReader]] and [[ConfigWriter]] instances for Scala-XML's data structures. - */ +/** + * [[ConfigReader]] and [[ConfigWriter]] instances for Scala-XML's data structures. + */ package object scalaxml { implicit def elemReader: ConfigReader[Elem] = diff --git a/modules/scalaz/src/main/scala/pureconfig/module/scalaz/instances/package.scala b/modules/scalaz/src/main/scala/pureconfig/module/scalaz/instances/package.scala index 92981ada3..d9ba56604 100644 --- a/modules/scalaz/src/main/scala/pureconfig/module/scalaz/instances/package.scala +++ b/modules/scalaz/src/main/scala/pureconfig/module/scalaz/instances/package.scala @@ -6,9 +6,10 @@ import pureconfig.error.{ConfigReaderFailure, ConfigReaderFailures, FailureReaso import scalaz.{Contravariant, Equal, InvariantFunctor, MonadError, Semigroup, Show} -/** Instances of `scalaz` type classes for `ConfigReader`, `ConfigWriter`, `ConfigConvert` - * and other `pureconfig` citizens. - */ +/** + * Instances of `scalaz` type classes for `ConfigReader`, `ConfigWriter`, `ConfigConvert` + * and other `pureconfig` citizens. + */ package object instances { implicit val configReaderInstance: MonadError[ConfigReader, ConfigReaderFailures] = diff --git a/modules/scalaz/src/main/scala/pureconfig/module/scalaz/package.scala b/modules/scalaz/src/main/scala/pureconfig/module/scalaz/package.scala index a01fbaea4..b9ebf7a2e 100644 --- a/modules/scalaz/src/main/scala/pureconfig/module/scalaz/package.scala +++ b/modules/scalaz/src/main/scala/pureconfig/module/scalaz/package.scala @@ -4,8 +4,9 @@ import _root_.scalaz.{==>>, ICons, INil, IList, ISet, Maybe, NonEmptyList, Order import pureconfig._ import pureconfig.error.FailureReason -/** `ConfigReader` and `ConfigWriter` instances for `scalaz` data structures. - */ +/** + * `ConfigReader` and `ConfigWriter` instances for `scalaz` data structures. + */ package object scalaz { case object EmptyIListFound extends FailureReason { diff --git a/modules/scalaz/src/main/scala/pureconfig/module/scalaz/syntax/package.scala b/modules/scalaz/src/main/scala/pureconfig/module/scalaz/syntax/package.scala index 4aaa21aaf..b1a114b23 100644 --- a/modules/scalaz/src/main/scala/pureconfig/module/scalaz/syntax/package.scala +++ b/modules/scalaz/src/main/scala/pureconfig/module/scalaz/syntax/package.scala @@ -8,8 +8,9 @@ import scalaz.{\/, Maybe, NonEmptyList, Validation} import scala.reflect.ClassTag -/** Useful extension methods that bring `scalaz` data structures into `pureconfig` world. - */ +/** + * Useful extension methods that bring `scalaz` data structures into `pureconfig` world. + */ package object syntax { implicit final class ConfigConvertCompanionObjectOps(val co: ConfigConvert.type) extends AnyVal { diff --git a/modules/squants/src/main/scala/pureconfig/module/squants/package.scala b/modules/squants/src/main/scala/pureconfig/module/squants/package.scala index 861a555cc..03c591fed 100644 --- a/modules/squants/src/main/scala/pureconfig/module/squants/package.scala +++ b/modules/squants/src/main/scala/pureconfig/module/squants/package.scala @@ -14,17 +14,18 @@ import _root_.squants.time._ import pureconfig.ConfigConvert._ -/** Provides [[ConfigConvert]] instances for Squants [[_root_.squants.Dimension]]. - * - * Note: All of the machinery can disappear if the `parse` method of [[_root_.squants.Dimension]] - * is made public. (see: https://github.com/typelevel/squants/issues/184). After that, something - * like this should suffice: - * - * {{{ - * implicit def dimensionConfigConvert[A <: Quantity[A]](dim: Dimension[A])(implicit tag: ClassTag[A]) = - * viaNonEmptyStringTry[A](dim.parse, _.toString) - * }}} - */ +/** + * Provides [[ConfigConvert]] instances for Squants [[_root_.squants.Dimension]]. + * + * Note: All of the machinery can disappear if the `parse` method of [[_root_.squants.Dimension]] + * is made public. (see: https://github.com/typelevel/squants/issues/184). After that, something + * like this should suffice: + * + * {{{ + * implicit def dimensionConfigConvert[A <: Quantity[A]](dim: Dimension[A])(implicit tag: ClassTag[A]) = + * viaNonEmptyStringTry[A](dim.parse, _.toString) + * }}} + */ package object squants { // electro diff --git a/modules/yaml/src/main/scala/pureconfig/module/yaml/YamlConfigSource.scala b/modules/yaml/src/main/scala/pureconfig/module/yaml/YamlConfigSource.scala index 4e87bfed9..3cf507e02 100644 --- a/modules/yaml/src/main/scala/pureconfig/module/yaml/YamlConfigSource.scala +++ b/modules/yaml/src/main/scala/pureconfig/module/yaml/YamlConfigSource.scala @@ -18,14 +18,15 @@ import pureconfig.error._ import pureconfig.module.yaml.error.{NonStringKeyFound, UnsupportedYamlType} import pureconfig.{ConfigObjectSource, ConfigSource} -/** A `ConfigSource` that reads configs from YAML documents in a stream, file or string. - * - * @param getReader the thunk to generate a `Reader` instance from which the YAML document will be - * read. This parameter won't be memoized so it can be used with dynamic sources - * (e.g. URLs) - * @param uri the optional URI of the source. Used only to provide better error messages. - * @param onIOFailure an optional function used to provide a custom failure when IO errors happen - */ +/** + * A `ConfigSource` that reads configs from YAML documents in a stream, file or string. + * + * @param getReader the thunk to generate a `Reader` instance from which the YAML document will be + * read. This parameter won't be memoized so it can be used with dynamic sources + * (e.g. URLs) + * @param uri the optional URI of the source. Used only to provide better error messages. + * @param onIOFailure an optional function used to provide a custom failure when IO errors happen + */ final class YamlConfigSource private ( getReader: () => Reader, uri: Option[URI] = None, @@ -41,19 +42,21 @@ final class YamlConfigSource private ( } } - /** Converts this YAML source to a config object source to allow merging with other sources. This - * operation is not reversible. The new source will load with an error if this document does not - * contain an object. - * - * @return a config object source that produces YAML object documents read by this source - */ + /** + * Converts this YAML source to a config object source to allow merging with other sources. This + * operation is not reversible. The new source will load with an error if this document does not + * contain an object. + * + * @return a config object source that produces YAML object documents read by this source + */ def asObjectSource: ConfigObjectSource = ConfigObjectSource(fluentCursor().asObjectCursor.right.map(_.objValue.toConfig)) - /** Returns a new source that produces a multi-document YAML read by this source as a config list. - * - * @return a new source that produces a multi-document YAML read by this source as a config list. - */ + /** + * Returns a new source that produces a multi-document YAML read by this source as a config list. + * + * @return a new source that produces a multi-document YAML read by this source as a config list. + */ def multiDoc: ConfigSource = new ConfigSource { def value(): Result[ConfigValue] = { @@ -141,11 +144,12 @@ final class YamlConfigSource private ( object YamlConfigSource { - /** Returns a YAML source that provides configs read from a file. - * - * @param path the path to the file as a string - * @return a YAML source that provides configs read from a file. - */ + /** + * Returns a YAML source that provides configs read from a file. + * + * @param path the path to the file as a string + * @return a YAML source that provides configs read from a file. + */ def file(path: String) = new YamlConfigSource( () => new FileReader(path), @@ -153,11 +157,12 @@ object YamlConfigSource { onIOFailure = Some(CannotReadFile(Paths.get(path), _)) ) - /** Returns a YAML source that provides configs read from a file. - * - * @param path the path to the file - * @return a YAML source that provides configs read from a file. - */ + /** + * Returns a YAML source that provides configs read from a file. + * + * @param path the path to the file + * @return a YAML source that provides configs read from a file. + */ def file(path: Path) = new YamlConfigSource( () => Files.newBufferedReader(path), @@ -165,11 +170,12 @@ object YamlConfigSource { onIOFailure = Some(CannotReadFile(path, _)) ) - /** Returns a YAML source that provides configs read from a file. - * - * @param file the file - * @return a YAML source that provides configs read from a file. - */ + /** + * Returns a YAML source that provides configs read from a file. + * + * @param file the file + * @return a YAML source that provides configs read from a file. + */ def file(file: File) = new YamlConfigSource( () => new FileReader(file), @@ -177,10 +183,11 @@ object YamlConfigSource { onIOFailure = Some(CannotReadFile(file.toPath, _)) ) - /** Returns a YAML source that provides a config parsed from a string. - * - * @param confStr the YAML content - * @return a YAML source that provides a config parsed from a string. - */ + /** + * Returns a YAML source that provides a config parsed from a string. + * + * @param confStr the YAML content + * @return a YAML source that provides a config parsed from a string. + */ def string(confStr: String) = new YamlConfigSource(() => new StringReader(confStr)) } diff --git a/modules/yaml/src/main/scala/pureconfig/module/yaml/package.scala b/modules/yaml/src/main/scala/pureconfig/module/yaml/package.scala index a1160f009..9c18e53f3 100644 --- a/modules/yaml/src/main/scala/pureconfig/module/yaml/package.scala +++ b/modules/yaml/src/main/scala/pureconfig/module/yaml/package.scala @@ -9,24 +9,26 @@ import pureconfig.error._ package object yaml { - /** Loads a configuration of type `Config` from the given YAML file. - * - * @param path the path of the YAML file to read - * @return A `Success` with the configuration if it is possible to create an instance of type - * `Config` from the YAML file, else a `Failure` with details on why it isn't possible - */ + /** + * Loads a configuration of type `Config` from the given YAML file. + * + * @param path the path of the YAML file to read + * @return A `Success` with the configuration if it is possible to create an instance of type + * `Config` from the YAML file, else a `Failure` with details on why it isn't possible + */ @deprecated("Use `YamlConfigSource.file(path).load[Config]` instead", "0.12.1") def loadYaml[Config](path: Path)(implicit reader: Derivation[ConfigReader[Config]]): ConfigReader.Result[Config] = { YamlConfigSource.file(path).load[Config] } - /** Loads a configuration of type `Config` from the given YAML file. - * - * @param path the path of the YAML file to read - * @param namespace the base namespace from which the configuration should be load - * @return A `Success` with the configuration if it is possible to create an instance of type - * `Config` from the YAML file, else a `Failure` with details on why it isn't possible - */ + /** + * Loads a configuration of type `Config` from the given YAML file. + * + * @param path the path of the YAML file to read + * @param namespace the base namespace from which the configuration should be load + * @return A `Success` with the configuration if it is possible to create an instance of type + * `Config` from the YAML file, else a `Failure` with details on why it isn't possible + */ @deprecated("Use `YamlConfigSource.file(path).at(namespace).load[Config]` instead", "0.12.1") def loadYaml[Config](path: Path, namespace: String)(implicit reader: Derivation[ConfigReader[Config]] @@ -34,12 +36,13 @@ package object yaml { YamlConfigSource.file(path).at(namespace).load[Config] } - /** Loads a configuration of type `Config` from the given string. - * - * @param content the string containing the YAML document - * @return A `Success` with the configuration if it is possible to create an instance of type - * `Config` from `content`, else a `Failure` with details on why it isn't possible - */ + /** + * Loads a configuration of type `Config` from the given string. + * + * @param content the string containing the YAML document + * @return A `Success` with the configuration if it is possible to create an instance of type + * `Config` from `content`, else a `Failure` with details on why it isn't possible + */ @deprecated("Use `YamlConfigSource.string(content).load[Config]` instead", "0.12.1") def loadYaml[Config]( content: String @@ -54,23 +57,25 @@ package object yaml { YamlConfigSource.string(content).at(namespace).load[Config] } - /** Loads a configuration of type `Config` from the given YAML file. - * - * @param path the path of the YAML file to read - * @return the configuration - */ + /** + * Loads a configuration of type `Config` from the given YAML file. + * + * @param path the path of the YAML file to read + * @return the configuration + */ @throws[ConfigReaderException[_]] @deprecated("Use `YamlConfigSource.file(path).loadOrThrow[Config]` instead", "0.12.1") def loadYamlOrThrow[Config: ClassTag](path: Path)(implicit reader: Derivation[ConfigReader[Config]]): Config = { YamlConfigSource.file(path).loadOrThrow[Config] } - /** Loads a configuration of type `Config` from the given YAML file. - * - * @param path the path of the YAML file to read - * @param namespace the base namespace from which the configuration should be load - * @return the configuration - */ + /** + * Loads a configuration of type `Config` from the given YAML file. + * + * @param path the path of the YAML file to read + * @param namespace the base namespace from which the configuration should be load + * @return the configuration + */ @throws[ConfigReaderException[_]] @deprecated("Use `YamlConfigSource.file(path).at(namespace).loadOrThrow[Config]` instead", "0.12.1") def loadYamlOrThrow[Config: ClassTag](path: Path, namespace: String)(implicit @@ -79,23 +84,25 @@ package object yaml { YamlConfigSource.file(path).at(namespace).loadOrThrow[Config] } - /** Loads a configuration of type `Config` from the given string. - * - * @param content the string containing the YAML document - * @return the configuration - */ + /** + * Loads a configuration of type `Config` from the given string. + * + * @param content the string containing the YAML document + * @return the configuration + */ @throws[ConfigReaderException[_]] @deprecated("Use `YamlConfigSource.string(content).loadOrThrow[Config]` instead", "0.12.1") def loadYamlOrThrow[Config: ClassTag](content: String)(implicit reader: Derivation[ConfigReader[Config]]): Config = { YamlConfigSource.string(content).loadOrThrow[Config] } - /** Loads a configuration of type `Config` from the given string. - * - * @param content the string containing the YAML document - * @param namespace the base namespace from which the configuration should be load - * @return the configuration - */ + /** + * Loads a configuration of type `Config` from the given string. + * + * @param content the string containing the YAML document + * @param namespace the base namespace from which the configuration should be load + * @return the configuration + */ @throws[ConfigReaderException[_]] @deprecated("Use `YamlConfigSource.string(content).at(namespace).loadOrThrow[Config]` instead", "0.12.1") def loadYamlOrThrow[Config: ClassTag](content: String, namespace: String)(implicit @@ -104,27 +111,29 @@ package object yaml { YamlConfigSource.string(content).at(namespace).loadOrThrow[Config] } - /** Loads a configuration of type `Config` from the given multi-document YAML file. `Config` must have a - * `ConfigReader` supporting reading from config lists. - * - * @param path the path of the YAML file to read - * @return A `Success` with the configuration if it is possible to create an instance of type - * `Config` from the multi-document YAML file, else a `Failure` with details on why it - * isn't possible - */ + /** + * Loads a configuration of type `Config` from the given multi-document YAML file. `Config` must have a + * `ConfigReader` supporting reading from config lists. + * + * @param path the path of the YAML file to read + * @return A `Success` with the configuration if it is possible to create an instance of type + * `Config` from the multi-document YAML file, else a `Failure` with details on why it + * isn't possible + */ @deprecated("Use `YamlConfigSource.file(path).multiDoc.load[Config]` instead", "0.12.1") def loadYamls[Config](path: Path)(implicit reader: Derivation[ConfigReader[Config]]): ConfigReader.Result[Config] = { YamlConfigSource.file(path).multiDoc.load[Config] } - /** Loads a configuration of type `Config` from the given multi-document string. `Config` must have a - * `ConfigReader` supporting reading from config lists. - * - * @param content the string containing the YAML documents - * @return A `Success` with the configuration if it is possible to create an instance of type - * `Config` from the multi-document string, else a `Failure` with details on why it - * isn't possible - */ + /** + * Loads a configuration of type `Config` from the given multi-document string. `Config` must have a + * `ConfigReader` supporting reading from config lists. + * + * @param content the string containing the YAML documents + * @return A `Success` with the configuration if it is possible to create an instance of type + * `Config` from the multi-document string, else a `Failure` with details on why it + * isn't possible + */ @deprecated("Use `YamlConfigSource.string(content).multiDoc.load[Config]` instead", "0.12.1") def loadYamls[Config]( content: String @@ -132,24 +141,26 @@ package object yaml { YamlConfigSource.string(content).multiDoc.load[Config] } - /** Loads a configuration of type `Config` from the given multi-document YAML file. `Config` must have a - * `ConfigReader` supporting reading from config lists. - * - * @param path the path of the YAML file to read - * @return the configuration - */ + /** + * Loads a configuration of type `Config` from the given multi-document YAML file. `Config` must have a + * `ConfigReader` supporting reading from config lists. + * + * @param path the path of the YAML file to read + * @return the configuration + */ @throws[ConfigReaderException[_]] @deprecated("Use `YamlConfigSource.file(path).multiDoc.loadOrThrow[Config]` instead", "0.12.1") def loadYamlsOrThrow[Config: ClassTag](path: Path)(implicit reader: Derivation[ConfigReader[Config]]): Config = { YamlConfigSource.file(path).multiDoc.loadOrThrow[Config] } - /** Loads a configuration of type `Config` from the given multi-document string. `Config` must have a - * `ConfigReader` supporting reading from config lists. - * - * @param content the string containing the YAML documents - * @return the configuration - */ + /** + * Loads a configuration of type `Config` from the given multi-document string. `Config` must have a + * `ConfigReader` supporting reading from config lists. + * + * @param content the string containing the YAML documents + * @return the configuration + */ @throws[ConfigReaderException[_]] @deprecated("Use `YamlConfigSource.string(content).multiDoc.loadOrThrow[Config]` instead", "0.12.1") def loadYamlsOrThrow[Config: ClassTag](content: String)(implicit reader: Derivation[ConfigReader[Config]]): Config = { diff --git a/project/ModuleMdocPlugin.scala b/project/ModuleMdocPlugin.scala index 958fe1f05..cb7c97b93 100644 --- a/project/ModuleMdocPlugin.scala +++ b/project/ModuleMdocPlugin.scala @@ -3,13 +3,14 @@ import mdoc.MdocPlugin.autoImport._ import sbt._ import sbt.Keys._ -/** A plugin that generates a synthetic SBT project for documentation for each module it is enabled on. The generated - * SBT projects depend on the original project and also have a hardcoded dependency on "generic" in order to provide - * support for auto-derivation in documentation. - * - * This is needed because unlike tut there is no separate classpath configuration for documentation. See - * https://github.com/scalameta/mdoc/issues/155 for details. - */ +/** + * A plugin that generates a synthetic SBT project for documentation for each module it is enabled on. The generated + * SBT projects depend on the original project and also have a hardcoded dependency on "generic" in order to provide + * support for auto-derivation in documentation. + * + * This is needed because unlike tut there is no separate classpath configuration for documentation. See + * https://github.com/scalameta/mdoc/issues/155 for details. + */ object ModuleMdocPlugin extends AutoPlugin { object autoImport { diff --git a/testkit/src/main/scala-2.13-/pureconfig/DerivationChecks.scala b/testkit/src/main/scala-2.13-/pureconfig/DerivationChecks.scala index 55eff29cb..640bf3e6d 100644 --- a/testkit/src/main/scala-2.13-/pureconfig/DerivationChecks.scala +++ b/testkit/src/main/scala-2.13-/pureconfig/DerivationChecks.scala @@ -3,16 +3,18 @@ package pureconfig import scala.language.experimental.macros import scala.reflect.macros.blackbox -/** Helper methods for testing the behavior of `Derivation`. - */ +/** + * Helper methods for testing the behavior of `Derivation`. + */ object DerivationChecks { - /** A version of the `shapeless.test.illTyped` macro that allows expected error messages with multiple lines, as well - * as whitespace before and after the message. - * - * @param code the code to check for non-compilation - * @param expected the expected error message as a variable number of lines - */ + /** + * A version of the `shapeless.test.illTyped` macro that allows expected error messages with multiple lines, as well + * as whitespace before and after the message. + * + * @param code the code to check for non-compilation + * @param expected the expected error message as a variable number of lines + */ def illTyped(code: String, expected: String*): Unit = macro DerivationChecksMacros.illTyped } diff --git a/testkit/src/main/scala/pureconfig/ConfigConvertChecks.scala b/testkit/src/main/scala/pureconfig/ConfigConvertChecks.scala index 5b3b792a5..1f8daddd1 100644 --- a/testkit/src/main/scala/pureconfig/ConfigConvertChecks.scala +++ b/testkit/src/main/scala/pureconfig/ConfigConvertChecks.scala @@ -11,18 +11,20 @@ import org.scalatest.matchers.should.Matchers import org.scalatestplus.scalacheck.ScalaCheckDrivenPropertyChecks import pureconfig.error.{ConfigReaderFailures, ConvertFailure, FailureReason} -/** Add utilities to a scalatest `FlatSpec` to test `ConfigConvert` instances - */ +/** + * Add utilities to a scalatest `FlatSpec` to test `ConfigConvert` instances + */ trait ConfigConvertChecks { this: AnyFlatSpec with Matchers with ScalaCheckDrivenPropertyChecks with EitherValues => - /** For each value of type `A`, check that the value produced by converting to and then from `ConfigValue` is the same - * of the original value - * - * Note that this method doesn't check all the values but only the values that can be created by `Arbitrary[A]` and - * only the `ConfigValue` created by `ConfigConvert[A].to`. While `Arbitrary[A]` is usually comprehensive, - * `ConfigConvert[A].from` could support different kind of values that `ConfigConvert[A].to` doesn't produce - * because, for instance, multiple representation of `a: A` are possible. Use [[checkRead]] for those representations. - */ + /** + * For each value of type `A`, check that the value produced by converting to and then from `ConfigValue` is the same + * of the original value + * + * Note that this method doesn't check all the values but only the values that can be created by `Arbitrary[A]` and + * only the `ConfigValue` created by `ConfigConvert[A].to`. While `Arbitrary[A]` is usually comprehensive, + * `ConfigConvert[A].from` could support different kind of values that `ConfigConvert[A].to` doesn't produce + * because, for instance, multiple representation of `a: A` are possible. Use [[checkRead]] for those representations. + */ def checkArbitrary[A](implicit cc: Derivation[ConfigConvert[A]], arb: Arbitrary[A], @@ -33,23 +35,24 @@ trait ConfigConvertChecks { this: AnyFlatSpec with Matchers with ScalaCheckDrive cc.value.from(cc.value.to(a)).value shouldEqual a } - /** A more generic version of [[checkArbitrary]] where the type which will be written as `ConfigValue` is - * different from the type which will be read from that `ConfigValue`. The idea being is to test the reading - * part of a `ConfigConvert` by providing another type for which it's easy to create `Arbitrary` instances - * and write the values to a configuration. - * - * For instance, to test that `Double` can be read from percentages, like `"42 %"`, we can create a dummy - * [[pureconfig.data.Percentage]] class which contains an integer from `0` to `100`, write that percentage to - * a `ConfigValue` representing a `String` and then try to read the percentage from the `ConfigValue` via - * `ConfigConvert[Double].from`. Creating an instance of `Arbitrary[Percentage]` is simple, same for - * `ConfigConvert[Percentage]`. - * - * @param f a function used to convert a value of type `T2` to a value of type `T1`. The result of the conversion - * to and from a `ConfigValue` will be tested against the output of this function. - * @param cr the `ConfigConvert` used to read a value from a `ConfigValue`. This is the instance that we want to test - * @param cw the `ConfigConvert` used to write a value to a `ConfigValue`. This is the dummy instance used to test `cr` - * @param arb the `Arbitrary` used to generate values to write a `ConfigValue` via `cw` - */ + /** + * A more generic version of [[checkArbitrary]] where the type which will be written as `ConfigValue` is + * different from the type which will be read from that `ConfigValue`. The idea being is to test the reading + * part of a `ConfigConvert` by providing another type for which it's easy to create `Arbitrary` instances + * and write the values to a configuration. + * + * For instance, to test that `Double` can be read from percentages, like `"42 %"`, we can create a dummy + * [[pureconfig.data.Percentage]] class which contains an integer from `0` to `100`, write that percentage to + * a `ConfigValue` representing a `String` and then try to read the percentage from the `ConfigValue` via + * `ConfigConvert[Double].from`. Creating an instance of `Arbitrary[Percentage]` is simple, same for + * `ConfigConvert[Percentage]`. + * + * @param f a function used to convert a value of type `T2` to a value of type `T1`. The result of the conversion + * to and from a `ConfigValue` will be tested against the output of this function. + * @param cr the `ConfigConvert` used to read a value from a `ConfigValue`. This is the instance that we want to test + * @param cw the `ConfigConvert` used to write a value to a `ConfigValue`. This is the dummy instance used to test `cr` + * @param arb the `Arbitrary` used to generate values to write a `ConfigValue` via `cw` + */ def checkArbitrary2[A, B](f: B => A)(implicit cr: ConfigConvert[A], cw: ConfigConvert[B], @@ -62,9 +65,10 @@ trait ConfigConvertChecks { this: AnyFlatSpec with Matchers with ScalaCheckDrive cr.from(cw.to(b)).value shouldEqual f(b) } - /** For each pair of value of type `A` and `ConfigValue`, check that `ConfigReader[A].from` - * successfully converts the latter into to former. Useful to test specific values - */ + /** + * For each pair of value of type `A` and `ConfigValue`, check that `ConfigReader[A].from` + * successfully converts the latter into to former. Useful to test specific values + */ def checkRead[A: Equality]( reprsToValues: (ConfigValue, A)* )(implicit cr: ConfigReader[A], tpe: TypeStringCompat[A]): Unit = @@ -78,9 +82,10 @@ trait ConfigConvertChecks { this: AnyFlatSpec with Matchers with ScalaCheckDrive def checkReadString[A: ConfigReader: TypeStringCompat: Equality](strsToValues: (String, A)*): Unit = checkRead[A](strsToValues.map { case (s, a) => ConfigValueFactory.fromAnyRef(s) -> a }: _*) - /** For each pair of value of type `A` and `ConfigValue`, check that `ConfigWriter[A].to` - * successfully converts the former into the latter. Useful to test specific values - */ + /** + * For each pair of value of type `A` and `ConfigValue`, check that `ConfigWriter[A].to` + * successfully converts the former into the latter. Useful to test specific values + */ def checkWrite[A: Equality]( valuesToReprs: (A, ConfigValue)* )(implicit cw: ConfigWriter[A], tpe: TypeStringCompat[A]): Unit = @@ -94,10 +99,11 @@ trait ConfigConvertChecks { this: AnyFlatSpec with Matchers with ScalaCheckDrive def checkWriteString[A: ConfigWriter: TypeStringCompat: Equality](valuesToStrs: (A, String)*): Unit = checkWrite[A](valuesToStrs.map { case (a, s) => a -> ConfigValueFactory.fromAnyRef(s) }: _*) - /** For each pair of value of type `A` and `ConfigValue`, check that `ConfigReader[A].from` - * successfully converts the latter into to former and `ConfigWriter[A].to` successfully converts the former into the - * latter. - */ + /** + * For each pair of value of type `A` and `ConfigValue`, check that `ConfigReader[A].from` + * successfully converts the latter into to former and `ConfigWriter[A].to` successfully converts the former into the + * latter. + */ def checkReadWrite[A: ConfigReader: ConfigWriter: TypeStringCompat: Equality]( reprsValues: (ConfigValue, A)* ): Unit = { @@ -113,11 +119,12 @@ trait ConfigConvertChecks { this: AnyFlatSpec with Matchers with ScalaCheckDrive checkWriteString[A](strsValues.map(_.swap): _*) } - /** Check that `cc` returns error of type `E` when trying to read each value passed with `values` - * - * @param values the values that should not be conver - * @param cr the `ConfigConvert` to test - */ + /** + * Check that `cc` returns error of type `E` when trying to read each value passed with `values` + * + * @param values the values that should not be conver + * @param cr the `ConfigConvert` to test + */ def checkFailure[A, E <: FailureReason]( values: ConfigValue* )(implicit cr: ConfigReader[A], tpe: TypeStringCompat[A], eTag: ClassTag[E]): Unit = @@ -130,10 +137,11 @@ trait ConfigConvertChecks { this: AnyFlatSpec with Matchers with ScalaCheckDrive } } - /** For each pair of `ConfigValue` and `ConfigReaderFailures`, check that `cr` - * fails with the provided errors when trying to read the provided - * `ConfigValue`. - */ + /** + * For each pair of `ConfigValue` and `ConfigReaderFailures`, check that `cr` + * fails with the provided errors when trying to read the provided + * `ConfigValue`. + */ def checkFailures[A]( valuesToErrors: (ConfigValue, ConfigReaderFailures)* )(implicit cr: ConfigReader[A], tpe: TypeStringCompat[A]): Unit = diff --git a/tests/src/test/scala/pureconfig/ConfigReaderFailureOriginSuite.scala b/tests/src/test/scala/pureconfig/ConfigReaderFailureOriginSuite.scala index 274ec20af..778e95c8e 100644 --- a/tests/src/test/scala/pureconfig/ConfigReaderFailureOriginSuite.scala +++ b/tests/src/test/scala/pureconfig/ConfigReaderFailureOriginSuite.scala @@ -9,8 +9,9 @@ import com.typesafe.config.{ConfigFactory, ConfigValueType} import org.scalatest.{EitherValues, Inside} import pureconfig.error._ -/** Suite of tests related to the origin of ConfigValues that raised failures. - */ +/** + * Suite of tests related to the origin of ConfigValues that raised failures. + */ class ConfigReaderFailureOriginSuite extends BaseSuite with EitherValues with Inside { case class Conf(a: Int, b: String, c: Int) implicit val confReader: ConfigReader[Conf] = ConfigReader.forProduct3("a", "b", "c")(Conf.apply) diff --git a/tests/src/test/scala/pureconfig/ConfigReaderFailuresPrettyPrintSuite.scala b/tests/src/test/scala/pureconfig/ConfigReaderFailuresPrettyPrintSuite.scala index bc5d21fbf..a7ac8dd30 100644 --- a/tests/src/test/scala/pureconfig/ConfigReaderFailuresPrettyPrintSuite.scala +++ b/tests/src/test/scala/pureconfig/ConfigReaderFailuresPrettyPrintSuite.scala @@ -8,8 +8,9 @@ import java.net.URL import com.typesafe.config._ import pureconfig.error._ -/** Suite of tests related to the pretty printing of config reader failures. - */ +/** + * Suite of tests related to the pretty printing of config reader failures. + */ class ConfigReaderFailuresPrettyPrintSuite extends BaseSuite { "A ConfigReaderFailures prettyPrint method" should "print errors with a configurable identation" in {