<commit_before>import sbt._

/**
 * Generate a range of boilerplate classes that would be tedious to craft by hand.
 *
 * Copied, with modifications, from
 * [[https://github.com/milessabin/shapeless/blob/master/project/Boilerplate.scala Shapeless]].
 *
 * @author <NAME>
 * @author <NAME>
 */
object Boilerplate {
  import scala.StringContext._

  implicit class BlockHelper(val sc: StringContext) extends AnyVal {
    def block(args: Any*): String = {
      val interpolated = sc.standardInterpolator(treatEscapes, args)
      val rawLines = interpolated split '\n'
      val trimmedLines = rawLines map { _ dropWhile (_.isWhitespace) }
      trimmedLines mkString "\n"
    }
  }

  val templates: Seq[Template] = Seq(
    GenProductReaders,
    GenProductWriters)

  val testTemplates: Seq[Template] = Seq(
    GenProductTests)

  val header = "// auto-generated boilerplate"
  val maxArity = 22

  /**
   * Returns a seq of the generated files. As a side-effect, it actually generates them...
   */
  def gen(dir : File) = for (t <- templates) yield {
    val tgtFile = t.filename(dir)
    IO.write(tgtFile, t.body)
    tgtFile
  }

  /**
   * Return a sequence of the generated test files. As a side-effect, it actually generates them...
   */
  def genTests(dir: File): Seq[File] = testTemplates.map { template =>
    val tgtFile = template.filename(dir)
    IO.write(tgtFile, template.body)
    tgtFile
  }

  class TemplateVals(val arity: Int) {
    val synTypes = (0 until arity).map(n => s"A$n")
    val synVals = (0 until arity).map(n => s"a$n")

    val `A..N` = synTypes.mkString(", ")
  }

  /**
   * Blocks in the templates below use a custom interpolator, combined with post-processing to
   * produce the body.
   *
   * - The contents of the `header` val is output first
   * - Then the first block of lines beginning with '|'
   * - Then the block of lines beginning with '-' is replicated once for each arity,
   *   with the `templateVals` already pre-populated with relevant relevant vals for that arity
   * - Then the last block of lines prefixed with '|'
   *
   * The block otherwise behaves as a standard interpolated string with regards to variable
   * substitution.
   */
  trait Template {
    def filename(root: File): File
    def content(tv: TemplateVals): String
    def range: IndexedSeq[Int] = 1 to maxArity
    def body: String = {
      val headerLines = header.split('\n')
      val raw = range.map(n => content(new TemplateVals(n)).split('\n').filterNot(_.isEmpty))
      val preBody = raw.head.takeWhile(_.startsWith("|")).map(_.tail)
      val instances = raw.flatMap(_.filter(_.startsWith("-")).map(_.tail))
      val postBody = raw.head.dropWhile(_.startsWith("|")).dropWhile(_.startsWith("-")).map(_.tail)
      (headerLines ++ preBody ++ instances ++ postBody).mkString("\n")
    }
  }

  object GenProductReaders extends Template {
    def filename(root: sbt.File) = root / "pureconfig" / "ProductReaders.scala"

    def content(tv: TemplateVals): String = {
      import tv._

      val paramNames = synTypes.map(tpe => s"key$tpe: String").mkString(", ")
      val readerInstances = synTypes.map(tpe => s"reader$tpe: ConfigReader[$tpe]").mkString(", ")

      val results = synTypes.zip(synVals).map { case (tpe, v) =>
        s"""
           |-        val ${v}Result = objCur.atKeyOrUndefined(key$tpe) match {
           |-          case cur if cur.isUndefined =>
           |-            if (reader$tpe.isInstanceOf[AllowMissingKey])
           |-              reader$tpe.from(cur)
           |-            else
           |-              objCur.failed(KeyNotFound.forKeys(key$tpe, objCur.keys))
           |-          case cur => reader$tpe.from(cur)
           |-        }
           |-
         """.stripMargin
      }.mkString("\n")

      val curriedTypes = synTypes.mkString(" => ")

      val resultCombination = synVals.foldLeft("baseF") { case (curr, v) =>
        s"ConvertHelpers.combineResults($curr, ${v}Result)(_(_))"
      }

      block"""
        |package pureconfig
        |
        |import pureconfig.error._
        |
        |private[pureconfig] trait ProductReaders {
        -
        -  final def forProduct$arity[B, ${`A..N`}]($paramNames)(f: (${`A..N`}) => B)(implicit
        -    $readerInstances
        -  ): ConfigReader[B] = new ConfigReader[B] {
        -    def from(cur: ConfigCursor): Either[ConfigReaderFailures, B] =
        -      cur.asObjectCursor.right.flatMap { objCur =><commit_msg>Simplify generated readers<commit_after>import sbt._

/**
 * Generate a range of boilerplate classes that would be tedious to craft by hand.
 *
 * Copied, with modifications, from
 * [[https://github.com/milessabin/shapeless/blob/master/project/Boilerplate.scala Shapeless]].
 *
 * @author <NAME>
 * @author <NAME>
 */
object Boilerplate {
  import scala.StringContext._

  implicit class BlockHelper(val sc: StringContext) extends AnyVal {
    def block(args: Any*): String = {
      val interpolated = sc.standardInterpolator(treatEscapes, args)
      val rawLines = interpolated split '\n'
      val trimmedLines = rawLines map { _ dropWhile (_.isWhitespace) }
      trimmedLines mkString "\n"
    }
  }

  val templates: Seq[Template] = Seq(
    GenProductReaders,
    GenProductWriters)

  val testTemplates: Seq[Template] = Seq(
    GenProductTests)

  val header = "// auto-generated boilerplate"
  val maxArity = 22

  /**
   * Returns a seq of the generated files. As a side-effect, it actually generates them...
   */
  def gen(dir : File) = for (t <- templates) yield {
    val tgtFile = t.filename(dir)
    IO.write(tgtFile, t.body)
    tgtFile
  }

  /**
   * Return a sequence of the generated test files. As a side-effect, it actually generates them...
   */
  def genTests(dir: File): Seq[File] = testTemplates.map { template =>
    val tgtFile = template.filename(dir)
    IO.write(tgtFile, template.body)
    tgtFile
  }

  class TemplateVals(val arity: Int) {
    val synTypes = (0 until arity).map(n => s"A$n")
    val synVals = (0 until arity).map(n => s"a$n")

    val `A..N` = synTypes.mkString(", ")
  }

  /**
   * Blocks in the templates below use a custom interpolator, combined with post-processing to
   * produce the body.
   *
   * - The contents of the `header` val is output first
   * - Then the first block of lines beginning with '|'
   * - Then the block of lines beginning with '-' is replicated once for each arity,
   *   with the `templateVals` already pre-populated with relevant relevant vals for that arity
   * - Then the last block of lines prefixed with '|'
   *
   * The block otherwise behaves as a standard interpolated string with regards to variable
   * substitution.
   */
  trait Template {
    def filename(root: File): File
    def content(tv: TemplateVals): String
    def range: IndexedSeq[Int] = 1 to maxArity
    def body: String = {
      val headerLines = header.split('\n')
      val raw = range.map(n => content(new TemplateVals(n)).split('\n').filterNot(_.isEmpty))
      val preBody = raw.head.takeWhile(_.startsWith("|")).map(_.tail)
      val instances = raw.flatMap(_.filter(_.startsWith("-")).map(_.tail))
      val postBody = raw.head.dropWhile(_.startsWith("|")).dropWhile(_.startsWith("-")).map(_.tail)
      (headerLines ++ preBody ++ instances ++ postBody).mkString("\n")
    }
  }

  object GenProductReaders extends Template {
    def filename(root: sbt.File) = root / "pureconfig" / "ProductReaders.scala"

    def content(tv: TemplateVals): String = {
      import tv._

      val paramNames = synTypes.map(tpe => s"key$tpe: String").mkString(", ")
      val readerInstances = synTypes.map(tpe => s"reader$tpe: ConfigReader[$tpe]").mkString(", ")

      val results = synTypes.zip(synVals).map { case (tpe, v) =>
        s"""
           |-        val ${v}Result = if (reader$tpe.isInstanceOf[AllowMissingKey]) reader$tpe.from(objCur.atKeyOrUndefined(key$tpe)) else objCur.atKey(key$tpe).right.flatMap(reader$tpe.from)
         """.stripMargin
      }.mkString("\n")

      val curriedTypes = synTypes.mkString(" => ")

      val resultCombination = synVals.foldLeft("baseF") { case (curr, v) =>
        s"ConvertHelpers.combineResults($curr, ${v}Result)(_(_))"
      }

      block"""
        |package pureconfig
        |
        |import pureconfig.error._
        |
        |private[pureconfig] trait ProductReaders {
        -
        -  final def forProduct$arity[B, ${`A..N`}]($paramNames)(f: (${`A..N`}) => B)(implicit
        -    $readerInstances
        -  ): ConfigReader[B] = new ConfigReader[B] {
        -    def from(cur: ConfigCursor): Either[ConfigReaderFailures, B] =
        -      cur.asObjectCursor.right.flatMap { objCur =>
{'fraction_non_alphanumeric': 0.13330268903700299, 'fraction_numerical': 0.0011491611123879567, 'mean_word_length': 2.7659022068368673, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 31, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '891281', 'n_tokens_mistral': 2800, 'n_tokens_neox': 2731, 'n_words': 708}