diff options
author | Vlad Ureche <vlad.ureche@gmail.com> | 2012-07-11 23:56:32 +0200 |
---|---|---|
committer | Vlad Ureche <vlad.ureche@gmail.com> | 2012-07-16 23:41:44 +0200 |
commit | 0f2a0b7441153f3bdac49ca8878ffd9215458918 (patch) | |
tree | 7d8abd2e70c253c1d2d39fb811177e7859dbf31a | |
parent | b651269275a4cfd72761586e088bff5a130949b5 (diff) | |
download | scala-0f2a0b7441153f3bdac49ca8878ffd9215458918.tar.gz scala-0f2a0b7441153f3bdac49ca8878ffd9215458918.tar.bz2 scala-0f2a0b7441153f3bdac49ca8878ffd9215458918.zip |
Scaladoc: updated type class descriptions
The known type class descriptions give you a humanly-understandable
explanation for [T: TypeClass] in the implicit conversions. For
example [T: Integral] will tell you that T must be an integral type
such as Integer and co.
Now that the reflection dust settled, I can actually add the test to
make sure the well-known type classes are intercepted and explanations
are given instead of the usual "the type T is context-bounded by
TypeClass"
7 files changed, 90 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/ant/Scaladoc.scala b/src/compiler/scala/tools/ant/Scaladoc.scala index 9aa2f6f921..61db3c7fa9 100644 --- a/src/compiler/scala/tools/ant/Scaladoc.scala +++ b/src/compiler/scala/tools/ant/Scaladoc.scala @@ -677,5 +677,4 @@ class Scaladoc extends ScalaMatchingTask { "(no error message provided); see the error output for details.") } } - } diff --git a/src/compiler/scala/tools/nsc/doc/Settings.scala b/src/compiler/scala/tools/nsc/doc/Settings.scala index da478121e5..12b27387a7 100644 --- a/src/compiler/scala/tools/nsc/doc/Settings.scala +++ b/src/compiler/scala/tools/nsc/doc/Settings.scala @@ -209,16 +209,15 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_)) * the function result should be a humanly-understandable description of the type class */ val knownTypeClasses: Map[String, String => String] = Map() + - // TODO: Bring up to date and test these - ("scala.package.Numeric" -> ((tparam: String) => tparam + " is a numeric class, such as Int, Long, Float or Double")) + - ("scala.package.Integral" -> ((tparam: String) => tparam + " is an integral numeric class, such as Int or Long")) + - ("scala.package.Fractional" -> ((tparam: String) => tparam + " is a fractional numeric class, such as Float or Double")) + - ("scala.reflect.Manifest" -> ((tparam: String) => tparam + " is accompanied by a Manifest, which is a runtime representation of its type that survives erasure")) + - ("scala.reflect.ClassManifest" -> ((tparam: String) => tparam + " is accompanied by a ClassManifest, which is a runtime representation of its type that survives erasure")) + - ("scala.reflect.OptManifest" -> ((tparam: String) => tparam + " is accompanied by an OptManifest, which can be either a runtime representation of its type or the NoManifest, which means the runtime type is not available")) + - ("scala.reflect.ClassTag" -> ((tparam: String) => tparam + " is accompanied by a ClassTag, which is a runtime representation of its type that survives erasure")) + - ("scala.reflect.AbsTypeTag" -> ((tparam: String) => tparam + " is accompanied by an AbsTypeTag, which is a runtime representation of its type that survives erasure")) + - ("scala.reflect.TypeTag" -> ((tparam: String) => tparam + " is accompanied by a TypeTag, which is a runtime representation of its type that survives erasure")) + ("scala.math.Numeric" -> ((tparam: String) => tparam + " is a numeric class, such as Int, Long, Float or Double")) + + ("scala.math.Integral" -> ((tparam: String) => tparam + " is an integral numeric class, such as Int or Long")) + + ("scala.math.Fractional" -> ((tparam: String) => tparam + " is a fractional numeric class, such as Float or Double")) + + ("scala.reflect.Manifest" -> ((tparam: String) => tparam + " is accompanied by a Manifest, which is a runtime representation of its type that survives erasure")) + + ("scala.reflect.ClassManifest" -> ((tparam: String) => tparam + " is accompanied by a ClassManifest, which is a runtime representation of its type that survives erasure")) + + ("scala.reflect.OptManifest" -> ((tparam: String) => tparam + " is accompanied by an OptManifest, which can be either a runtime representation of its type or the NoManifest, which means the runtime type is not available")) + + ("scala.reflect.ClassTag" -> ((tparam: String) => tparam + " is accompanied by a ClassTag, which is a runtime representation of its type that survives erasure")) + + ("scala.reflect.AbsTypeTag" -> ((tparam: String) => tparam + " is accompanied by an AbsTypeTag, which is a runtime representation of its type that survives erasure")) + + ("scala.reflect.base.TypeTags.TypeTag" -> ((tparam: String) => tparam + " is accompanied by a TypeTag, which is a runtime representation of its type that survives erasure")) /** * Set of classes to exclude from index and diagrams diff --git a/src/compiler/scala/tools/nsc/doc/model/Entity.scala b/src/compiler/scala/tools/nsc/doc/model/Entity.scala index 42db408fee..626c1500f1 100644 --- a/src/compiler/scala/tools/nsc/doc/model/Entity.scala +++ b/src/compiler/scala/tools/nsc/doc/model/Entity.scala @@ -520,6 +520,9 @@ trait ImplicitConversion { /** The members inherited by this implicit conversion */ def members: List[MemberEntity] + + /** Is this a common implicit conversion (aka conversion that affects all classes, in Predef?) */ + def isCommonConversion: Boolean } /** Shadowing captures the information that the member is shadowed by some other members diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala index ddcdf1cf5c..bdae09e84d 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala @@ -115,7 +115,7 @@ trait ModelFactoryImplicitSupport { // Put the class-specific conversions in front val (ownConversions, commonConversions) = - conversions.partition(conv => !hardcoded.commonConversionTargets.contains(conv.conversionQualifiedName)) + conversions.partition(!_.isCommonConversion) ownConversions ::: commonConversions } @@ -347,7 +347,7 @@ trait ModelFactoryImplicitSupport { if (convSym != NoSymbol) makeTemplate(convSym.owner) else { - error("Scaladoc implicits: Implicit conversion from " + sym.tpe + " to " + toType + " done by " + convSym + " = NoSymbol!") + error("Scaladoc implicits: " + toString + " = NoSymbol!") makeRootPackage } @@ -415,6 +415,10 @@ trait ModelFactoryImplicitSupport { } lazy val members: List[MemberEntity] = memberImpls + + def isCommonConversion = hardcoded.commonConversionTargets.contains(conversionQualifiedName) + + override def toString = "Implcit conversion from " + sym.tpe + " to " + toType + " done by " + convSym } /* ========================= HELPER METHODS ========================== */ diff --git a/test/scaladoc/resources/implicits-known-type-classes-res.scala b/test/scaladoc/resources/implicits-known-type-classes-res.scala new file mode 100644 index 0000000000..9ad652947d --- /dev/null +++ b/test/scaladoc/resources/implicits-known-type-classes-res.scala @@ -0,0 +1,38 @@ +/** Tests the "known type classes" feature of scaladoc implicits + * if the test fails, please update the correct qualified name of + * the type class in src/compiler/scala/tools/nsc/doc/Settings.scala + * in the knownTypeClasses map. Thank you! */ +package scala.test.scaladoc.implicits.typeclasses { + class A[T] + object A { + import language.implicitConversions + import scala.reflect.{ClassTag, TypeTag} + implicit def convertNumeric [T: Numeric] (a: A[T]) = new B(implicitly[Numeric[T]]) + implicit def convertIntegral [T: Integral] (a: A[T]) = new B(implicitly[Integral[T]]) + implicit def convertFractional [T: Fractional] (a: A[T]) = new B(implicitly[Fractional[T]]) + implicit def convertManifest [T: Manifest] (a: A[T]) = new B(implicitly[Manifest[T]]) + implicit def convertClassManifest [T: ClassManifest] (a: A[T]) = new B(implicitly[ClassManifest[T]]) + implicit def convertOptManifest [T: OptManifest] (a: A[T]) = new B(implicitly[OptManifest[T]]) + implicit def convertClassTag [T: ClassTag] (a: A[T]) = new B(implicitly[ClassTag[T]]) + implicit def convertTypeTag [T: TypeTag] (a: A[T]) = new B(implicitly[TypeTag[T]]) + type K[X] = Numeric[X] + type L[X] = Integral[X] + type M[X] = Fractional[X] + type N[X] = Manifest[X] + type O[X] = ClassManifest[X] + type P[X] = OptManifest[X] + type Q[X] = ClassTag[X] + type R[X] = TypeTag[X] + implicit def convertK [T: K] (a: A[T]) = new B(implicitly[K[T]]) + implicit def convertL [T: L] (a: A[T]) = new B(implicitly[L[T]]) + implicit def convertM [T: M] (a: A[T]) = new B(implicitly[M[T]]) + implicit def convertN [T: N] (a: A[T]) = new B(implicitly[N[T]]) + implicit def convertO [T: O] (a: A[T]) = new B(implicitly[O[T]]) + implicit def convertP [T: P] (a: A[T]) = new B(implicitly[P[T]]) + implicit def convertQ [T: Q] (a: A[T]) = new B(implicitly[Q[T]]) + implicit def convertR [T: R] (a: A[T]) = new B(implicitly[R[T]]) + } + class B[T](t: T) { + def typeClass: T = t + } +}
\ No newline at end of file diff --git a/test/scaladoc/run/implicits-known-type-classes.check b/test/scaladoc/run/implicits-known-type-classes.check new file mode 100644 index 0000000000..619c56180b --- /dev/null +++ b/test/scaladoc/run/implicits-known-type-classes.check @@ -0,0 +1 @@ +Done. diff --git a/test/scaladoc/run/implicits-known-type-classes.scala b/test/scaladoc/run/implicits-known-type-classes.scala new file mode 100644 index 0000000000..9f4ca372b0 --- /dev/null +++ b/test/scaladoc/run/implicits-known-type-classes.scala @@ -0,0 +1,33 @@ +import scala.tools.nsc.doc.model._ +import scala.tools.partest.ScaladocModelTest +import language._ + +object Test extends ScaladocModelTest { + + // test a file instead of a piece of code + override def resourceFile = "implicits-known-type-classes-res.scala" + + // start implicits + def scaladocSettings = "-implicits" + + def testModel(root: Package) = { + // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s)) + import access._ + + /** Tests the "known type classes" feature of scaladoc implicits + * if the test fails, please update the correct qualified name of + * the type class in src/compiler/scala/tools/nsc/doc/Settings.scala + * in the knownTypeClasses map. Thank you! */ + + val base = root._package("scala")._package("test")._package("scaladoc")._package("implicits")._package("typeclasses") + var conv: ImplicitConversion = null + + val A = base._class("A") + + for (conversion <- A.conversions if !conversion.isCommonConversion) { + assert(conversion.constraints.length == 1, conversion.constraints.length + " == 1 (in " + conversion + ")") + assert(conversion.constraints.head.isInstanceOf[KnownTypeClassConstraint], + conversion.constraints.head + " is not a known type class constraint!") + } + } +} |