diff --git a/build.sbt b/build.sbt index 0bca389a..08ca3422 100644 --- a/build.sbt +++ b/build.sbt @@ -245,7 +245,6 @@ lazy val munit = crossProject(JSPlatform, JVMPlatform, NativePlatform) ) .jvmConfigure(_.dependsOn(junit)) .dependsOn(munitDiff) -// .dependsOn(munitDiff, munitCore) lazy val munitJVM = munit.jvm lazy val munitJS = munit.js @@ -291,30 +290,6 @@ lazy val munitScalacheck = crossProject(JSPlatform, JVMPlatform, NativePlatform) .jsConfigure(sharedJSConfigure) .jsSettings(sharedJSSettings) -// lazy val munitCore = crossProject(JSPlatform, JVMPlatform, NativePlatform) -// .in(file("munit-core")) -// .settings( -// moduleName := "munit-core", -// sharedSettings, -// Compile / unmanagedSourceDirectories ++= -// crossBuildingDirectories("munit-core", "main").value, -// libraryDependencies ++= List( -// "org.scala-lang" % "scala-reflect" % { -// if (isScala3Setting.value) scala213 -// else scalaVersion.value -// } % Provided -// ) -// ) -// .jvmSettings( -// sharedJVMSettings -// ) -// .nativeConfigure(sharedNativeConfigure) -// .nativeSettings( -// sharedNativeSettings -// ) -// .jsConfigure(sharedJSConfigure) -// .jsSettings(sharedJSSettings) - lazy val munitDiff = crossProject(JSPlatform, JVMPlatform, NativePlatform) .in(file("scala-diff")) .settings( @@ -338,7 +313,6 @@ lazy val munitDiff = crossProject(JSPlatform, JVMPlatform, NativePlatform) ) .jsConfigure(sharedJSConfigure) .jsSettings(sharedJSSettings) -// .dependsOn(munitCore) lazy val munitScalacheckJVM = munitScalacheck.jvm lazy val munitScalacheckJS = munitScalacheck.js diff --git a/munit-core/js/src/main/scala/munit/internal/io/File.scala b/munit-core/js/src/main/scala/munit/internal/io/File.scala deleted file mode 100644 index 73d6936e..00000000 --- a/munit-core/js/src/main/scala/munit/internal/io/File.scala +++ /dev/null @@ -1,78 +0,0 @@ -package munit.internal.io - -import java.net.URI - -// obtained implementation by experimentation on the JDK. -class File(path: String) { - def this(parent: String, child: String) = - this(parent + File.separator + child) - def this(parent: File, child: String) = - this(parent.getPath, child) - def this(uri: URI) = - this( - if (uri.getScheme != "file") { - throw new IllegalArgumentException("URI scheme is not \"file\"") - } else { - uri.getPath - } - ) - def toPath: MunitPath = - MunitPath(path) - def toURI: URI = { - val file = getAbsoluteFile.toString - val uripath = - if (file.startsWith("/")) file - else "/" + file.replace(File.separator, "/") - val withslash = - if (isDirectory && !uripath.endsWith("/")) uripath + "/" else uripath - new URI("file", null, withslash, null) - } - def getAbsoluteFile: File = - toPath.toAbsolutePath.toFile - def getAbsolutePath: String = - getAbsoluteFile.toString - def getParentFile: File = - toPath.getParent.toFile - def mkdirs(): Unit = - throw new UnsupportedOperationException( - "mkdirs() is not supported in Scala.js" - ) - def getPath: String = - path - def exists(): Boolean = - JSIO.exists(path) - def isFile: Boolean = - JSIO.isFile(path) - def isDirectory: Boolean = - JSIO.isDirectory(path) - override def toString: String = - path -} - -object File { - def listRoots(): Array[File] = Array( - new File( - JSIO.path match { - case Some(p) => p.parse(p.resolve()).root.asInstanceOf[String] - case None => "/" - } - // if (JSIO.isNode) JSPath.parse(JSPath.resolve()).root - // else "/" - ) - ) - - def separatorChar: Char = - separator.charAt(0) - - def separator: String = - JSIO.path match { - case Some(p) => p.sep.asInstanceOf[String] - case None => "/" - } - - def pathSeparator: String = - JSIO.path match { - case Some(p) => p.delimeter.asInstanceOf[String] - case None => ":" - } -} diff --git a/munit-core/js/src/main/scala/munit/internal/io/Files.scala b/munit-core/js/src/main/scala/munit/internal/io/Files.scala deleted file mode 100644 index 77ea39d4..00000000 --- a/munit-core/js/src/main/scala/munit/internal/io/Files.scala +++ /dev/null @@ -1,30 +0,0 @@ -package munit.internal.io - -import scala.scalajs.js -import java.{util => ju} -import java.nio.charset.StandardCharsets - -import scala.collection.JavaConverters._ - -object Files { - def readAllLines(path: MunitPath): ju.List[String] = { - val bytes = readAllBytes(path) - val text = new String(bytes, StandardCharsets.UTF_8) - text.linesIterator.toSeq.asJava - } - def readAllBytes(path: MunitPath): Array[Byte] = { - val jsArray = JSIO.fs match { - case Some(fs) => - fs.readFileSync(path.toString).asInstanceOf[js.Array[Int]] - case None => new js.Array[Int](0) - } - val len = jsArray.length - val result = new Array[Byte](len) - var curr = 0 - while (curr < len) { - result(curr) = jsArray(curr).toByte - curr += 1 - } - result - } -} diff --git a/munit-core/js/src/main/scala/munit/internal/io/JSIO.scala b/munit-core/js/src/main/scala/munit/internal/io/JSIO.scala deleted file mode 100644 index 466c4ae8..00000000 --- a/munit-core/js/src/main/scala/munit/internal/io/JSIO.scala +++ /dev/null @@ -1,42 +0,0 @@ -package munit.internal.io - -import scala.scalajs.js -import scala.util.Try - -object JSIO { - - private def require(module: String): Option[js.Dynamic] = { - Try(js.Dynamic.global.require(module)) // Node.js - .orElse( // JSDOM - Try(js.Dynamic.global.Node.constructor("return require")()(module)) - ) - .toOption - } - val process: Option[js.Dynamic] = require("process") - val path: Option[js.Dynamic] = require("path") - val fs: Option[js.Dynamic] = require("fs") - - def cwd(): String = - process match { - case Some(p) => p.cwd().asInstanceOf[String] - case None => "/" - } - - def exists(path: String): Boolean = - fs match { - case Some(f) => f.existsSync(path).asInstanceOf[Boolean] - case None => false - } - - def isFile(path: String): Boolean = - exists(path) && (fs match { - case Some(f) => f.lstatSync(path).isFile().asInstanceOf[Boolean] - case None => false - }) - - def isDirectory(path: String): Boolean = - exists(path) && (fs match { - case Some(f) => f.lstatSync(path).isDirectory().asInstanceOf[Boolean] - case None => false - }) -} diff --git a/munit-core/js/src/main/scala/munit/internal/io/MunitPath.scala b/munit-core/js/src/main/scala/munit/internal/io/MunitPath.scala deleted file mode 100644 index de1302ed..00000000 --- a/munit-core/js/src/main/scala/munit/internal/io/MunitPath.scala +++ /dev/null @@ -1,149 +0,0 @@ -package munit.internal.io - -import java.net.URI -import java.util - -import scala.collection.JavaConverters._ - -// Rough implementation of java.nio.Path, should work similarly for the happy -// path but has undefined behavior for error handling. -case class MunitPath(filename: String) { - private[this] val escapedSeparator = - java.util.regex.Pattern.quote(File.separator) - - private def adjustIndex(idx: Int): Int = - if (isAbsolute) idx + 1 else idx - def subpath(beginIndex: Int, endIndex: Int): MunitPath = - MunitPath( - filename - .split(escapedSeparator) - .slice(adjustIndex(beginIndex), adjustIndex(endIndex)) - .mkString - ) - def toFile: File = - new File(filename) - def isAbsolute: Boolean = JSIO.path match { - case Some(path) => path.isAbsolute(filename).asInstanceOf[Boolean] - case None => filename.startsWith(File.separator) - } - def getName(index: Int): MunitPath = - MunitPath( - filename - .split(escapedSeparator) - .lift(adjustIndex(index)) - .getOrElse(throw new IllegalArgumentException) - ) - def getParent: MunitPath = - JSIO.path match { - case Some(path) => - MunitPath(path.dirname(filename).asInstanceOf[String]) - case None => - throw new UnsupportedOperationException( - "Path.getParent() is only supported in Node.js" - ) - } - - def toAbsolutePath: MunitPath = - if (isAbsolute) this - else MunitPath.workingDirectory.resolve(this) - def relativize(other: MunitPath): MunitPath = - JSIO.path match { - case Some(path) => - MunitPath( - path.relative(filename, other.toString()).asInstanceOf[String] - ) - case None => - throw new UnsupportedOperationException( - "Path.relativize() is only supported in Node.js" - ) - } - def getNameCount: Int = { - val strippeddrive = - if ((filename.length > 1) && (filename(1) == ':')) filename.substring(2) - else filename - val (first, remaining) = - strippeddrive.split(escapedSeparator + "+").span(_.isEmpty) - if (remaining.isEmpty) first.length - else remaining.length - } - def toUri: URI = toFile.toURI - def getFileName(): MunitPath = - JSIO.path match { - case Some(path) => - MunitPath(path.basename(filename).asInstanceOf[String]) - case None => - throw new UnsupportedOperationException( - "Path.getFileName() is only supported in Node.js" - ) - } - def getRoot: MunitPath = - if (!isAbsolute) null - else MunitPath(File.separator) - def normalize(): MunitPath = - JSIO.path match { - case Some(path) => - MunitPath(path.normalize(filename).asInstanceOf[String]) - case None => - throw new UnsupportedOperationException( - "Path.normalize() is only supported in Node.js" - ) - } - def endsWith(other: MunitPath): Boolean = - endsWith(other.toString) - def endsWith(other: String): Boolean = - paths(filename).endsWith(paths(other)) - // JSPath.resolve(relpath, relpath) produces an absolute path from cwd. - // This method turns the generated absolute path back into a relative path. - private def adjustResolvedPath(resolved: MunitPath): MunitPath = - if (isAbsolute) resolved - else MunitPath.workingDirectory.relativize(resolved) - def resolveSibling(other: MunitPath): MunitPath = - resolveSibling(other.toString) - def resolveSibling(other: String): MunitPath = - JSIO.path match { - case Some(path) => - adjustResolvedPath( - MunitPath( - path - .resolve(path.dirname(filename).asInstanceOf[String], other) - .asInstanceOf[String] - ) - ) - case None => - throw new UnsupportedOperationException( - "Path.normalize() is only supported in Node.js" - ) - } - def resolve(other: MunitPath): MunitPath = - resolve(other.toString) - def resolve(other: String): MunitPath = - JSIO.path match { - case Some(path) => - adjustResolvedPath( - MunitPath(path.resolve(filename, other).asInstanceOf[String]) - ) - case None => - throw new UnsupportedOperationException( - "Path.normalize() is only supported in Node.js" - ) - } - def startsWith(other: MunitPath): Boolean = - startsWith(other.toString) - def startsWith(other: String): Boolean = - paths(filename).startsWith(paths(other)) - private def paths(name: String) = - name.split(escapedSeparator) - override def toString: String = - filename - def iterator(): util.Iterator[MunitPath] = - filename - .split(File.separator) - .iterator - .map(name => MunitPath(name): MunitPath) - .asJava -} - -object MunitPath { - def workingDirectory: MunitPath = - MunitPath(JSIO.cwd()) -} diff --git a/munit-core/js/src/main/scala/munit/internal/io/Paths.scala b/munit-core/js/src/main/scala/munit/internal/io/Paths.scala deleted file mode 100644 index cf04e689..00000000 --- a/munit-core/js/src/main/scala/munit/internal/io/Paths.scala +++ /dev/null @@ -1,29 +0,0 @@ -package munit.internal.io - -import java.net.URI - -object Paths { - // NOTE: We can't use Scala-style varargs since those have a different jvm - // signature than Java-style varargs. The boot classpath contains nio.file.Path - // so call-sites to `get` will resolve to the original java.nio.file.Paths.get, - // which results in a Scala.js linking error when using Scala varargs. - def get(first: String, more: Array[String] = Array.empty): MunitPath = { - val path = - if (more.isEmpty) first - else first + File.separator + more.mkString(File.separator) - MunitPath(path) - } - - def get(uri: URI): MunitPath = { - if (uri.getScheme != "file") - throw new IllegalArgumentException("only file: URIs are supported") - val uripath = uri.getPath - val parts = uripath.split('/').toList - val (leading, trailing) = parts.span(_ == "") - trailing match { - case drive :: path if (drive.length == 2 && drive(1) == ':') => - MunitPath(trailing.mkString("\\")) - case _ => MunitPath(uripath) - } - } -} diff --git a/munit-core/js/src/main/scala/munit/internal/io/PlatformIO.scala b/munit-core/js/src/main/scala/munit/internal/io/PlatformIO.scala deleted file mode 100644 index 50ff8eec..00000000 --- a/munit-core/js/src/main/scala/munit/internal/io/PlatformIO.scala +++ /dev/null @@ -1,16 +0,0 @@ -package munit.internal.io - -object PlatformIO { - type File = munit.internal.io.File - object File { - def separatorChar = munit.internal.io.File.separatorChar - } - - object Files { - def readAllLines(path: Path): java.util.List[String] = - munit.internal.io.Files.readAllLines(path) - } - - type Path = MunitPath - val Paths = munit.internal.io.Paths -} diff --git a/munit-core/jvm/src/main/scala/munit/internal/io/PlatformIO.scala b/munit-core/jvm/src/main/scala/munit/internal/io/PlatformIO.scala deleted file mode 100644 index 3e942d10..00000000 --- a/munit-core/jvm/src/main/scala/munit/internal/io/PlatformIO.scala +++ /dev/null @@ -1,18 +0,0 @@ -package munit.internal.io - -object PlatformIO { - type File = java.io.File - object File { - def separatorChar = java.io.File.separatorChar - } - - object Files { - def readAllLines(path: Path): java.util.List[String] = - java.nio.file.Files.readAllLines(path) - } - - type Path = java.nio.file.Path - object Paths { - def get(path: String): Path = java.nio.file.Paths.get(path) - } -} diff --git a/munit-core/native/src/main/scala/munit/internal/io/PlatformIO.scala b/munit-core/native/src/main/scala/munit/internal/io/PlatformIO.scala deleted file mode 100644 index 3e942d10..00000000 --- a/munit-core/native/src/main/scala/munit/internal/io/PlatformIO.scala +++ /dev/null @@ -1,18 +0,0 @@ -package munit.internal.io - -object PlatformIO { - type File = java.io.File - object File { - def separatorChar = java.io.File.separatorChar - } - - object Files { - def readAllLines(path: Path): java.util.List[String] = - java.nio.file.Files.readAllLines(path) - } - - type Path = java.nio.file.Path - object Paths { - def get(path: String): Path = java.nio.file.Paths.get(path) - } -} diff --git a/munit-core/shared/src/main/scala-2.13/munit/internal/Compat.scala b/munit-core/shared/src/main/scala-2.13/munit/internal/Compat.scala deleted file mode 100644 index e0606348..00000000 --- a/munit-core/shared/src/main/scala-2.13/munit/internal/Compat.scala +++ /dev/null @@ -1,10 +0,0 @@ -package munit.internal - -object Compat { - type LazyList[+T] = scala.LazyList[T] - val LazyList = scala.LazyList - def productElementNames(p: Product): Iterator[String] = - p.productElementNames - def collectionClassName(i: Iterable[_]): String = - i.asInstanceOf[{ def collectionClassName: String }].collectionClassName -} diff --git a/munit-core/shared/src/main/scala-2/munit/internal/MacroCompat.scala b/munit-core/shared/src/main/scala-2/munit/internal/MacroCompat.scala deleted file mode 100644 index 594abdb7..00000000 --- a/munit-core/shared/src/main/scala-2/munit/internal/MacroCompat.scala +++ /dev/null @@ -1,35 +0,0 @@ -package munit.internal - -import munit.Clue -import munit.Location -import scala.language.experimental.macros -import scala.reflect.macros.blackbox.Context - -object MacroCompat { - - trait LocationMacro { - implicit def generate: Location = macro MacroCompatScala2.locationImpl - } - - @deprecated("Use MacroCompatScala2.locationImpl instead", "2020-01-06") - def locationImpl(c: Context): c.Tree = MacroCompatScala2.locationImpl(c) - - trait ClueMacro { - implicit def generate[T](value: T): Clue[T] = - macro MacroCompatScala2.clueImpl - } - - @deprecated("Use MacroCompatScala2.clueImpl instead", "2020-01-06") - def clueImpl(c: Context)(value: c.Tree): c.Tree = - MacroCompatScala2.clueImpl(c)(value) - - trait CompileErrorMacro { - def compileErrors(code: String): String = - macro MacroCompatScala2.compileErrorsImpl - } - - @deprecated("Use MacroCompatScala2.compileErrorsImpl instead", "2020-01-06") - def compileErrorsImpl(c: Context)(value: c.Tree): c.Tree = - MacroCompatScala2.compileErrorsImpl(c)(value) - -} diff --git a/munit-core/shared/src/main/scala-3/munit/internal/Compat.scala b/munit-core/shared/src/main/scala-3/munit/internal/Compat.scala deleted file mode 100644 index 7e489e23..00000000 --- a/munit-core/shared/src/main/scala-3/munit/internal/Compat.scala +++ /dev/null @@ -1,13 +0,0 @@ -package munit.internal - -import scala.reflect.Selectable.reflectiveSelectable - -object Compat { - type LazyList[+T] = scala.LazyList[T] - val LazyList = scala.LazyList - def productElementNames(p: Product): Iterator[String] = - p.productElementNames - def collectionClassName(i: Iterable[_]): String = { - i.asInstanceOf[{ def collectionClassName: String }].collectionClassName - } -} diff --git a/munit-core/shared/src/main/scala-3/munit/internal/MacroCompat.scala b/munit-core/shared/src/main/scala-3/munit/internal/MacroCompat.scala deleted file mode 100644 index 721cf52b..00000000 --- a/munit-core/shared/src/main/scala-3/munit/internal/MacroCompat.scala +++ /dev/null @@ -1,57 +0,0 @@ -package munit.internal - -import munit.Clue -import munit.Location -import scala.quoted._ -import scala.language.experimental.macros - -object MacroCompat { - - trait LocationMacro { - inline implicit def generate: Location = ${ locationImpl() } - implicit def generate: Location = macro MacroCompatScala2.locationImpl - } - - def locationImpl()(using Quotes): Expr[Location] = { - import quotes.reflect._ - val pos = Position.ofMacroExpansion - val path = pos.sourceFile.jpath.toString - val startLine = pos.startLine + 1 - '{ new Location(${ Expr(path) }, ${ Expr(startLine) }) } - } - - trait ClueMacro { - inline implicit def generate[T](value: T): Clue[T] = ${ clueImpl('value) } - implicit def generate[T](value: T): Clue[T] = macro - MacroCompatScala2.clueImpl - } - - def clueImpl[T: Type](value: Expr[T])(using Quotes): Expr[Clue[T]] = { - import quotes.reflect._ - val source = value.asTerm.pos.sourceCode.getOrElse("") - val valueType = TypeTree.of[T].show(using Printer.TreeShortCode) - '{ new Clue(${ Expr(source) }, $value, ${ Expr(valueType) }) } - } - - trait CompileErrorMacro { - inline def compileErrors(inline code: String): String = { - val errors = scala.compiletime.testing.typeCheckErrors(code) - errors - .map { error => - val indent = " " * (error.column - 1) - val trimMessage = error.message.linesIterator - .map { line => - if (line.matches(" +")) "" - else line - } - .mkString("\n") - val separator = if (error.message.contains('\n')) "\n" else " " - s"error:${separator}${trimMessage}\n${error.lineContent}\n${indent}^" - } - .mkString("\n") - } - def compileErrors(code: String): String = macro - MacroCompatScala2.compileErrorsImpl - } - -} diff --git a/munit-core/shared/src/main/scala-pre-2.13/munit/internal/Compat.scala b/munit-core/shared/src/main/scala-pre-2.13/munit/internal/Compat.scala deleted file mode 100644 index cadb0ab8..00000000 --- a/munit-core/shared/src/main/scala-pre-2.13/munit/internal/Compat.scala +++ /dev/null @@ -1,10 +0,0 @@ -package munit.internal - -object Compat { - type LazyList[+T] = Stream[T] - val LazyList = scala.Stream - def productElementNames(p: Product): Iterator[String] = - Iterator.continually("") - def collectionClassName(i: Iterable[_]): String = - i.stringPrefix -} diff --git a/munit-core/shared/src/main/scala/munit/Clue.scala b/munit-core/shared/src/main/scala/munit/Clue.scala deleted file mode 100644 index cb905bee..00000000 --- a/munit-core/shared/src/main/scala/munit/Clue.scala +++ /dev/null @@ -1,16 +0,0 @@ -package munit - -import munit.internal.MacroCompat - -class Clue[+T]( - val source: String, - val value: T, - val valueType: String -) extends Serializable { - override def toString(): String = s"Clue($source, $value)" -} -object Clue extends MacroCompat.ClueMacro { - @deprecated("use fromValue instead", "1.0.0") - def empty[T](value: T): Clue[T] = fromValue(value) - def fromValue[T](value: T): Clue[T] = new Clue("", value, "") -} diff --git a/munit-core/shared/src/main/scala/munit/Clues.scala b/munit-core/shared/src/main/scala/munit/Clues.scala deleted file mode 100644 index 8659a06a..00000000 --- a/munit-core/shared/src/main/scala/munit/Clues.scala +++ /dev/null @@ -1,11 +0,0 @@ -package munit - -import munit.internal.console.Printers - -class Clues(val values: List[Clue[_]]) { - override def toString(): String = Printers.print(this) -} -object Clues { - def empty: Clues = new Clues(List()) - def fromValue[T](value: T): Clues = new Clues(List(Clue.fromValue(value))) -} diff --git a/munit-core/shared/src/main/scala/munit/Location.scala b/munit-core/shared/src/main/scala/munit/Location.scala deleted file mode 100644 index ca0fd517..00000000 --- a/munit-core/shared/src/main/scala/munit/Location.scala +++ /dev/null @@ -1,43 +0,0 @@ -package munit - -import java.lang.annotation.Annotation -import scala.runtime.Statics -import munit.internal.io.PlatformIO.File -import munit.internal.MacroCompat - -object Location extends MacroCompat.LocationMacro { - def empty: Location = new Location("", 0) -} - -final class Location( - val path: String, - val line: Int -) extends Annotation - with Serializable { - def filename: String = { - val sep = path.lastIndexOf(File.separatorChar) - if (sep < 0) path - else path.substring(math.min(sep + 1, path.length() - 1)) - } - override def annotationType(): Class[Annotation] = { - classOf[Annotation] - } - override def toString: String = { - path + ":" + line - } - override def equals(obj: Any): Boolean = { - obj.asInstanceOf[AnyRef].eq(this) || (obj match { - case l: Location => - l.path == path && - l.line == line - case _ => - false - }) - } - override def hashCode(): Int = { - var acc = -889275714 - acc = Statics.mix(acc, Statics.anyHash(path)) - acc = Statics.mix(acc, line) - acc - } -} diff --git a/munit-core/shared/src/main/scala/munit/Printable.scala b/munit-core/shared/src/main/scala/munit/Printable.scala deleted file mode 100644 index 6947b7a5..00000000 --- a/munit-core/shared/src/main/scala/munit/Printable.scala +++ /dev/null @@ -1,8 +0,0 @@ -package munit - -/** - * Override this class to customize the default pretty-printer. - */ -trait Printable { - def print(out: StringBuilder, indent: Int): Unit -} diff --git a/munit-core/shared/src/main/scala/munit/Printer.scala b/munit-core/shared/src/main/scala/munit/Printer.scala deleted file mode 100644 index ee94cf53..00000000 --- a/munit-core/shared/src/main/scala/munit/Printer.scala +++ /dev/null @@ -1,107 +0,0 @@ -package munit - -/** - * Implement this trait to customize the default printer - */ -trait Printer { - - /** - * Pretty-print a single value during pretty printing. - * - * Returns true if this value has been printed, false if FunSuite should fallback to the default pretty-printer. - */ - def print(value: Any, out: StringBuilder, indent: Int): Boolean - def height: Int = Printer.defaultHeight - def isMultiline(string: String): Boolean = - string.contains('\n') - - /** - * Combine two printers into a single printer. - * - * Order is important : this printer will be tried first, then the other printer. - * The new Printer's height will be the max of the two printers' heights. - * - * Example use case : define some default printers for some types for all tests, - * and override it for some tests only. - * - * {{{ - * - * case class Person(name: String, age: Int, mail: String) - * - * trait MySuites extends FunSuite { - * override val printer = Printer.apply { - * case Person(name, age, mail) => s"$name:$age:$mail" - * case m: SomeOtherCaseClass => m.someCustomToString - * } - * } - * - * trait CompareMailsOnly extends MySuites { - * val mailOnlyPrinter = Printer.apply { - * case Person(_, _, mail) => mail - * } - * override val printer = mailOnlyPrinterPrinter orElse super.printer - * } - * - * }}} - */ - def orElse(other: Printer): Printer = { - val h = this.height - val p: (Any, StringBuilder, Int) => Boolean = this.print - new Printer { - def print(value: Any, out: StringBuilder, indent: Int): Boolean = - p.apply(value, out, indent) || other.print( - value, - out, - indent - ) - override def height: Int = h.max(other.height) - } - } - -} - -object Printer { - - val defaultHeight = 100 - - def apply( - height: Int - )(partialPrint: PartialFunction[Any, String]): Printer = { - val h = height - new Printer { - def print(value: Any, out: StringBuilder, indent: Int): Boolean = { - partialPrint.lift.apply(value) match { - case Some(string) => - out.append(string) - true - case None => false - } - } - - override def height: Int = h - } - } - - /** - * Utiliy constructor defining a printer for some types. - * - * Example use case is overriding the string repr for types which default pretty-printers - * do not output helpful diffs. - * - * {{{ - * type ByteArray = Array[Byte] - * val listPrinter = Printer.apply { - * case ll: ByteArray => ll.map(String.format("%02x", b)).mkString(" ") - * } - * val bytes = Array[Byte](1, 5, 8, 24) - * Printers.print(bytes, listPrinter) // "01 05 08 18" - * }}} - */ - def apply(partialPrint: PartialFunction[Any, String]): Printer = - apply(defaultHeight)(partialPrint) -} - -/** Default printer that does not customize the pretty-printer */ -object EmptyPrinter extends Printer { - def print(value: Any, out: StringBuilder, indent: Int): Boolean = false -} diff --git a/munit-core/shared/src/main/scala/munit/internal/FutureCompat.scala b/munit-core/shared/src/main/scala/munit/internal/FutureCompat.scala deleted file mode 100644 index 1581f51e..00000000 --- a/munit-core/shared/src/main/scala/munit/internal/FutureCompat.scala +++ /dev/null @@ -1,24 +0,0 @@ -package munit.internal - -import scala.concurrent.Future -import scala.util.Try -import scala.concurrent.ExecutionContext - -object FutureCompat { - implicit class ExtensionFuture[T](f: Future[T]) { - def flattenCompat[S]( - ec: ExecutionContext - )(implicit ev: T <:< Future[S]): Future[S] = - f.flatten - def transformCompat[B]( - fn: Try[T] => Try[B] - )(implicit ec: ExecutionContext): Future[B] = { - f.transform(fn) - } - def transformWithCompat[B]( - fn: Try[T] => Future[B] - )(implicit ec: ExecutionContext): Future[B] = { - f.transformWith(fn) - } - } -} diff --git a/munit-core/shared/src/main/scala/munit/internal/MacroCompatScala2.scala b/munit-core/shared/src/main/scala/munit/internal/MacroCompatScala2.scala deleted file mode 100644 index 90c298db..00000000 --- a/munit-core/shared/src/main/scala/munit/internal/MacroCompatScala2.scala +++ /dev/null @@ -1,95 +0,0 @@ -package munit.internal - -import munit.Clue -import munit.Location -import scala.reflect.macros.blackbox.Context -import scala.reflect.macros.TypecheckException -import scala.reflect.macros.ParseException - -object MacroCompatScala2 { - - def locationImpl(c: Context): c.Tree = { - import c.universe._ - val line = Literal(Constant(c.enclosingPosition.line)) - val path = Literal(Constant(c.enclosingPosition.source.path)) - New(c.mirror.staticClass(classOf[Location].getName()), path, line) - } - - def clueImpl(c: Context)(value: c.Tree): c.Tree = { - import c.universe._ - val text: String = - if (value.pos != null && value.pos.isRange) { - val chars = value.pos.source.content - val start = value.pos.start - val end = value.pos.end - if ( - end > start && - start >= 0 && start < chars.length && - end >= 0 && end < chars.length - ) { - new String(chars, start, end - start) - } else { - "" - } - } else { - "" - } - def simplifyType(tpe: Type): Type = tpe match { - case TypeRef(ThisType(pre), sym, args) if pre == sym.owner => - simplifyType(c.internal.typeRef(NoPrefix, sym, args)) - case t => - // uncomment to debug: - // Printers.log(t)(Location.empty) - t.widen - } - val source = Literal(Constant(text)) - val valueType = Literal(Constant(simplifyType(value.tpe).toString())) - New( - c.internal.typeRef( - NoPrefix, - c.mirror.staticClass(classOf[Clue[_]].getName()), - List(value.tpe.widen) - ), - source, - value, - valueType - ) - } - - def compileErrorsImpl(c: Context)(code: c.Tree): c.Tree = { - import c.universe._ - val toParse: String = code match { - case Literal(Constant(literal: String)) => literal - case _ => - c.abort( - code.pos, - "cannot compile dynamic expressions, only constant literals.\n" + - "To fix this problem, pass in a string literal in double quotes \"...\"" - ) - } - - def formatError(message: String, pos: scala.reflect.api.Position): String = - new StringBuilder() - .append("error:") - .append(if (message.contains('\n')) "\n" else " ") - .append(message) - .append("\n") - .append(pos.lineContent) - .append("\n") - .append(" " * (pos.column - 1)) - .append("^") - .toString() - - val message: String = - try { - c.typecheck(c.parse(s"{\n$toParse\n}")) - "" - } catch { - case e: ParseException => - formatError(e.getMessage(), e.pos) - case e: TypecheckException => - formatError(e.getMessage(), e.pos) - } - Literal(Constant(message)) - } -} diff --git a/munit-core/shared/src/main/scala/munit/internal/console/Lines.scala b/munit-core/shared/src/main/scala/munit/internal/console/Lines.scala deleted file mode 100644 index 440a55dc..00000000 --- a/munit-core/shared/src/main/scala/munit/internal/console/Lines.scala +++ /dev/null @@ -1,79 +0,0 @@ -package munit.internal.console - -import munit.internal.io.PlatformIO.{Files, Path, Paths} -import munit.Location - -import scala.collection.JavaConverters._ -import scala.collection.mutable -import scala.util.control.NonFatal -import munit.Clues - -class Lines extends Serializable { - private val filecache = mutable.Map.empty[Path, Array[String]] - - def formatLine(location: Location, message: String): String = { - formatLine(location, message, new Clues(Nil)) - } - def formatPath(location: Location): String = - location.path - def formatLine(location: Location, message: String, clues: Clues): String = { - try { - val path = Paths.get(location.path) - val lines = filecache.getOrElseUpdate( - path, { - Files.readAllLines(path).asScala.toArray - } - ) - val slice = lines.slice(location.line - 2, location.line + 1) - val out = new StringBuilder() - if (slice.length >= 2) { - val width = (location.line + 1).toString().length() + 1 - def format(n: Int): String = { - s"$n:".padTo(width, ' ') - } - val isMultilineMessage = message.contains('\n') - out - .append(formatPath(location)) - .append(':') - .append(location.line.toString()) - if (message.length() > 0 && !isMultilineMessage) { - out.append(" ").append(message) - } - out - .append('\n') - .append(format(location.line - 1)) - .append(slice(0)) - .append('\n') - .append( - munit.diff.console.AnsiColors - .use(munit.diff.console.AnsiColors.Reversed) - ) - .append(format(location.line)) - .append(slice(1)) - .append( - munit.diff.console.AnsiColors - .use(munit.diff.console.AnsiColors.Reset) - ) - if (slice.length >= 3) - out - .append('\n') - .append(format(location.line + 1)) - .append(slice(2)) - if (isMultilineMessage) { - out.append('\n').append(message) - } - if (clues.values.nonEmpty) { - out.append('\n').append(Printers.print(clues)) - } - } - out.toString() - } catch { - case NonFatal(_) => - if (clues.values.isEmpty) { - message - } else { - message + "\n" + Printers.print(clues) - } - } - } -} diff --git a/munit-core/shared/src/main/scala/munit/internal/console/Printers.scala b/munit-core/shared/src/main/scala/munit/internal/console/Printers.scala deleted file mode 100644 index 466b52d7..00000000 --- a/munit-core/shared/src/main/scala/munit/internal/console/Printers.scala +++ /dev/null @@ -1,239 +0,0 @@ -// Adaptation of https://github.com/lihaoyi/PPrint/blob/e6a918c259ed7ae1998bbf58c360334a3f0157ca/pprint/src/pprint/Walker.scala -package munit.internal.console - -import munit.internal.Compat -import munit.{EmptyPrinter, Location, Printable, Printer} - -import scala.annotation.switch -import munit.Clues - -object Printers { - def log(any: Any, printer: Printer = EmptyPrinter)(implicit - loc: Location - ): Unit = { - println(loc.toString) - println(print(any, printer)) - } - - /** Pretty-prints the value in a format that's optimized for producing diffs */ - def print(any: Any, printer: Printer = EmptyPrinter): String = { - var height = printer.height - val out = new StringBuilder() - val indentStep = 2 - def loop(a: Any, indent: Int): Unit = { - height -= 1 - if (height < 0) { - out.append("...") - return - } - val nextIndent = indent + indentStep - val isDone = printer.print(a, out, indent) - if (!isDone) { - a match { - case null => out.append("null") - case x: Printable => x.print(out, indent) - case x: Char => - out.append('\'') - if (x == '\'') out.append("\\'") - else printChar(x, out) - out.append('\'') - case x: Byte => out.append(x.toString()) - case x: Short => out.append(x.toString()) - case x: Int => out.append(x.toString()) - case x: Long => out.append(x.toString()) - case x: Float => out.append(x.toString()) - case x: Double => out.append(x.toString()) - case x: String => printString(x, out, printer) - case x: Clues => - printApply( - "Clues", - x.values.iterator, - out, - indent, - nextIndent, - open = " {", - close = "}", - comma = "" - ) { clue => - if (clue.source.nonEmpty) { - out.append(clue.source) - } - if (clue.valueType.nonEmpty) { - out.append(": ").append(clue.valueType) - } - out.append(" = ") - loop(clue.value, nextIndent) - } - case None => - out.append("None") - case Nil => - out.append("Nil") - case x: Map[_, _] => - printApply( - Compat.collectionClassName(x), - x.iterator, - out, - indent, - nextIndent - ) { case (key, value) => - loop(key, nextIndent) - out.append(" -> ") - loop(value, nextIndent) - } - case x: Iterable[_] => - printApply( - Compat.collectionClassName(x), - x.iterator, - out, - indent, - nextIndent - ) { value => loop(value, nextIndent) } - case x: Array[_] => - printApply( - "Array", - x.iterator, - out, - indent, - nextIndent - ) { value => loop(value, nextIndent) } - case it: Iterator[_] => - if (it.isEmpty) out.append("empty iterator") - else out.append("non-empty iterator") - case p: Product => - val elementNames = Compat.productElementNames(p) - val infiniteElementNames = Iterator.continually { - if (elementNames.hasNext) elementNames.next() - else "" - } - printApply( - p.productPrefix, - p.productIterator.zip(infiniteElementNames), - out, - indent, - nextIndent - ) { case (value, key) => - if (key.nonEmpty) { - out.append(key).append(" = ") - } - loop(value, nextIndent) - } - case _ => - out.append(a.toString()) - } - } - } - loop(any, indent = 0) - munit.diff.console.AnsiColors.filterAnsi(out.toString()) - } - - private def printApply[T]( - prefix: String, - it: Iterator[T], - out: StringBuilder, - indent: Int, - nextIndent: Int, - open: String = "(", - close: String = ")", - comma: String = "," - )(fn: T => Unit): Unit = { - out.append(prefix) - out.append(open) - if (it.hasNext) { - printNewline(out, nextIndent) - while (it.hasNext) { - val value = it.next() - fn(value) - if (it.hasNext) { - out.append(comma) - printNewline(out, nextIndent) - } else { - printNewline(out, indent) - } - } - } - out.append(close) - } - - private def printNewline(out: StringBuilder, indent: Int): Unit = { - out.append("\n") - var i = 0 - while (i < indent) { - out.append(' ') - i += 1 - } - } - - private def printString( - string: String, - out: StringBuilder, - printer: Printer - ): Unit = { - val isMultiline = printer.isMultiline(string) - if (isMultiline) { - out.append('"') - out.append('"') - out.append('"') - out.append(string) - out.append('"') - out.append('"') - out.append('"') - } else { - out.append('"') - var i = 0 - while (i < string.length()) { - printChar(string.charAt(i), out) - i += 1 - } - out.append('"') - } - } - - /** - * Pretty-prints this string with non-visible characters escaped. - * - * The exact definition of "non-visible" is fuzzy and is subject to change. - * The original motivation for this method was to fix - * https://github.com/scalameta/munit/issues/258 related to escaping \r in - * test names. - * - * The spirit of this method is to preserve "visible" characters like emojis - * and double quotes and escape "non-visible" characters like newlines and - * ANSI escape codes. A non-goal of this method is to make the output - * copy-pasteable back into source code unlike the `printChar` method, which - * escapes for example double-quote characters. - */ - def escapeNonVisible(string: String): String = { - val out = new StringBuilder() - var i = 0 - while (i < string.length()) { - val ch = string.charAt(i) - ch match { - case '"' | '\'' => out.append(ch) - case _ => printChar(ch, out, isEscapeUnicode = false) - } - i += 1 - } - out.toString() - } - - private def printChar( - c: Char, - sb: StringBuilder, - isEscapeUnicode: Boolean = true - ): Unit = - (c: @switch) match { - case '"' => sb.append("\\\"") - case '\\' => sb.append("\\\\") - case '\b' => sb.append("\\b") - case '\f' => sb.append("\\f") - case '\n' => sb.append("\\n") - case '\r' => sb.append("\\r") - case '\t' => sb.append("\\t") - case c => - val isNonReadableAscii = c < ' ' || (c > '~' && isEscapeUnicode) - if (isNonReadableAscii && !Character.isLetter(c)) - sb.append("\\u%04x".format(c.toInt)) - else sb.append(c) - } - -} diff --git a/munit-core/shared/src/main/scala/munit/internal/console/StackTraces.scala b/munit-core/shared/src/main/scala/munit/internal/console/StackTraces.scala deleted file mode 100644 index d6b3ce80..00000000 --- a/munit-core/shared/src/main/scala/munit/internal/console/StackTraces.scala +++ /dev/null @@ -1,61 +0,0 @@ -// Adaptation of https://github.com/lihaoyi/utest/blob/5c0fd1c25381592e1301f4bd97b0bf18a65a0a1a/utest/src/utest/framework/StackMarker.scala -package munit.internal.console - -import java.{util => ju} - -/** Utility methods for trimming unrelated elements from stack traces */ -class StackTraces -object StackTraces { - @noinline - def dropInside[T](t: => T): T = t - @noinline - def dropOutside[T](t: => T): T = t - - def trimStackTrace(ex: Throwable): ex.type = { - val isVisited = ju.Collections.newSetFromMap( - new ju.IdentityHashMap[Throwable, java.lang.Boolean]() - ) - def loop(e: Throwable): Unit = { - if (e != null && isVisited.add(e)) { - val stack = e.getStackTrace() - if (stack != null) { - e.setStackTrace(filterCallStack(stack)) - } - loop(e.getCause()) - } - } - loop(ex) - ex - } - private val className = "munit.internal.console.StackTraces$" - def filterCallStack( - stack: Array[StackTraceElement] - ): Array[StackTraceElement] = { - val droppedInside = stack.lastIndexWhere(x => - x.getClassName == className && - x.getMethodName == "dropInside" - ) - - val droppedOutside = stack.indexWhere(x => - x.getClassName == className && - x.getMethodName == "dropOutside" - ) - - val stack1 = stack.slice( - droppedInside match { - case -1 => 0 - case n => n + 3 - }, - droppedOutside match { - case -1 => stack.length - case n => n - } - ) - - val lastNonLMFIndex = - stack1.lastIndexWhere(x => !x.getClassName.contains("$$Lambda$")) - - if (lastNonLMFIndex < 0) stack1 - else stack1.take(lastNonLMFIndex + 1) - } -} diff --git a/munit/shared/src/main/scala/munit/Assertions.scala b/munit/shared/src/main/scala/munit/Assertions.scala index edfa19a9..22c3e5a2 100644 --- a/munit/shared/src/main/scala/munit/Assertions.scala +++ b/munit/shared/src/main/scala/munit/Assertions.scala @@ -4,7 +4,6 @@ import munit.internal.console.{Lines, StackTraces} import munit.diff.console.Printers import munit.diff.Printer import munit.diff.EmptyPrinter -import munit.Diffs import scala.reflect.ClassTag import scala.util.control.NonFatal @@ -53,7 +52,7 @@ trait Assertions extends MacroCompat.CompileErrorMacro { clue: => Any = "diff assertion failed" )(implicit loc: Location): Unit = { StackTraces.dropInside { - Diffs.assertNoDiff( + DiffsAssetion.assertNoDiff( obtained, expected, exceptionHandlerFromAssertions(this, Clues.empty), diff --git a/munit/shared/src/main/scala/munit/Compare.scala b/munit/shared/src/main/scala/munit/Compare.scala index 122a53ed..c2b8ccba 100644 --- a/munit/shared/src/main/scala/munit/Compare.scala +++ b/munit/shared/src/main/scala/munit/Compare.scala @@ -1,6 +1,5 @@ package munit -import munit.Diffs import scala.annotation.implicitNotFound /** @@ -60,7 +59,7 @@ trait Compare[A, B] { } // Attempt 1: custom pretty-printer that produces multiline output, which is // optimized for line-by-line diffing. - Diffs.assertNoDiff( + DiffsAssetion.assertNoDiff( assertions.munitPrint(obtained), assertions.munitPrint(expected), diffHandler, @@ -70,7 +69,7 @@ trait Compare[A, B] { // Attempt 2: try with `.toString` in case `munitPrint()` produces identical // formatting for both values. - Diffs.assertNoDiff( + DiffsAssetion.assertNoDiff( obtained.toString(), expected.toString(), diffHandler, diff --git a/munit/shared/src/main/scala/munit/ComparisonFailExceptionHandler.scala b/munit/shared/src/main/scala/munit/ComparisonFailExceptionHandler.scala index 4df24ac7..7f9ba7f6 100644 --- a/munit/shared/src/main/scala/munit/ComparisonFailExceptionHandler.scala +++ b/munit/shared/src/main/scala/munit/ComparisonFailExceptionHandler.scala @@ -1,7 +1,5 @@ package munit -import munit.Location - trait ComparisonFailExceptionHandler { def handle( message: String, diff --git a/munit/shared/src/main/scala/munit/Diffs.scala b/munit/shared/src/main/scala/munit/DiffsAssetion.scala similarity index 54% rename from munit/shared/src/main/scala/munit/Diffs.scala rename to munit/shared/src/main/scala/munit/DiffsAssetion.scala index c12cade6..c44db1f4 100644 --- a/munit/shared/src/main/scala/munit/Diffs.scala +++ b/munit/shared/src/main/scala/munit/DiffsAssetion.scala @@ -1,32 +1,8 @@ package munit -import munit.Location import munit.diff.Diff -object Diffs { - @deprecated("") - def assertNoDiff( - obtained: String, - expected: String, - fail: String => Nothing, - title: String = "", - printObtainedAsStripMargin: Boolean = true - )(implicit loc: Location): Boolean = { - assertNoDiff( - obtained, - expected, - new ComparisonFailExceptionHandler { - def handle( - message: String, - obtained: String, - expected: String, - loc: Location - ): Nothing = fail(message) - }, - title, - printObtainedAsStripMargin - ) - } +object DiffsAssetion { def assertNoDiff( obtained: String, @@ -53,4 +29,5 @@ object Diffs { ) } } + } diff --git a/munit/shared/src/main/scala/munit/MUnitRunner.scala b/munit/shared/src/main/scala/munit/MUnitRunner.scala index 348d79b3..47fa8ec6 100644 --- a/munit/shared/src/main/scala/munit/MUnitRunner.scala +++ b/munit/shared/src/main/scala/munit/MUnitRunner.scala @@ -80,7 +80,7 @@ class MUnitRunner(val cls: Class[_ <: Suite], newInstance: () => Suite) descriptions.getOrElseUpdate( test, { val escapedName = Printers.escapeNonVisible(test.name) - val testName = munit.internal.Compat.LazyList + val testName = munit.diff.internal.Compat.LazyList .from(0) .map { case 0 => escapedName diff --git a/munit/shared/src/main/scala/munit/Printer.scala b/munit/shared/src/main/scala/munit/Printer.scala deleted file mode 100644 index ee94cf53..00000000 --- a/munit/shared/src/main/scala/munit/Printer.scala +++ /dev/null @@ -1,107 +0,0 @@ -package munit - -/** - * Implement this trait to customize the default printer - */ -trait Printer { - - /** - * Pretty-print a single value during pretty printing. - * - * Returns true if this value has been printed, false if FunSuite should fallback to the default pretty-printer. - */ - def print(value: Any, out: StringBuilder, indent: Int): Boolean - def height: Int = Printer.defaultHeight - def isMultiline(string: String): Boolean = - string.contains('\n') - - /** - * Combine two printers into a single printer. - * - * Order is important : this printer will be tried first, then the other printer. - * The new Printer's height will be the max of the two printers' heights. - * - * Example use case : define some default printers for some types for all tests, - * and override it for some tests only. - * - * {{{ - * - * case class Person(name: String, age: Int, mail: String) - * - * trait MySuites extends FunSuite { - * override val printer = Printer.apply { - * case Person(name, age, mail) => s"$name:$age:$mail" - * case m: SomeOtherCaseClass => m.someCustomToString - * } - * } - * - * trait CompareMailsOnly extends MySuites { - * val mailOnlyPrinter = Printer.apply { - * case Person(_, _, mail) => mail - * } - * override val printer = mailOnlyPrinterPrinter orElse super.printer - * } - * - * }}} - */ - def orElse(other: Printer): Printer = { - val h = this.height - val p: (Any, StringBuilder, Int) => Boolean = this.print - new Printer { - def print(value: Any, out: StringBuilder, indent: Int): Boolean = - p.apply(value, out, indent) || other.print( - value, - out, - indent - ) - override def height: Int = h.max(other.height) - } - } - -} - -object Printer { - - val defaultHeight = 100 - - def apply( - height: Int - )(partialPrint: PartialFunction[Any, String]): Printer = { - val h = height - new Printer { - def print(value: Any, out: StringBuilder, indent: Int): Boolean = { - partialPrint.lift.apply(value) match { - case Some(string) => - out.append(string) - true - case None => false - } - } - - override def height: Int = h - } - } - - /** - * Utiliy constructor defining a printer for some types. - * - * Example use case is overriding the string repr for types which default pretty-printers - * do not output helpful diffs. - * - * {{{ - * type ByteArray = Array[Byte] - * val listPrinter = Printer.apply { - * case ll: ByteArray => ll.map(String.format("%02x", b)).mkString(" ") - * } - * val bytes = Array[Byte](1, 5, 8, 24) - * Printers.print(bytes, listPrinter) // "01 05 08 18" - * }}} - */ - def apply(partialPrint: PartialFunction[Any, String]): Printer = - apply(defaultHeight)(partialPrint) -} - -/** Default printer that does not customize the pretty-printer */ -object EmptyPrinter extends Printer { - def print(value: Any, out: StringBuilder, indent: Int): Boolean = false -} diff --git a/munit/shared/src/main/scala/munit/internal/console/Printers.scala b/munit/shared/src/main/scala/munit/internal/console/Printers.scala index ea3ccbd6..7b382bcb 100644 --- a/munit/shared/src/main/scala/munit/internal/console/Printers.scala +++ b/munit/shared/src/main/scala/munit/internal/console/Printers.scala @@ -1,15 +1,11 @@ // Adaptation of https://github.com/lihaoyi/PPrint/blob/e6a918c259ed7ae1998bbf58c360334a3f0157ca/pprint/src/pprint/Walker.scala package munit.internal.console -import munit.internal.Compat -import munit.{Location, Printable} +import munit.Location import munit.diff.Printer import munit.diff.EmptyPrinter import munit.diff.console.{Printers => DiffPrinters} -import scala.annotation.switch -import munit.Clues - object Printers { def log(any: Any, printer: Printer = EmptyPrinter)(implicit loc: Location diff --git a/tests/shared/src/test/scala/munit/CustomPrinterSuite.scala b/tests/shared/src/test/scala/munit/CustomPrinterSuite.scala index 610a9d10..97c9612b 100644 --- a/tests/shared/src/test/scala/munit/CustomPrinterSuite.scala +++ b/tests/shared/src/test/scala/munit/CustomPrinterSuite.scala @@ -2,6 +2,7 @@ package munit import org.scalacheck.Prop.forAll import munit.internal.console.Printers +import munit.diff.Printer import org.scalacheck.Arbitrary.arbitrary import org.scalacheck.Prop diff --git a/tests/shared/src/test/scala/munit/DiffsSuite.scala b/tests/shared/src/test/scala/munit/DiffsSuite.scala index 4c583e21..f8287268 100644 --- a/tests/shared/src/test/scala/munit/DiffsSuite.scala +++ b/tests/shared/src/test/scala/munit/DiffsSuite.scala @@ -1,12 +1,10 @@ package munit -import munit.diff.Diffs - class DiffsSuite extends FunSuite { self => test("ansi") { - val diff1 = Diffs.unifiedDiff("a", "b") - val diff2 = Diffs.unifiedDiff("a", "c") - val obtained = Diffs.unifiedDiff(diff1, diff2) + val diff1 = munit.diff.Diffs.unifiedDiff("a", "b") + val diff2 = munit.diff.Diffs.unifiedDiff("a", "c") + val obtained = munit.diff.Diffs.unifiedDiff(diff1, diff2) // Asserts that a roundtrip of ANSI color processing still produces // intuitive results. assertNoDiff( @@ -25,7 +23,7 @@ class DiffsSuite extends FunSuite { self => expected: String )(implicit loc: Location): Unit = { test(name) { - val obtained = Diffs.unifiedDiff(a, b) + val obtained = munit.diff.Diffs.unifiedDiff(a, b) assertNoDiff(obtained, expected) } }