/* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ // $Id: Show.scala 18235 2009-07-07 13:22:17Z michelou $ package scala.testing /** <p> * Classes inheriting trait <code>Show</code> can test their member methods * using the notattion <code>meth(arg<sub>1</sub>, ..., arg<sub>n</sub>)</code>, * where <code>meth</code> is the name of the method and * <code>arg<sub>1</sub>,...,arg<sub>n</sub></code> are the arguments. * The only difference to a normal method call is the leading quote * character ('). A quoted method call like the one above will produces a * legible diagnostic to be printed on <a href="../Console.html" * target="ContentFrame"><code>Console</code></a>. It is of the form * </p><pre> * meth(arg<sub>1</sub>, ..., arg<sub>n</sub>) gives <result></pre> * <p> * where <code><result></code> is the result of evaluating the call. * </p> */ trait Show { /** The result class of wrapper <code>symApply</code>. * Prints out diagnostics of method applications. */ class SymApply(f: Symbol) { def apply[A](args: A*) { println(test(f, args: _*)) } } /** An implicit definition that adds an apply method to Symbol which forwards to `test`. */ implicit def symApply(sym: Symbol) = new SymApply(sym) /** Apply method with name of given symbol `f` to given arguments and return * a result diagnostics. */ def test[A](f: Symbol, args: A*): String = { val args1 = args map (_.asInstanceOf[AnyRef]) def testMethod(meth: java.lang.reflect.Method): String = f.name+"("+(args mkString ",")+") gives "+ { try { meth.invoke(this, args1: _*) } catch { case ex: IllegalAccessException => ex case ex: IllegalArgumentException => ex case ex: java.lang.reflect.InvocationTargetException => ex } } getClass.getMethods.toList filter (_.getName == f.name) match { case List() => f.name+" is not defined" case List(m) => testMethod(m) case ms => // multiple methods, disambiguate by number of arguments ms filter (_.getParameterTypes.length == args.length) match { case List() => testMethod(ms.head) // go ahead anyway, to get an exception case List(m) => testMethod(m) case ms => "cannot disambiguate between multiple implementations of "+f.name } } } }