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

org.scalactic.Snapshots.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2001-2014 Artima, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.scalactic

import scala.quoted._

/**
 * Case class that stores the name and value of a variable or expression.
 *
 * 

* See the main documentation for trait Snapshots for more information and examples. *

* * @param name the name of the expression * @param value the value of the expression */ final case class Snapshot(name: String, value: Any) { /** * Overriden toString to print in {name} = {value} format. * * @return string in {name} = {value} format */ override def toString: String = Resources.variableWasValue(name, Prettifier.default(value)) } /** *

Trait that provides a snap method that takes one or more arguments and results in a * SnapshotSeq, whose toString lists the names * and values of each argument. * *

* The intended use case of this trait is to help you write debug and log * messages that give a "snapshot" of program state. Here's an example: *

* *
 * scala> import Snapshots._
 * import Snapshots._
 *
 * scala> snap(a, b, c, d, e, f)
 * res3: org.scalactic.SnapshotSeq = a was 1, b was 2, c was 3, d was 4, e was null, f was null
 * 
* *

SnapshotSeq offers a lines method that places each variable name/value pair on its own line:

* *

 * scala> snap(a, b, c, d, e, f).lines
 * res4: String =
 * a was 1
 * b was 2
 * c was 3
 * d was 4
 * e was null
 * f was null
 * 
* *

* Or, because a SnapshotSeq is a IndexedSeq[Snapshot], you can process it just like any other Seq, for example: *

* *
 * scala> snap(a, b, c, d, e, f).mkString("Wow! ", ", and ", ". That's so awesome!")
 * res6: String = Wow! a was 1, and b was 2, and c was 3, and d was 4, and e was null, and f was null. That's so awesome!
 * 
*/ trait Snapshots { /** * Snap the given expressions. * * @param expressions expressions to be snapped * @return an IndexedSeq of Snapshot for the given expressions. */ inline def snap(expressions: Any*): SnapshotSeq = ${ SnapshotsMacro.snap('expressions) } } /** * An IndexedSeq[Snapshot] providing toString and lines methods that * can be useful for debug and log messages about program state. * *

* See the main documentation for trait Snapshots for more information and examples. *

*/ final class SnapshotSeq(underlying: collection.immutable.IndexedSeq[Snapshot]) extends collection.immutable.IndexedSeq[Snapshot] { /** * Selects an element by its index in the sequence. * *

* This method invokes apply on the underlying immutable IndexedSeq[String], passing in idx, and returns the result. *

* * @param idx the index to select * @return the element of this sequence at index idx, where 0 indicates the first element */ def apply(idx: Int): Snapshot = underlying.apply(idx) /** * The length of this sequence. * *

* This method invokes length on the underlying immutable IndexedSeq[String] and returns the result. *

* * @return the number of elements in this sequence */ def length: Int = underlying.length /** * Appends a string element to this sequence, if it doesn't already exist in the sequence. * *

* If the string element already exists in this sequence, this method returns itself. If not, * this method returns a new MultiSelOptionSeq with the passed value appended to the * end of the original MultiSelOptionSeq. *

* * @param the string element to append to this sequence * @return a MultiSelOptionSeq that contains the passed string value */ def +(value: Snapshot): SnapshotSeq = { if (!underlying.contains(value)) new SnapshotSeq(underlying :+ value) else this } /** * Removes a string element to this sequence, if it already exists in the sequence. * *

* If the string element does not already exist in this sequence, this method returns itself. If the element * is contained in this sequence, this method returns a new MultiSelOptionSeq with the passed value * removed from the the original MultiSelOptionSeq, leaving any other elements in the same order. *

* * @param the string element to append to this sequence * @return a MultiSelOptionSeq that contains the passed string value */ def -(value: Snapshot): SnapshotSeq = { if (underlying.contains(value)) new SnapshotSeq(underlying.filter(_ != value)) else this } /** * The default way to present the result of the snap method of trait
Snapshots. * * Here's an example: * *
   * scala> snap(a, b, c, d, e, f)
   * res3: org.scalactic.SnapshotSeq = a was 1, b was 2, c was 3, d was 4, e was null, f was null
   * 
*/ override def toString: String = mkString(", ") /** * An alternate way to present the result of the snap method of trait Snapshots that * puts each variable or expression on its own line. * * Here's an example: * *
   * scala> snap(a, b, c, d, e, f).lines
   * res4: String =
   * a was 1
   * b was 2
   * c was 3
   * d was 4
   * e was null
   * f was null
   * 
*/ def lines: String = mkString("\n") } object SnapshotSeq { def apply(snapshots: Snapshot*): SnapshotSeq = new SnapshotSeq(Vector(snapshots: _*)) } /** * Companion object that facilitates the importing of Snapshots members as * an alternative to mixing it in. One use case is to import Snapshots members so you can use * them in the Scala interpreter: * *
 * $scala -classpath scalatest.jar
 * Welcome to Scala version 2.10.3.final (Java HotSpot(TM) Client VM, Java xxxxxx).
 * Type in expressions to have them evaluated.
 * Type :help for more information.
 *  
 * scala> import org.scalactic.Snapshots._
 * import org.scalatest.Snapshots._
 *  
 * scala> val a = 8
 * a: Int = 8
 * 
 * scala> snap(a)
 * res0: scala.collection.immutable.Vector[org.scalactic.Snapshot] = Vector(a = 8)
 * 
*/ object Snapshots extends Snapshots object SnapshotsMacro { def snap(expressions: Expr[Seq[Any]])(using Quotes): Expr[SnapshotSeq] = { import quotes.reflect._ def liftSeq(args: Seq[Expr[Snapshot]]): Expr[Seq[Snapshot]] = args match { case x :: xs => '{ ($x) +: ${ liftSeq(xs) } } case Nil => '{ Seq(): Seq[Snapshot] } } val snapshots: List[Expr[Snapshot]] = expressions.asTerm.underlyingArgument match { case Typed(Repeated(args, _), _) => // only sequence literal args.map { arg => val str = Expr(arg.asExpr.show) '{ Snapshot($str, ${ arg.asExpr }) } } case arg => report.throwError("snap can only be used with sequence literal, not `seq : _*`") } val argumentsS: Expr[Seq[Snapshot]] = liftSeq(snapshots) '{ SnapshotSeq($argumentsS : _*) } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy