All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.specs2.matcher.describe.LinesDiffable.scala Maven / Gradle / Ivy

The newest version!
package org.specs2.matcher.describe

/** Import the implicit Diffable contained in this object to get a colored output showing line differences in Strings
  * containing lots of lines
  */
object LinesDiffable:

  given largeStringDiffable: Diffable[String] with
    def diff(actual: String, expected: String): ComparisonResult =
      val (actualLines, expectedLines) =
        (actual.toString.split("\n").toList, expected.toString.split("\n").toList)

      if actualLines.size + expectedLines.size > 2 then linesDiffable[String].diff(actualLines, expectedLines)
      else Diffable.stringDiffable.diff(actual, expected)

  given linesDiffable[T: Diffable]: Diffable[List[T]] with
    def diff(actual: List[T], expected: List[T]): ComparisonResult =
      LinesComparisonResult(actual, expected)

case class LinesComparisonResult[T: Diffable](actual: List[T], expected: List[T]) extends ComparisonResult:
  import org.specs2.data.*
  import EditDistance.*
  import org.specs2.text.AnsiColors.*

  private val diffable: Diffable[T] =
    implicitly[Diffable[T]]

  private lazy val operations: IndexedSeq[EditDistanceOperation[T]] =
    levenhsteinDistance[T](actual.toIndexedSeq, expected.toIndexedSeq)(using
      new Equiv[T]:
        def equiv(a: T, b: T) = diffable.diff(a, b).identical
    )

  def identical: Boolean =
    actual.size == expected.size &&
      actual.zip(expected).forall { case (a, e) => diffable.diff(a, e).identical }

  def render: String = operations
    .flatMap {
      case Same(line)          => List(line)
      case Add(line)           => List(color("+ " + line, green))
      case Del(line)           => List(color("- " + line, red))
      case Subst(line1, line2) => List(color("- " + line1, red), color("+ " + line2, green))
    }
    .mkString("", "\n", "")




© 2015 - 2024 Weber Informatics LLC | Privacy Policy