1 /*
2  *  Make.org Core API
3  *  Copyright (C) 2020 Make.org
4  *
5  * This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Affero General Public License as
7  *  published by the Free Software Foundation, either version 3 of the
8  *  License, or (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Affero General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Affero General Public License
16  *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  *
18  */
19 
20 package org.make.core.technical
21 
22 import cats.data.{NonEmptyList, Validated, ValidatedNec}
23 import cats.implicits._
24 import io.circe.{Decoder, DecodingFailure, HCursor}
25 import org.make.core.ValidationError
26 import org.make.core.reference.Language
27 import shapeless.{HList, LabelledGeneric}
28 import shapeless.ops.record.{Keys, Values}
29 import scala.annotation.tailrec
30 
31 object MultilingualUtils {
32 
33   def hasRequiredTranslationsFromCsv(
34     languagesSet: Set[Language],
35     translations: Option[Multilingual[String]],
36     originalLanguage: Option[Language],
37     lineNumber: Int
38   ): ValidatedNec[ValidationError, Option[Multilingual[String]]] = {
39     val languages = originalLanguage.toList.toSet ++ translations.toList
40       .toSet[Multilingual[String]]
41       .flatMap(_.providedLanguages)
42     languagesSet == languages match {
43       case true => translations.validNec
44       case false if languagesSet.sizeIs > languages.size =>
45         val missing = languagesSet.diff(languages)
46         ValidationError(
47           "contents",
48           "missing_translation",
49           Some(s"There is a missing translations for ${missing.mkString(",")} on line $lineNumber")
50         ).invalidNec
51       case false if languagesSet.sizeIs < languages.size =>
52         val tooMany = languages.diff(languagesSet)
53         ValidationError(
54           "contents",
55           "too_many_translation",
56           Some(s"There is too many translations : ${tooMany.mkString(",")} on line $lineNumber")
57         ).invalidNec
58       case _ =>
59         val mismatch = languages.diff(languagesSet)
60         ValidationError(
61           "content",
62           "mismatch_translation",
63           Some(s"There is a translations mismatch : ${mismatch.mkString(",")} on line $lineNumber")
64         ).invalidNec
65     }
66   }
67 
68   def hasRequiredTranslations(
69     languagesSet: Set[Language],
70     multilinguals: List[(Multilingual[_], String)]
71   ): ValidatedNec[ValidationError, Unit] =
72     multilinguals.traverse_({
73       case (field, fieldName) =>
74         languagesSet == field.providedLanguages match {
75           case true => ().validNec
76           case false if languagesSet.sizeIs > field.providedLanguages.size =>
77             val missing = languagesSet.diff(field.providedLanguages)
78             ValidationError(
79               fieldName,
80               "missing_translation",
81               Some(s"Field $fieldName is missing translations for ${missing.mkString(",")}")
82             ).invalidNec
83           case false if languagesSet.sizeIs < field.providedLanguages.size =>
84             val tooMany = field.providedLanguages.diff(languagesSet)
85             ValidationError(
86               fieldName,
87               "too_many_translation",
88               Some(s"Field $fieldName has too many translations : ${tooMany.mkString(",")}")
89             ).invalidNec
90           case _ =>
91             val mismatch = field.providedLanguages.diff(languagesSet)
92             ValidationError(
93               fieldName,
94               "mismatch_translation",
95               Some(s"Field $fieldName has mismatch translations : ${mismatch.mkString(",")}")
96             ).invalidNec
97         }
98     })
99 
100   def validateDecoder[A](decoder: Decoder[A])(
101     langsF: A    => Set[Language],
102     requiredF: A => Seq[(Multilingual[_], String)],
103     optionalF: A => Seq[Option[(Multilingual[_], String)]]
104   ): Decoder[A] =
105     decoder.flatMap { t =>
106       val langs = langsF(t)
107 
108       def findErrors(c: HCursor) =
109         (requiredF(t).iterator ++ optionalF(t).iterator.flatten).flatMap {
110           case (field, fieldName) =>
111             langs.diff(field.providedLanguages) match {
112               case missing if missing.nonEmpty =>
113                 val ac = c.downField(fieldName)
114                 Some(DecodingFailure(s"Missing translations: ${missing.mkString(", ")}", ac.history))
115 
116               case _ =>
117                 None
118             }
119         }
120 
121       new Decoder[A] {
122         override def apply(c: HCursor): Decoder.Result[A] =
123           findErrors(c).nextOption().toLeft(t)
124 
125         override def decodeAccumulating(c: HCursor): Decoder.AccumulatingResult[A] =
126           findErrors(c).toList match {
127             case hd :: tl =>
128               Validated.Invalid(NonEmptyList(hd, tl))
129 
130             case Nil =>
131               Validated.Valid(t)
132           }
133       }
134     }
135 
136   /**
137     * Enhances an instance of `Decoder[A]` by checking every fields of `A` which has a
138     * type of `Multilingual[_]`, or `Option[Multilingual[_]]`. Every one of these fields
139     * must contain a translation for every given languages passed as parameter.
140     *
141     * You have to pass as parameter `langsF` a function `A => Set[Language]` since it
142     * generally depends upon values in `A` instead of a static set of languages.
143     */
144   def genDecoder[A, Repr <: HList](
145     decoder: Decoder[A],
146     langsF: A => Set[Language]
147   )(implicit gen: LabelledGeneric.Aux[A, Repr], keys: Keys[Repr], values: Values[Repr]): Decoder[A] =
148     decoder.flatMap(a => new GenDecoder(a, langsF(a)))
149 
150   private class GenDecoder[A, Repr <: HList](a: A, langs: Set[Language])(
151     implicit gen: LabelledGeneric.Aux[A, Repr],
152     keys: Keys[Repr],
153     values: Values[Repr]
154   ) extends Decoder[A] {
155 
156     override def apply(c: HCursor): Decoder.Result[A] = {
157 
158       /**
159         * Actually validate a `Multilingual[_]` instance, which is actually stored
160         * in some field `k` of `A`.
161         */
162       def doValidate(x: Multilingual[_], k: Symbol): Either[DecodingFailure, Unit] =
163         langs.diff(x.providedLanguages) match {
164           case missing if missing.nonEmpty =>
165             Left(DecodingFailure(s"Missing translations: ${missing.mkString(", ")}", c.downField(k.name).history))
166           case _ => Right(())
167         }
168 
169       /**
170         * Scan through every fields of `A` to find instances of :
171         *   - `Multilingual[_]`,
172         *   - `Option[Multilingual[_]]`.
173         */
174       @SuppressWarnings(Array("org.wartremover.warts.TraversableOps", "org.wartremover.warts.IterableOps"))
175       @tailrec
176       def recApply(ks: List[Any], xs: List[Any]): Decoder.Result[A] =
177         ks.headOption.zip(xs.headOption) match {
178           case None => Right(a)
179 
180           case Some((k: Symbol, x: Multilingual[_])) =>
181             doValidate(x, k) match {
182               case Left(err) =>
183                 Left(err)
184               case _ =>
185                 recApply(ks.tail, xs.tail)
186             }
187 
188           case Some((k: Symbol, Some(x: Multilingual[_]))) =>
189             doValidate(x, k) match {
190               case Left(err) =>
191                 Left(err)
192               case _ =>
193                 recApply(ks.tail, xs.tail)
194             }
195 
196           case _ => recApply(ks.tail, xs.tail)
197         }
198 
199       // Fetch reflective information generated at compile-time by shapeless,
200       // and start to validate `a`.
201       recApply(keys().runtimeList, values(gen.to(a)).runtimeList)
202     }
203 
204   }
205 }
Line Stmt Id Pos Tree Symbol Tests Code
39 2334 1402 - 1525 Apply scala.collection.SetOps.++ originalLanguage.toList.toSet[org.make.core.reference.Language].++(translations.toList.toSet[org.make.core.technical.Multilingual[String]].flatMap[org.make.core.reference.Language](((x$1: org.make.core.technical.Multilingual[String]) => x$1.providedLanguages)))
41 943 1505 - 1524 Select org.make.core.technical.Multilingual.providedLanguages x$1.providedLanguages
41 4151 1435 - 1525 Apply scala.collection.IterableOps.flatMap translations.toList.toSet[org.make.core.technical.Multilingual[String]].flatMap[org.make.core.reference.Language](((x$1: org.make.core.technical.Multilingual[String]) => x$1.providedLanguages))
42 1220 1530 - 1555 Apply java.lang.Object.== languagesSet.==(languages)
43 4516 1583 - 1604 TypeApply cats.syntax.ValidatedIdOpsBinCompat0.validNec cats.implicits.catsSyntaxValidatedIdBinCompat0[Option[org.make.core.technical.Multilingual[String]]](translations).validNec[Nothing]
44 2454 1647 - 1661 Select scala.collection.IterableOnceOps.size languages.size
44 512 1625 - 1661 Apply scala.collection.IterableOps.SizeCompareOps.> languagesSet.sizeIs.>(languages.size)
45 3989 1687 - 1715 Apply scala.collection.immutable.SetOps.diff languagesSet.diff(languages)
46 2168 1724 - 1905 Apply org.make.core.ValidationError.apply org.make.core.ValidationError.apply("contents", "missing_translation", scala.Some.apply[String](("There is a missing translations for ".+(missing.mkString(",")).+(" on line ").+(lineNumber): String)))
47 2878 1751 - 1761 Literal <nosymbol> "contents"
48 892 1773 - 1794 Literal <nosymbol> "missing_translation"
49 4093 1806 - 1895 Apply scala.Some.apply scala.Some.apply[String](("There is a missing translations for ".+(missing.mkString(",")).+(" on line ").+(lineNumber): String))
50 5500 1724 - 1916 TypeApply cats.syntax.ValidatedIdOpsBinCompat0.invalidNec cats.implicits.catsSyntaxValidatedIdBinCompat0[org.make.core.ValidationError](org.make.core.ValidationError.apply("contents", "missing_translation", scala.Some.apply[String](("There is a missing translations for ".+(missing.mkString(",")).+(" on line ").+(lineNumber): String)))).invalidNec[Nothing]
51 4527 1959 - 1973 Select scala.collection.IterableOnceOps.size languages.size
51 2465 1937 - 1973 Apply scala.collection.IterableOps.SizeCompareOps.< languagesSet.sizeIs.<(languages.size)
52 452 1999 - 2027 Apply scala.collection.immutable.SetOps.diff languages.diff(languagesSet)
53 4104 2036 - 2215 Apply org.make.core.ValidationError.apply org.make.core.ValidationError.apply("contents", "too_many_translation", scala.Some.apply[String](("There is too many translations : ".+(tooMany.mkString(",")).+(" on line ").+(lineNumber): String)))
54 3702 2063 - 2073 Literal <nosymbol> "contents"
55 2803 2085 - 2107 Literal <nosymbol> "too_many_translation"
56 752 2119 - 2205 Apply scala.Some.apply scala.Some.apply[String](("There is too many translations : ".+(tooMany.mkString(",")).+(" on line ").+(lineNumber): String))
57 2106 2036 - 2226 TypeApply cats.syntax.ValidatedIdOpsBinCompat0.invalidNec cats.implicits.catsSyntaxValidatedIdBinCompat0[org.make.core.ValidationError](org.make.core.ValidationError.apply("contents", "too_many_translation", scala.Some.apply[String](("There is too many translations : ".+(tooMany.mkString(",")).+(" on line ").+(lineNumber): String)))).invalidNec[Nothing]
59 5334 2266 - 2294 Apply scala.collection.immutable.SetOps.diff languages.diff(languagesSet)
60 3980 2303 - 2484 Apply org.make.core.ValidationError.apply org.make.core.ValidationError.apply("content", "mismatch_translation", scala.Some.apply[String](("There is a translations mismatch : ".+(mismatch.mkString(",")).+(" on line ").+(lineNumber): String)))
61 4458 2330 - 2339 Literal <nosymbol> "content"
62 2400 2351 - 2373 Literal <nosymbol> "mismatch_translation"
63 462 2385 - 2474 Apply scala.Some.apply scala.Some.apply[String](("There is a translations mismatch : ".+(mismatch.mkString(",")).+(" on line ").+(lineNumber): String))
64 1728 2303 - 2495 TypeApply cats.syntax.ValidatedIdOpsBinCompat0.invalidNec cats.implicits.catsSyntaxValidatedIdBinCompat0[org.make.core.ValidationError](org.make.core.ValidationError.apply("content", "mismatch_translation", scala.Some.apply[String](("There is a translations mismatch : ".+(mismatch.mkString(",")).+(" on line ").+(lineNumber): String)))).invalidNec[Nothing]
72 765 2669 - 2669 Select cats.instances.ListInstances.catsStdInstancesForList org.make.api.technical.tracking.trackingapitest,org.make.api.demographics.demographicscardservicetest cats.implicits.catsStdInstancesForList
72 1907 2692 - 2692 ApplyToImplicitArgs cats.data.ValidatedInstances.catsDataApplicativeErrorForValidated org.make.api.technical.tracking.trackingapitest,org.make.api.demographics.demographicscardservicetest data.this.Validated.catsDataApplicativeErrorForValidated[cats.data.NonEmptyChain[org.make.core.ValidationError]](data.this.NonEmptyChainImpl.catsDataSemigroupForNonEmptyChain[org.make.core.ValidationError])
72 836 2669 - 3849 ApplyToImplicitArgs cats.Foldable.Ops.traverse_ org.make.api.technical.tracking.trackingapitest,org.make.api.demographics.demographicscardservicetest cats.implicits.toFoldableOps[List, (org.make.core.technical.Multilingual[_], String)](multilinguals)(cats.implicits.catsStdInstancesForList).traverse_[[+A]cats.data.Validated[cats.data.NonEmptyChain[org.make.core.ValidationError],A], Unit](((x0$1: (org.make.core.technical.Multilingual[_], String)) => x0$1 match { case (_1: org.make.core.technical.Multilingual[_], _2: String): (org.make.core.technical.Multilingual[_], String)((field @ _), (fieldName @ _)) => languagesSet.==(field.providedLanguages) match { case true => cats.implicits.catsSyntaxValidatedIdBinCompat0[Unit](()).validNec[Nothing] case false if languagesSet.sizeIs.>(field.providedLanguages.size) => { val missing: scala.collection.immutable.Set[org.make.core.reference.Language] = languagesSet.diff(field.providedLanguages); cats.implicits.catsSyntaxValidatedIdBinCompat0[org.make.core.ValidationError](org.make.core.ValidationError.apply(fieldName, "missing_translation", scala.Some.apply[String](("Field ".+(fieldName).+(" is missing translations for ").+(missing.mkString(",")): String)))).invalidNec[Nothing] } case false if languagesSet.sizeIs.<(field.providedLanguages.size) => { val tooMany: scala.collection.immutable.Set[org.make.core.reference.Language] = field.providedLanguages.diff(languagesSet); cats.implicits.catsSyntaxValidatedIdBinCompat0[org.make.core.ValidationError](org.make.core.ValidationError.apply(fieldName, "too_many_translation", scala.Some.apply[String](("Field ".+(fieldName).+(" has too many translations : ").+(tooMany.mkString(",")): String)))).invalidNec[Nothing] } case _ => { val mismatch: scala.collection.immutable.Set[org.make.core.reference.Language] = field.providedLanguages.diff(languagesSet); cats.implicits.catsSyntaxValidatedIdBinCompat0[org.make.core.ValidationError](org.make.core.ValidationError.apply(fieldName, "mismatch_translation", scala.Some.apply[String](("Field ".+(fieldName).+(" has mismatch translations : ").+(mismatch.mkString(",")): String)))).invalidNec[Nothing] } } }))(data.this.Validated.catsDataApplicativeErrorForValidated[cats.data.NonEmptyChain[org.make.core.ValidationError]](data.this.NonEmptyChainImpl.catsDataSemigroupForNonEmptyChain[org.make.core.ValidationError]))
72 3942 2692 - 2692 TypeApply cats.data.NonEmptyChainInstances.catsDataSemigroupForNonEmptyChain org.make.api.technical.tracking.trackingapitest,org.make.api.demographics.demographicscardservicetest data.this.NonEmptyChainImpl.catsDataSemigroupForNonEmptyChain[org.make.core.ValidationError]
74 4049 2752 - 2775 Select org.make.core.technical.Multilingual.providedLanguages org.make.api.technical.tracking.trackingapitest,org.make.api.demographics.demographicscardservicetest field.providedLanguages
74 2329 2736 - 2775 Apply java.lang.Object.== org.make.api.technical.tracking.trackingapitest,org.make.api.demographics.demographicscardservicetest languagesSet.==(field.providedLanguages)
75 5608 2807 - 2809 Literal <nosymbol> org.make.api.technical.tracking.trackingapitest,org.make.api.demographics.demographicscardservicetest ()
75 4513 2807 - 2818 TypeApply cats.syntax.ValidatedIdOpsBinCompat0.validNec org.make.api.technical.tracking.trackingapitest,org.make.api.demographics.demographicscardservicetest cats.implicits.catsSyntaxValidatedIdBinCompat0[Unit](()).validNec[Nothing]
76 2410 2865 - 2893 Select scala.collection.IterableOnceOps.size org.make.api.technical.tracking.trackingapitest,org.scalatest.testsuite field.providedLanguages.size
76 412 2843 - 2893 Apply scala.collection.IterableOps.SizeCompareOps.> org.make.api.technical.tracking.trackingapitest,org.scalatest.testsuite languagesSet.sizeIs.>(field.providedLanguages.size)
77 3985 2941 - 2964 Select org.make.core.technical.Multilingual.providedLanguages org.make.api.technical.tracking.trackingapitest field.providedLanguages
77 1740 2923 - 2965 Apply scala.collection.immutable.SetOps.diff org.make.api.technical.tracking.trackingapitest languagesSet.diff(field.providedLanguages)
78 2266 2978 - 3163 Apply org.make.core.ValidationError.apply org.make.api.technical.tracking.trackingapitest org.make.core.ValidationError.apply(fieldName, "missing_translation", scala.Some.apply[String](("Field ".+(fieldName).+(" is missing translations for ").+(missing.mkString(",")): String)))
80 888 3034 - 3055 Literal <nosymbol> org.make.api.technical.tracking.trackingapitest "missing_translation"
81 4058 3071 - 3149 Apply scala.Some.apply org.make.api.technical.tracking.trackingapitest scala.Some.apply[String](("Field ".+(fieldName).+(" is missing translations for ").+(missing.mkString(",")): String))
82 5615 2978 - 3174 TypeApply cats.syntax.ValidatedIdOpsBinCompat0.invalidNec org.make.api.technical.tracking.trackingapitest cats.implicits.catsSyntaxValidatedIdBinCompat0[org.make.core.ValidationError](org.make.core.ValidationError.apply(fieldName, "missing_translation", scala.Some.apply[String](("Field ".+(fieldName).+(" is missing translations for ").+(missing.mkString(",")): String)))).invalidNec[Nothing]
83 4525 3221 - 3249 Select scala.collection.IterableOnceOps.size org.scalatest.testsuite field.providedLanguages.size
83 2521 3199 - 3249 Apply scala.collection.IterableOps.SizeCompareOps.< org.scalatest.testsuite languagesSet.sizeIs.<(field.providedLanguages.size)
84 615 3279 - 3321 Apply scala.collection.immutable.SetOps.diff field.providedLanguages.diff(languagesSet)
85 899 3334 - 3520 Apply org.make.core.ValidationError.apply org.make.core.ValidationError.apply(fieldName, "too_many_translation", scala.Some.apply[String](("Field ".+(fieldName).+(" has too many translations : ").+(tooMany.mkString(",")): String)))
87 3934 3390 - 3412 Literal <nosymbol> "too_many_translation"
88 1900 3428 - 3506 Apply scala.Some.apply scala.Some.apply[String](("Field ".+(fieldName).+(" has too many translations : ").+(tooMany.mkString(",")): String))
89 4162 3334 - 3531 TypeApply cats.syntax.ValidatedIdOpsBinCompat0.invalidNec cats.implicits.catsSyntaxValidatedIdBinCompat0[org.make.core.ValidationError](org.make.core.ValidationError.apply(fieldName, "too_many_translation", scala.Some.apply[String](("Field ".+(fieldName).+(" has too many translations : ").+(tooMany.mkString(",")): String)))).invalidNec[Nothing]
91 2273 3579 - 3621 Apply scala.collection.immutable.SetOps.diff org.scalatest.testsuite field.providedLanguages.diff(languagesSet)
92 2531 3634 - 3821 Apply org.make.core.ValidationError.apply org.scalatest.testsuite org.make.core.ValidationError.apply(fieldName, "mismatch_translation", scala.Some.apply[String](("Field ".+(fieldName).+(" has mismatch translations : ").+(mismatch.mkString(",")): String)))
94 5621 3690 - 3712 Literal <nosymbol> org.scalatest.testsuite "mismatch_translation"
95 3540 3728 - 3807 Apply scala.Some.apply org.scalatest.testsuite scala.Some.apply[String](("Field ".+(fieldName).+(" has mismatch translations : ").+(mismatch.mkString(",")): String))
96 403 3634 - 3832 TypeApply cats.syntax.ValidatedIdOpsBinCompat0.invalidNec org.scalatest.testsuite cats.implicits.catsSyntaxValidatedIdBinCompat0[org.make.core.ValidationError](org.make.core.ValidationError.apply(fieldName, "mismatch_translation", scala.Some.apply[String](("Field ".+(fieldName).+(" has mismatch translations : ").+(mismatch.mkString(",")): String)))).invalidNec[Nothing]
105 4316 4066 - 5013 Apply io.circe.Decoder.flatMap decoder.flatMap[A](((t: A) => { val langs: Set[org.make.core.reference.Language] = langsF.apply(t); def findErrors(c: io.circe.HCursor): Iterator[io.circe.DecodingFailure] = requiredF.apply(t).iterator.++[(org.make.core.technical.Multilingual[_], String)](optionalF.apply(t).iterator.flatten[(org.make.core.technical.Multilingual[_], String)](scala.Predef.$conforms[Option[(org.make.core.technical.Multilingual[_], String)]])).flatMap[io.circe.DecodingFailure](((x0$1: (org.make.core.technical.Multilingual[_], String)) => x0$1 match { case (_1: org.make.core.technical.Multilingual[_], _2: String): (org.make.core.technical.Multilingual[_], String)((field @ _), (fieldName @ _)) => langs.diff(field.providedLanguages) match { case (missing @ _) if missing.nonEmpty => { val ac: io.circe.ACursor = c.downField(fieldName); scala.Some.apply[io.circe.DecodingFailure](io.circe.DecodingFailure.apply(("Missing translations: ".+(missing.mkString(", ")): String), ac.history)) } case _ => scala.None } })); { final class $anon extends AnyRef with io.circe.Decoder[A] { def <init>(): <$anon: io.circe.Decoder[A]> = { $anon.super.<init>(); () }; override def apply(c: io.circe.HCursor): io.circe.Decoder.Result[A] = findErrors(c).nextOption().toLeft[A](t); override def decodeAccumulating(c: io.circe.HCursor): io.circe.Decoder.AccumulatingResult[A] = findErrors(c).toList match { case (head: io.circe.DecodingFailure, next: List[io.circe.DecodingFailure]): scala.collection.immutable.::[io.circe.DecodingFailure]((hd @ _), (tl @ _)) => cats.data.Validated.Invalid.apply[cats.data.NonEmptyList[io.circe.DecodingFailure]](cats.data.NonEmptyList.apply[io.circe.DecodingFailure](hd, tl)) case scala.`package`.Nil => cats.data.Validated.Valid.apply[A](t) } }; new $anon() } }))
106 4047 4107 - 4116 Apply scala.Function1.apply langsF.apply(t)
109 5577 4187 - 4216 ApplyToImplicitArgs scala.collection.Iterator.flatten optionalF.apply(t).iterator.flatten[(org.make.core.technical.Multilingual[_], String)](scala.Predef.$conforms[Option[(org.make.core.technical.Multilingual[_], String)]])
109 5612 4162 - 4590 Apply scala.collection.Iterator.flatMap requiredF.apply(t).iterator.++[(org.make.core.technical.Multilingual[_], String)](optionalF.apply(t).iterator.flatten[(org.make.core.technical.Multilingual[_], String)](scala.Predef.$conforms[Option[(org.make.core.technical.Multilingual[_], String)]])).flatMap[io.circe.DecodingFailure](((x0$1: (org.make.core.technical.Multilingual[_], String)) => x0$1 match { case (_1: org.make.core.technical.Multilingual[_], _2: String): (org.make.core.technical.Multilingual[_], String)((field @ _), (fieldName @ _)) => langs.diff(field.providedLanguages) match { case (missing @ _) if missing.nonEmpty => { val ac: io.circe.ACursor = c.downField(fieldName); scala.Some.apply[io.circe.DecodingFailure](io.circe.DecodingFailure.apply(("Missing translations: ".+(missing.mkString(", ")): String), ac.history)) } case _ => scala.None } }))
109 2117 4209 - 4209 TypeApply scala.Predef.$conforms scala.Predef.$conforms[Option[(org.make.core.technical.Multilingual[_], String)]]
111 2478 4277 - 4312 Apply scala.collection.immutable.SetOps.diff langs.diff(field.providedLanguages)
111 3544 4288 - 4311 Select org.make.core.technical.Multilingual.providedLanguages field.providedLanguages
112 409 4351 - 4367 Select scala.collection.IterableOnceOps.nonEmpty missing.nonEmpty
113 3783 4396 - 4418 Apply io.circe.HCursor.downField c.downField(fieldName)
114 1840 4508 - 4518 Select io.circe.ACursor.history ac.history
114 847 4440 - 4519 Apply io.circe.DecodingFailure.apply io.circe.DecodingFailure.apply(("Missing translations: ".+(missing.mkString(", ")): String), ac.history)
114 4304 4435 - 4520 Apply scala.Some.apply scala.Some.apply[io.circe.DecodingFailure](io.circe.DecodingFailure.apply(("Missing translations: ".+(missing.mkString(", ")): String), ac.history))
117 2066 4562 - 4566 Select scala.None scala.None
121 5111 4598 - 4601 Apply org.make.core.technical.MultilingualUtils.$anon.<init> new $anon()
123 3492 4685 - 4721 Apply scala.Option.toLeft findErrors(c).nextOption().toLeft[A](t)
126 2667 4818 - 4838 Select scala.collection.IterableOnceOps.toList findErrors(c).toList
128 3717 4890 - 4929 Apply cats.data.Validated.Invalid.apply cats.data.Validated.Invalid.apply[cats.data.NonEmptyList[io.circe.DecodingFailure]](cats.data.NonEmptyList.apply[io.circe.DecodingFailure](hd, tl))
128 421 4908 - 4928 Apply cats.data.NonEmptyList.apply cats.data.NonEmptyList.apply[io.circe.DecodingFailure](hd, tl)
131 2003 4969 - 4987 Apply cats.data.Validated.Valid.apply cats.data.Validated.Valid.apply[A](t)
148 5570 5655 - 5705 Apply io.circe.Decoder.flatMap org.make.api.operation.defaultmoderationoperationofquestionapicomponenttest,org.make.core.technical.multilingualtest decoder.flatMap[A](((a: A) => new org.make.core.technical.MultilingualUtils.GenDecoder[A,Repr](a, langsF.apply(a))(gen, keys, values)))
148 2073 5676 - 5704 ApplyToImplicitArgs org.make.core.technical.MultilingualUtils.GenDecoder.<init> org.make.core.technical.multilingualtest new org.make.core.technical.MultilingualUtils.GenDecoder[A,Repr](a, langsF.apply(a))(gen, keys, values)
163 3648 6205 - 6224 Select org.make.core.technical.Multilingual.providedLanguages org.make.core.technical.multilingualtest x.providedLanguages
163 2599 6194 - 6225 Apply scala.collection.immutable.SetOps.diff org.make.core.technical.multilingualtest GenDecoder.this.langs.diff(x.providedLanguages)
164 696 6260 - 6276 Select scala.collection.IterableOnceOps.nonEmpty org.make.core.technical.multilingualtest missing.nonEmpty
165 3938 6377 - 6383 Select scala.Symbol.name k.name
165 1958 6365 - 6392 Select io.circe.ACursor.history c.downField(k.name).history
165 5154 6297 - 6393 Apply io.circe.DecodingFailure.apply org.make.core.technical.multilingualtest io.circe.DecodingFailure.apply(("Missing translations: ".+(missing.mkString(", ")): String), c.downField(k.name).history)
165 4328 6292 - 6394 Apply scala.util.Left.apply org.make.core.technical.multilingualtest scala.`package`.Left.apply[io.circe.DecodingFailure, Nothing](io.circe.DecodingFailure.apply(("Missing translations: ".+(missing.mkString(", ")): String), c.downField(k.name).history))
166 2351 6415 - 6424 Apply scala.util.Right.apply org.make.core.technical.multilingualtest scala.`package`.Right.apply[Nothing, Unit](())
177 5574 6816 - 6829 Select scala.collection.LinearSeqOps.headOption org.make.core.technical.multilingualtest xs.headOption
177 3594 6798 - 6830 Apply scala.Option.zip org.make.core.technical.multilingualtest ks.headOption.zip[Any, Any](xs.headOption)
178 707 6862 - 6870 Apply scala.util.Right.apply org.make.core.technical.multilingualtest scala.`package`.Right.apply[Nothing, A](GenDecoder.this.a)
178 1523 6868 - 6869 Select org.make.core.technical.MultilingualUtils.GenDecoder.a org.make.core.technical.multilingualtest GenDecoder.this.a
181 3874 6940 - 6956 Apply org.make.core.technical.MultilingualUtils.GenDecoder.doValidate org.make.core.technical.multilingualtest doValidate(x, k)
183 1965 7013 - 7022 Apply scala.util.Left.apply org.make.core.technical.multilingualtest scala.`package`.Left.apply[io.circe.DecodingFailure, Nothing](err)
185 2209 7063 - 7089 Apply org.make.core.technical.MultilingualUtils.GenDecoder.recApply org.make.core.technical.multilingualtest recApply(ks.tail, xs.tail)
185 4114 7081 - 7088 Select scala.collection.IterableOps.tail org.make.core.technical.multilingualtest xs.tail
185 5160 7072 - 7079 Select scala.collection.IterableOps.tail org.make.core.technical.multilingualtest ks.tail
189 5518 7179 - 7195 Apply org.make.core.technical.MultilingualUtils.GenDecoder.doValidate org.make.core.technical.multilingualtest doValidate(x, k)
191 3487 7252 - 7261 Apply scala.util.Left.apply scala.`package`.Left.apply[io.circe.DecodingFailure, Nothing](err)
193 3884 7302 - 7328 Apply org.make.core.technical.MultilingualUtils.GenDecoder.recApply org.make.core.technical.multilingualtest recApply(ks.tail, xs.tail)
193 1529 7311 - 7318 Select scala.collection.IterableOps.tail org.make.core.technical.multilingualtest ks.tail
193 473 7320 - 7327 Select scala.collection.IterableOps.tail org.make.core.technical.multilingualtest xs.tail
196 5109 7382 - 7389 Select scala.collection.IterableOps.tail org.make.core.technical.multilingualtest xs.tail
196 4125 7364 - 7390 Apply org.make.core.technical.MultilingualUtils.GenDecoder.recApply org.make.core.technical.multilingualtest recApply(ks.tail, xs.tail)
196 1917 7373 - 7380 Select scala.collection.IterableOps.tail org.make.core.technical.multilingualtest ks.tail
201 2338 7531 - 7537 Apply shapeless.DepFn0.apply org.make.core.technical.multilingualtest GenDecoder.this.keys.apply()
201 693 7551 - 7568 Apply shapeless.DepFn1.apply org.make.core.technical.multilingualtest GenDecoder.this.values.apply(GenDecoder.this.gen.to(GenDecoder.this.a))
201 3497 7565 - 7566 Select org.make.core.technical.MultilingualUtils.GenDecoder.a org.make.core.technical.multilingualtest GenDecoder.this.a
201 1481 7558 - 7567 Apply shapeless.LabelledGeneric.to org.make.core.technical.multilingualtest GenDecoder.this.gen.to(GenDecoder.this.a)
201 3993 7551 - 7580 Select shapeless.syntax.HListOps.runtimeList org.make.core.technical.multilingualtest shapeless.this.HList.hlistOps[GenDecoder.this.values.Out](GenDecoder.this.values.apply(GenDecoder.this.gen.to(GenDecoder.this.a))).runtimeList
201 5527 7531 - 7549 Select shapeless.syntax.HListOps.runtimeList org.make.core.technical.multilingualtest shapeless.this.HList.hlistOps[GenDecoder.this.keys.Out](GenDecoder.this.keys.apply()).runtimeList
201 1926 7522 - 7581 Apply org.make.core.technical.MultilingualUtils.GenDecoder.recApply org.make.core.technical.multilingualtest recApply(shapeless.this.HList.hlistOps[GenDecoder.this.keys.Out](GenDecoder.this.keys.apply()).runtimeList, shapeless.this.HList.hlistOps[GenDecoder.this.values.Out](GenDecoder.this.values.apply(GenDecoder.this.gen.to(GenDecoder.this.a))).runtimeList)