cats.data.NonEmptyChain Scala Examples

The following examples show how to use cats.data.NonEmptyChain. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: Metadata.scala    From sonar-scala   with GNU Lesser General Public License v3.0 5 votes vote down vote up
package com.mwz.sonar.scala

import java.nio.file.Paths
import java.nio.file.StandardOpenOption

import cats.data.NonEmptyChain
import cats.effect.Blocker
import cats.effect.ExitCode
import cats.effect.IO
import cats.effect.IOApp
import cats.instances.string._
import com.mwz.sonar.scala.metadata._
import com.mwz.sonar.scala.metadata.scalastyle.ScalastyleRules
import com.mwz.sonar.scala.metadata.scalastyle.ScalastyleRulesRepository
import com.mwz.sonar.scala.metadata.scapegoat.ScapegoatRules
import com.mwz.sonar.scala.metadata.scapegoat.ScapegoatRulesRepository
import fs2.Stream
import fs2.io.file._
import fs2.text
import io.circe.Printer
import io.circe.generic.JsonCodec
import io.circe.syntax._

@JsonCodec
final case class SonarScalaMetadata(
  rules: Rules,
  repositories: Map[String, RulesRepository]
)

@JsonCodec
final case class Rules(
  scalastyle: NonEmptyChain[Rule],
  scapegoat: NonEmptyChain[Rule]
)

object Metadata extends IOApp {
  private val metadata: SonarScalaMetadata =
    SonarScalaMetadata(
      rules = Rules(sort(ScalastyleRules.rules), sort(ScapegoatRules.rules)),
      repositories = Map(
        ScalastyleRulesRepository.RepositoryKey ->
        ScalastyleRulesRepository.rulesRepository
          .copy(rules = sort(ScalastyleRulesRepository.rulesRepository.rules)),
        ScapegoatRulesRepository.RepositoryKey ->
        ScapegoatRulesRepository.rulesRepository
          .copy(rules = sort(ScapegoatRulesRepository.rulesRepository.rules))
      )
    )
  private val printer: Printer =
    Printer.spaces2SortKeys.copy(
      colonLeft = "",
      lbraceLeft = "",
      rbraceRight = "",
      lbracketLeft = "",
      lrbracketsEmpty = "",
      rbracketRight = "",
      arrayCommaLeft = "",
      objectCommaLeft = ""
    )

  // Chain is missing sortBy, which should be added in 2.2.0.
  private def sort(rules: NonEmptyChain[Rule]): NonEmptyChain[Rule] =
    NonEmptyChain.fromNonEmptyList(rules.toNonEmptyList.sortBy(_.name))

  def run(args: List[String]): IO[ExitCode] = {
    val write: Stream[IO, Unit] = Stream.resource(Blocker[IO]).flatMap { blocker =>
      Stream[IO, String](metadata.asJson.printWith(printer))
        .through(text.utf8Encode)
        .through(
          writeAll(
            Paths.get("sonar-scala-metadata.json"),
            blocker,
            List(StandardOpenOption.TRUNCATE_EXISTING)
          )
        )
    }
    write.compile.drain.as(ExitCode.Success)
  }
} 
Example 2
Source File: ScalastyleRulesRepository.scala    From sonar-scala   with GNU Lesser General Public License v3.0 5 votes vote down vote up
package com.mwz.sonar.scala.metadata
package scalastyle

import cats.data.NonEmptyChain

object ScalastyleRulesRepository {
  final val RepositoryKey: String = "sonar-scala-scalastyle"
  final val RepositoryName: String = "Scalastyle"
  final val RuleClassParam: String = "ruleClass"

  // Skip creating template instances for the following inspections.
  final val SkipTemplateInstances: Set[String] = Set(
    // this rule wouldn't work with a default parameter value
    "org.scalastyle.file.HeaderMatchesChecker",
    // no default regex provided
    "org.scalastyle.file.RegexChecker",
    // incorrect default value of the ignoreRegex parameter
    "org.scalastyle.scalariform.ScalaDocChecker"
  )

  lazy val rulesRepository: RulesRepository =
    RulesRepository(
      key = RepositoryKey,
      name = RepositoryName,
      rules = ScalastyleRules.rules.flatMap(fromTemplate)
    )

  
  private[metadata] def extraParam(key: String): Param =
    Param(
      name = RuleClassParam,
      typ = ParamType.String,
      description = "Scalastyle's rule (checker) class name.",
      default = key
    )
} 
Example 3
Source File: model.scala    From sonar-scala   with GNU Lesser General Public License v3.0 5 votes vote down vote up
package com.mwz.sonar.scala.metadata

import cats.data.Chain
import cats.data.NonEmptyChain
import enumeratum._
import io.circe._
import io.circe.generic.JsonCodec
import io.circe.generic.encoding._
import org.sonar.api.server.rule.RuleParamType
import shapeless._
import shapeless.record._

@JsonCodec
final case class RulesRepository(
  key: String,
  name: String,
  rules: NonEmptyChain[Rule]
)

object Rule {
  implicit val ruleEncoder: Encoder[Rule] =
    ReprObjectEncoder.deriveReprAsObjectEncoder.contramap { rule =>
      LabelledGeneric[Rule]
        .to(rule)
        .-(Symbol("sonarMdDescription"))
        .renameField(Symbol("mdDescription"), Symbol("description"))
    }
}

@JsonCodec(decodeOnly = true)
final case class Rule(
  key: String,
  name: String,
  mdDescription: String,
  sonarMdDescription: String,
  severity: Severity,
  template: Boolean,
  params: Chain[Param]
)

@JsonCodec
final case class Param(
  name: String,
  typ: ParamType,
  description: String,
  default: String
)

sealed trait ParamType extends EnumEntry
object ParamType extends Enum[ParamType] with CirceEnum[ParamType] with CatsEnum[ParamType] {
  final case object String extends ParamType
  final case object Text extends ParamType
  final case object Boolean extends ParamType
  final case object Integer extends ParamType
  final case object Float extends ParamType
  val values = findValues

  implicit class ParamTypeSyntax(private val paramType: ParamType) extends AnyVal {
    def asSonarRuleParamType: RuleParamType =
      paramType match {
        case String  => RuleParamType.STRING
        case Text    => RuleParamType.TEXT
        case Boolean => RuleParamType.BOOLEAN
        case Integer => RuleParamType.INTEGER
        case Float   => RuleParamType.FLOAT
      }
  }
}

sealed trait Severity extends EnumEntry
object Severity extends Enum[Severity] with CirceEnum[Severity] with CatsEnum[Severity] {
  final case object Info extends Severity
  final case object Minor extends Severity
  final case object Major extends Severity
  final case object Critical extends Severity
  final case object Blocker extends Severity
  val values = findValues
} 
Example 4
Source File: ScapegoatRules.scala    From sonar-scala   with GNU Lesser General Public License v3.0 5 votes vote down vote up
package com.mwz.sonar.scala.metadata
package scapegoat

import cats.data.Chain
import cats.data.NonEmptyChain

object ScapegoatRules {
  // TODO: Refactor AllInspections to be a NonEmptyChain.
  lazy val rules: NonEmptyChain[Rule] =
    NonEmptyChain.fromChainUnsafe(
      Chain.fromSeq(ScapegoatInspections.AllInspections.map(toRule))
    )

  private[metadata] def toRule(inspection: ScapegoatInspection): Rule = {
    Rule(
      key = inspection.id,
      name = inspection.name.replaceAll("`", ""),
      mdDescription = mdDescription(inspection),
      sonarMdDescription = sonarMdDescription(inspection),
      severity = toSeverity(inspection.defaultLevel),
      template = false,
      params = Chain.empty
    )
  }

  private[metadata] def mdDescription(inspection: ScapegoatInspection): String =
    s"*${inspection.description}*" +
    s"\n\n${inspection.explanation}"

  // SonarQube's markdown parser converts any '=' characters in the middle of a sentence
  // into headings, so we're using a 7th level heading (which doesn't have any style properties)
  // to make it ignore the '=' characters and make it look like regular text.
  // Any inline code blocks between `` are also ignored until Scapegoat has all code blocks wrapped in ``.
  private[metadata] def sonarMdDescription(inspection: ScapegoatInspection): String =
    s"*${inspection.description.replaceAll("`", "")}*" +
    s"\n\n======= ${inspection.explanation.replaceAll("`", "")}"

  private[metadata] def toSeverity(level: Level): Severity =
    level match {
      case Level.Error   => Severity.Major
      case Level.Warning => Severity.Minor
      case Level.Info    => Severity.Info
    }
} 
Example 5
Source File: ScalastyleRulesReposotorySpec.scala    From sonar-scala   with GNU Lesser General Public License v3.0 5 votes vote down vote up
package com.mwz.sonar.scala.metadata
package scalastyle

import cats.data.Chain
import cats.data.NonEmptyChain
import enumeratum.scalacheck._
import org.scalacheck.Prop._
import org.scalacheck.Prop._
import org.scalacheck.ScalacheckShapeless._
import org.scalacheck._
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import org.scalatestplus.scalacheck.Checkers
import org.scalatestplus.scalacheck.ScalaCheckDrivenPropertyChecks

class ScalastyleRulesRepositorySpec
    extends AnyFlatSpec
    with Matchers
    with ScalaCheckDrivenPropertyChecks
    with Checkers {

  implicit def chainArbOf[T](implicit a: Arbitrary[T]): Arbitrary[Chain[T]] =
    Arbitrary(Gen.listOf[T](a.arbitrary).map(Chain.apply))

  def nonEmptyChainOf[T](implicit a: Arbitrary[T]): Gen[Chain[T]] =
    Gen.nonEmptyListOf[T](a.arbitrary).map(Chain.apply)

  it should "not create an additional rule from a non-template rule" in {
    forAll { rule: Rule =>
      val extraParam = ScalastyleRulesRepository.extraParam(rule.key)
      val expected = rule.copy(
        template = false,
        params = Chain(extraParam)
      )
      ScalastyleRulesRepository.fromTemplate(rule.copy(params = Chain.empty)) shouldBe NonEmptyChain.one(
        expected
      )
    }
  }

  it should "not create an additional rule if the instance is blacklisted" in {
    check(
      forAllNoShrink(
        Arbitrary.arbitrary[Rule],
        nonEmptyChainOf[Param],
        Gen.oneOf(ScalastyleRulesRepository.SkipTemplateInstances.toList)
      ) { (rule, params, className) =>
        val newRule = rule.copy(key = className, params = params)
        val extraParam = ScalastyleRulesRepository.extraParam(newRule.key)
        val expected = newRule.copy(
          key = className + "-template",
          template = true,
          params = params :+ extraParam
        )

        ScalastyleRulesRepository.fromTemplate(newRule) === NonEmptyChain.one(expected)
      }
    )
  }

  it should "create an additional rule for templates" in {
    check(
      forAllNoShrink(
        Arbitrary.arbitrary[Rule],
        nonEmptyChainOf[Param]
      ) { (rule, params) =>
        val newRule = rule.copy(params = params)
        val extraParam = ScalastyleRulesRepository.extraParam(newRule.key)
        val instance = newRule.copy(
          template = false,
          params = params :+ extraParam
        )
        val template = instance.copy(
          key = instance.key + "-template",
          template = true
        )

        ScalastyleRulesRepository.fromTemplate(newRule) === NonEmptyChain(template, instance)
      }
    )
  }

  it should "create an additional param with scalastyle class name" in {
    val expected = Param(
      name = "ruleClass",
      typ = ParamType.String,
      description = "Scalastyle's rule (checker) class name.",
      default = "scalastyle.class.name.test"
    )

    ScalastyleRulesRepository.extraParam("scalastyle.class.name.test") shouldBe expected
  }
} 
Example 6
Source File: UnusedLetCheck.scala    From bosatsu   with Apache License 2.0 5 votes vote down vote up
package org.bykn.bosatsu

import cats.Applicative
import cats.data.{Chain, Validated, ValidatedNec, Writer, NonEmptyChain}
import cats.implicits._

import Expr._
import Identifier.Bindable

object UnusedLetCheck {

  private[this] val ap = Applicative[Writer[Chain[(Bindable, Region)], ?]]
  private[this] val empty: Writer[Chain[(Bindable, Region)], Set[Bindable]] = ap.pure(Set.empty)

  private[this] def checkArg(arg: Bindable, reg: => Region, w: Writer[Chain[(Bindable, Region)], Set[Bindable]]) =
    w.flatMap { free =>
      if (free(arg)) ap.pure(free - arg)
      else {
        // this arg is free:
        ap.pure(free).tell(Chain.one((arg, reg)))
      }
    }

  private[this] def loop[A: HasRegion](e: Expr[A]): Writer[Chain[(Bindable, Region)], Set[Bindable]] =
    e match {
      case Annotation(expr, _, _) =>
        loop(expr)
      case AnnotatedLambda(arg, _, expr, _) =>
        checkArg(arg, HasRegion.region(e), loop(expr))
      case Lambda(arg, expr, _) =>
        checkArg(arg, HasRegion.region(e), loop(expr))
      case Let(arg, expr, in, rec, _) =>
        val exprCheck = loop(expr)
        val exprRes =
          // if it is recursive, it is definitely used, because
          // that is automatically applied in source conversions
          if (rec.isRecursive) exprCheck.map(_ - arg) else exprCheck
        val inCheck = checkArg(arg, HasRegion.region(e), loop(in))
        (exprRes, inCheck).mapN(_ ++ _)
      case Var(None, name: Bindable, _) =>
        // this is a free variable:
        ap.pure(Set(name))
      case Var(_, _, _) | Literal(_, _) => empty
      case App(fn, arg, _) =>
        (loop(fn), loop(arg)).mapN(_ ++ _)
      case Match(arg, branches, _) =>
        // TODO: patterns need their own region
        val argCheck = loop(arg)
        val bcheck = branches.traverse { case (pat, expr) =>
          val region = HasRegion.region(expr)
          loop(expr).flatMap { frees =>
            val thisPatNames = pat.names
            val unused = thisPatNames.filterNot(frees)
            val nextFrees = frees -- thisPatNames

            ap.pure(nextFrees).tell(Chain.fromSeq(unused.map((_, region))))
          }
        }
        .map(_.combineAll)

      (argCheck, bcheck).mapN(_ ++ _)
    }

  
  def freeBound[A](e: Expr[A]): Set[Bindable] =
    loop(e)(HasRegion.instance(_ => Region(0, 0))).run._2
} 
Example 7
Source File: BankingException.scala    From frdomain-extras   with Apache License 2.0 5 votes vote down vote up
package frdomain.ch6
package domain
package service

import cats.data.NonEmptyChain

trait BankingException

trait AccountServiceException extends BankingException {
  def message: NonEmptyChain[String]
}

case class AlreadyExistingAccount(no: String) extends AccountServiceException {
  val message = NonEmptyChain(s"Already existing account with no $no")
}

case class NonExistingAccount(no: String) extends AccountServiceException {
  val message = NonEmptyChain(s"No existing account with no $no")
}

case class ClosedAccount(no: String) extends AccountServiceException {
  val message = NonEmptyChain(s"Account with no $no is closed")
}

case object RateMissingForSavingsAccount extends AccountServiceException {
  val message = NonEmptyChain("Rate needs to be given for savings account")
}

case class MiscellaneousDomainExceptions(msgs: NonEmptyChain[String]) extends AccountServiceException {
  val message = msgs
}

case class ReportingServiceException(message: NonEmptyChain[String]) extends BankingException 
Example 8
Source File: ReportingService.scala    From frdomain-extras   with Apache License 2.0 5 votes vote down vote up
package frdomain.ch6
package domain
package service

import zio._
import cats.data.NonEmptyChain

import common._
import repository.AccountRepository
import model.Account

object ReportingService {
  trait Service {
    def balanceByAccount: IO[ReportingServiceException, Seq[(String, Amount)]]
  }

  val live = ZLayer.fromService[AccountRepository.Service, ReportingService.Service] {
    (repo: AccountRepository.Service) =>

    new Service {
      def balanceByAccount: IO[ReportingServiceException, Seq[(String, Amount)]] =
        withReportingServiceException(repo.all.map { accounts => accounts.map(a => (a.no, a.balance.amount)) })
    }
  }

  private def withReportingServiceException[A](t: Task[A]): IO[ReportingServiceException, A] = 
    t.foldM(
      error   => IO.fail(ReportingServiceException(NonEmptyChain(error.getMessage))),
      success => IO.succeed(success)
    )
} 
Example 9
Source File: DiffCatsInstances.scala    From diffx   with Apache License 2.0 5 votes vote down vote up
package com.softwaremill.diffx.cats

import cats.data.{NonEmptyChain, NonEmptyList, NonEmptySet, NonEmptyVector}
import com.softwaremill.diffx.{Derived, Diff}
import com.softwaremill.diffx.Diff._

trait DiffCatsInstances {
  implicit def diffNel[T: Diff]: Derived[Diff[NonEmptyList[T]]] =
    Derived(Diff[List[T]].contramap[NonEmptyList[T]](_.toList))

  implicit def diffNec[T: Diff]: Derived[Diff[NonEmptyChain[T]]] =
    Derived(Diff[List[T]].contramap[NonEmptyChain[T]](_.toChain.toList))

  implicit def diffNes[T: Diff]: Derived[Diff[NonEmptySet[T]]] =
    Derived(Diff[Set[T]].contramap[NonEmptySet[T]](_.toSortedSet))

  implicit def diffNev[T: Diff]: Derived[Diff[NonEmptyVector[T]]] =
    Derived(Diff[List[T]].contramap[NonEmptyVector[T]](_.toVector.toList))
} 
Example 10
Source File: StateEventJournal.scala    From aecor   with MIT License 5 votes vote down vote up
package aecor.testkit

import aecor.data._
import aecor.runtime.EventJournal
import aecor.testkit.StateEventJournal.State
import cats.Monad
import cats.data.{ Chain, NonEmptyChain }
import cats.implicits._
import cats.mtl.MonadState
import fs2._
import monocle.Lens

object StateEventJournal {
  final case class State[K, E](eventsByKey: Map[K, Chain[E]],
                               eventsByTag: Map[EventTag, Chain[EntityEvent[K, E]]],
                               consumerOffsets: Map[(EventTag, ConsumerId), Int]) {
    def getConsumerOffset(tag: EventTag, consumerId: ConsumerId): Int =
      consumerOffsets.getOrElse(tag -> consumerId, 0)

    def setConsumerOffset(tag: EventTag, consumerId: ConsumerId, offset: Int): State[K, E] =
      copy(consumerOffsets = consumerOffsets.updated(tag -> consumerId, offset))

    def getEventsByTag(tag: EventTag, offset: Int): Chain[(Int, EntityEvent[K, E])] = {
      val stream = eventsByTag
        .getOrElse(tag, Chain.empty)
        .mapWithIndex((e, i) => (i + 1, e))
        .toList
        .drop(offset)
      Chain.fromSeq(stream)
    }

    def readEvents(key: K): Chain[EntityEvent[K, E]] =
      eventsByKey
        .getOrElse(key, Chain.empty)
        .mapWithIndex((e, idx) => EntityEvent(key, idx + 1L, e))

    def appendEvents(key: K, offset: Long, events: NonEmptyChain[TaggedEvent[E]]): State[K, E] = {
      val updatedEventsById = eventsByKey
        .updated(key, eventsByKey.getOrElse(key, Chain.empty) ++ events.map(_.event).toChain)

      val newEventsByTag: Map[EventTag, Chain[EntityEvent[K, E]]] = events.toChain.zipWithIndex
        .flatMap {
          case (e, idx) =>
            Chain.fromSeq(e.tags.toSeq).map(t => t -> EntityEvent(key, idx + offset, e.event))
        }
        .groupBy(_._1)
        .map {
          case (key, value) =>
            key -> value.map(_._2).toChain
        }

      copy(
        eventsByKey = updatedEventsById,
        eventsByTag =
          eventsByTag |+| newEventsByTag
      )
    }
  }

  object State {
    def init[I, E]: State[I, E] = State(Map.empty, Map.empty, Map.empty)
  }

  def apply[F[_]: Monad: MonadState[*[_], A], K, A, E](
    lens: Lens[A, State[K, E]],
    tagging: Tagging[K]
  ): StateEventJournal[F, K, A, E] =
    new StateEventJournal(lens, tagging)

}

final class StateEventJournal[F[_]: Monad, K, S, E](lens: Lens[S, State[K, E]], tagging: Tagging[K])(
  implicit MS: MonadState[F, S]
) extends EventJournal[F, K, E] {
  private final val F = lens.transformMonadState(MonadState[F, S])

  override def append(key: K, offset: Long, events: NonEmptyChain[E]): F[Unit] =
    F.modify(_.appendEvents(key, offset, events.map(e => TaggedEvent(e, tagging.tag(key)))))

  override def read(key: K, offset: Long): Stream[F, EntityEvent[K, E]] =
    Stream
      .eval(F.inspect(_.readEvents(key)))
      .flatMap(x => Stream(x.toVector: _*))
      .drop(offset)

  def currentEventsByTag(tag: EventTag,
                         consumerId: ConsumerId): Stream[F, Committable[F, EntityEvent[K, E]]] =
    for {
      state <- Stream.eval(F.get)
      committedOffset = state.getConsumerOffset(tag, consumerId)
      result = state.getEventsByTag(tag, committedOffset)
      a <- Stream(result.toVector: _*).map {
            case (offset, e) =>
              Committable(F.modify(_.setConsumerOffset(tag, consumerId, offset)), e)
          }
    } yield a

}

final case class TaggedEvent[E](event: E, tags: Set[EventTag]) 
Example 11
Source File: ActionTSpec.scala    From aecor   with MIT License 5 votes vote down vote up
package aecor.tests

import aecor.data.Folded.Next
import aecor.data.{ ActionT, Fold, Folded }
import aecor.runtime.Eventsourced.Versioned
import cats.Id
import cats.data.{ Chain, NonEmptyChain }
import cats.instances.string._
import cats.syntax.either._
import cats.syntax.flatMap._
import cats.syntax.functor._
import org.scalatest.funsuite.AnyFunSuite

class ActionTSpec extends AnyFunSuite {
  def append(s: String): ActionT[Id, String, String, Unit] = ActionT.append(NonEmptyChain.one(s))
  def read[S]: ActionT[Id, S, String, S] = ActionT.read
  def pure[A](a: A): ActionT[Id, String, String, A] = ActionT.pure(a)
  def fold(s: String) = Fold(s, (l: String, r: String) => Folded.next(l ++ r))
  def run[A](action: ActionT[Id, String, String, A]): Folded[(Chain[String], A)] =
    action.run(fold(""))

  test("ActionT.read associativity") {
    val n1 @ Next((es, out)) = run(append("a") >> (append("b") >> read))
    val n2 = run(append("a") >> append("b") >> read)
    assert(es === Chain("a", "b"))
    assert(out === "ab")
    assert(n1 === n2)
  }

  test("xmapState") {
    val Next((es, (out, versioned))) =
      (append("a") >> append("b") >> read)
        .expand[Versioned[String]]((s, v) => s.copy(value = v))(_.value)
        .zipWithRead
        .run(Versioned.fold(fold("")))
    println(versioned)
    assert(versioned.version == 2)
    assert(es === Chain("a", "b"))
    assert(out === "ab")
  }

  test("tailRecM") {
    val x: ActionT[Id, String, String, Unit] = 0.tailRecM { c =>
      if (c < 50000) {
        append(s"$c").as((c + 1).asLeft[Unit])
      } else {
        pure(().asRight)
      }
    }

    val Next((es, _)) = run(x)
    assert(es.size == 50000)
  }

} 
Example 12
Source File: EventsourcedState.scala    From aecor   with MIT License 5 votes vote down vote up
package aecor.runtime

import aecor.data.Folded.Next
import aecor.data.{ ActionT, Fold, Folded }
import aecor.runtime.Eventsourced.Versioned
import cats.data.{ Chain, NonEmptyChain }
import cats.effect.Sync
import cats.implicits._

private[aecor] trait EventsourcedState[F[_], K, S, E] {
  def recover(key: K, snapshot: Option[Versioned[S]]): F[Versioned[S]]
  def run[A](key: K, state: Versioned[S], action: ActionT[F, S, E, A]): F[(Versioned[S], A)]
}

private[aecor] object EventsourcedState {
  def apply[F[_]: Sync, K, E, S](fold: Fold[Folded, S, E],
                                 journal: EventJournal[F, K, E]): EventsourcedState[F, K, S, E] =
    new DefaultEventsourcedState(fold, journal)
}

private[aecor] final class DefaultEventsourcedState[F[_], K, E, S](
  fold: Fold[Folded, S, E],
  journal: EventJournal[F, K, E]
)(implicit F: Sync[F])
    extends EventsourcedState[F, K, S, E] {

  private val versionedFold = Versioned.fold(fold)

  override def recover(key: K, snapshot: Option[Versioned[S]]): F[Versioned[S]] = {
    val from = snapshot.getOrElse(versionedFold.initial)
    journal
      .read(key, from.version)
      .evalScan(from) { (s, e) =>
        versionedFold.reduce(s, e.payload) match {
          case Next(a) =>
            F.pure(a)
          case Folded.Impossible =>
            F.raiseError(new IllegalStateException(s"Failed to apply event [$e] to [$s]"))
        }
      }
      .compile
      .lastOrError
  }

  override def run[A](key: K,
                      state: Versioned[S],
                      action: ActionT[F, S, E, A]): F[(Versioned[S], A)] =
    for {
      result <- action
                 .expand[Versioned[S]]((versioned, s) => versioned.copy(value = s))(_.value)
                 .zipWithRead
                 .run(versionedFold.init(state))
      (es, (a, nextState)) <- result match {
                               case Next(a) => a.pure[F]
                               case Folded.Impossible =>
                                 F.raiseError[(Chain[E], (A, Versioned[S]))](
                                   new IllegalArgumentException(
                                     s"Failed to run action [$action] against state [$state]"
                                   )
                                 )
                             }
      _ <- NonEmptyChain
            .fromChain(es)
            .traverse_(nes => journal.append(key, state.version + 1, nes))
    } yield (nextState, a)
} 
Example 13
Source File: EmbedSuite.scala    From tofu   with Apache License 2.0 5 votes vote down vote up
package tofu.higherKind.derived
import cats.data.{IorT, NonEmptyChain}
import cats.free.Free
import derevo.derive
import tofu.higherKind.Embed
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import cats.data.OptionT
import EmbedSuite.Foo
import tofu.syntax.monadic._
import tofu.syntax.embed._
import cats.instances.either._
import cats.instances.option._
import cats.syntax.traverse._
import cats.syntax.either._
import scala.util.Try

class EmbedSuite extends AnyFlatSpec with Matchers {
  val checkingFoo1: Foo[Either[String, *]] = new Foo[Either[String, *]] {
    override def foo(x: Int, s: String): Either[String, Double] =
      Try(s.toDouble).toEither.left.map(_ => s"could not parse $s as double").map(_ * x)
    override def bar(a: List[Int]): Either[String, Unit]        =
      a.headOption.toRight("must contain at least one element").void
    def baz(a: List[String]): OptionT[Either[String, *], Unit]  =
      OptionT(a.headOption.traverse(_.asLeft[Unit]))
  }

  "embed" should "generate nice embed" in {
    val rightFoo = checkingFoo1.asRight[String].embed
    val leftFoo  = "failed".asLeft[Foo[Either[String, *]]].embed

    rightFoo.foo(2, "2.3") should ===(Right(4.6))
    rightFoo.foo(2, "fail") should ===(Left("could not parse fail as double"))

    rightFoo.bar(List(4, 5, 6)) should ===(Right(()))
    rightFoo.bar(List()) should ===(Left("must contain at least one element"))

    leftFoo.foo(2, "2.3") should ===(Left("failed"))
    leftFoo.foo(2, "fail") should ===(Left("failed"))

    leftFoo.bar(List(4, 5, 6)) should ===(Left("failed"))
    leftFoo.bar(List()) should ===(Left("failed"))
  }
}

object EmbedSuite {
  @derive(embed)
  trait Foo[F[_]] {
    def foo(x: Int, s: String): F[Double]
    def bar(a: List[Int]): F[Unit]
    def baz(a: List[String]): OptionT[F, Unit]
  }

  Embed[Foo]

} 
Example 14
Source File: ScriptPreprocessor.scala    From Waves   with MIT License 5 votes vote down vote up
package com.wavesplatform.lang.script

import cats.data.NonEmptyChain
import cats.kernel.CommutativeSemigroup
import cats.implicits._
import com.wavesplatform.lang.directives.{Directive, DirectiveKey, DirectiveParser}
import com.wavesplatform.lang.directives.values.{Imports, Library}

object ScriptPreprocessor {
  def apply(
    scriptText: String,
    libraries:  Map[String, String],
    imports:    Imports
  ): Either[String, String] =
    for {
      matchedLibraries <- resolveLibraries(libraries, imports)
      _                <- checkLibrariesDirectives(matchedLibraries)
    } yield gatherScriptText(scriptText, matchedLibraries)

  private def resolveLibraries(
    libraries: Map[String, String],
    imports:   Imports
  ): Either[String, Map[String, String]] = {
    implicit val cs: CommutativeSemigroup[NonEmptyChain[String]] = _ ++ _
    imports.fileNames
      .map(f => (f, (f, libraries.get(f))))
      .toMap
      .unorderedTraverse { case (name, expr) => expr.toValidNec(name) }
      .leftMap(f => s"Unresolved imports: ${f.map(s => s"`$s`").toList.mkString(", ")}")
      .toEither
  }

  private def checkLibrariesDirectives(
    matchedLibraries: Map[String, String]
  ): Either[String, List[Unit]] =
    matchedLibraries
      .map { case (name, src) => checkLibraryDirectives(name, src) }
      .toList
      .sequence

  private def checkLibraryDirectives(
    libraryName: String,
    librarySrc:  String
  ): Either[String, Unit] =
    for {
      directives <- DirectiveParser(librarySrc)
      ds         <- Directive.extractDirectives(directives)
      _          <- Either.cond(ds.contentType == Library, (), s"CONTENT_TYPE of `$libraryName` is not LIBRARY")
    } yield ()

  private val importRegex = s"\\${DirectiveParser.start}\\s*${DirectiveKey.IMPORT.text}.*${DirectiveParser.end}"
  private val directiveRegex = s"\\${DirectiveParser.start}.*${DirectiveParser.end}"

  private def gatherScriptText(src: String, libraries: Map[String, String]) = {
    val additionalDecls = libraries.values.map(removeDirectives).mkString("\n")
    src.replaceFirst(importRegex, additionalDecls)
  }

  private def removeDirectives(script: String): String =
    script.replaceAll(directiveRegex, "")
} 
Example 15
Source File: TapirCodecCats.scala    From tapir   with Apache License 2.0 5 votes vote down vote up
package sttp.tapir.codec.cats

import cats.data.{NonEmptyChain, NonEmptyList, NonEmptySet}
import sttp.tapir.{Schema, SchemaType}
import sttp.tapir._

import scala.collection.immutable.SortedSet

trait TapirCodecCats {

  private def nonEmpty[T, C[X] <: Iterable[X]]: Validator.Primitive[C[T]] = Validator.minSize[T, C](1)

  private def iterableAndNonEmpty[T, C[X] <: Iterable[X]](implicit v: Validator[T]): Validator[C[T]] =
    v.asIterableElements[C].and(nonEmpty)

  implicit def validatorNel[T: Validator]: Validator[NonEmptyList[T]] =
    iterableAndNonEmpty[T, List].contramap(_.toList)

  implicit def validatorNec[T: Validator]: Validator[NonEmptyChain[T]] =
    iterableAndNonEmpty[T, List].contramap(_.toChain.toList)

  implicit def validatorNes[T: Validator]: Validator[NonEmptySet[T]] =
    iterableAndNonEmpty[T, Set].contramap(_.toSortedSet)

  implicit def schemaForNel[T: Schema]: Schema[NonEmptyList[T]] =
    Schema[NonEmptyList[T]](SchemaType.SArray(implicitly[Schema[T]])).copy(isOptional = false)

  implicit def schemaForNec[T: Schema]: Schema[NonEmptyChain[T]] =
    Schema[NonEmptyChain[T]](SchemaType.SArray(implicitly[Schema[T]])).copy(isOptional = false)

  implicit def schemaForNes[T: Schema]: Schema[NonEmptySet[T]] =
    Schema[NonEmptySet[T]](SchemaType.SArray(implicitly[Schema[T]])).copy(isOptional = false)

  implicit def codecForNonEmptyList[L, H, CF <: CodecFormat](implicit c: Codec[L, List[H], CF]): Codec[L, NonEmptyList[H], CF] =
    c.modifySchema(_.copy(isOptional = false))
      .validate(nonEmpty)
      .mapDecode { l => DecodeResult.fromOption(NonEmptyList.fromList(l)) }(_.toList)

  implicit def codecForNonEmptyChain[L, H, CF <: CodecFormat](implicit c: Codec[L, List[H], CF]): Codec[L, NonEmptyChain[H], CF] =
    c.modifySchema(_.copy(isOptional = false))
      .validate(nonEmpty)
      .mapDecode { l => DecodeResult.fromOption(NonEmptyChain.fromSeq(l)) }(_.toNonEmptyList.toList)

  implicit def codecForNonEmptySet[L, H: Ordering, CF <: CodecFormat](implicit c: Codec[L, Set[H], CF]): Codec[L, NonEmptySet[H], CF] =
    c.modifySchema(_.copy(isOptional = false))
      .validate(nonEmpty)
      .mapDecode { set => DecodeResult.fromOption(NonEmptySet.fromSet(SortedSet(set.toSeq: _*))) }(_.toSortedSet)
} 
Example 16
Source File: ValidatedUtils.scala    From chimney   with Apache License 2.0 5 votes vote down vote up
package io.scalaland.chimney.cats.utils

import cats.InvariantMonoidal
import cats.data.{NonEmptyChain, NonEmptyList, Validated, ValidatedNec, ValidatedNel}

object ValidatedUtils {

  implicit class OptionOps[T](val opt: Option[T]) extends AnyVal {

    def toValidated[EE[_]: InvariantMonoidal](err: => String): Validated[EE[String], T] = {
      opt match {
        case Some(value) => Validated.Valid(value)
        case None        => Validated.Invalid(InvariantMonoidal[EE].point(err))
      }
    }

    def toValidatedNec(err: => String): ValidatedNec[String, T] =
      toValidated[NonEmptyChain](err)(implicitly)

    def toValidatedNel(err: => String): ValidatedNel[String, T] =
      toValidated[NonEmptyList](err)(implicitly)
  }

  implicit class ValidatedOps[+E, +A](val validated: Validated[E, A]) extends AnyVal {

    def getValid: A = {
      validated.valueOr(_ => throw new NoSuchElementException)
    }
  }
}