summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala126
-rw-r--r--test/scaladoc/resources/SI-3314.scala15
-rw-r--r--test/scaladoc/run/SI-3314.scala19
-rw-r--r--test/scaladoc/run/SI-4887.check1
-rw-r--r--test/scaladoc/run/SI-4887.scala46
5 files changed, 200 insertions, 7 deletions
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala
index 2bc9f070b1..0463ac0420 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala
@@ -83,8 +83,6 @@ trait ModelFactoryTypeSupport {
val owner =
if ((preSym != NoSymbol) && /* it needs a prefix */
(preSym != bSym.owner) && /* prefix is different from owner */
- // ((preSym != inTpl.sym) && /* prevent prefixes from being shown inside the defining class */
- // (preSym != inTpl.sym.moduleClass)) && /* or object */
(aSym == bSym)) /* normalization doesn't play tricks on us */
preSym
else
@@ -112,8 +110,14 @@ trait ModelFactoryTypeSupport {
// but we won't show the prefix if our symbol is among them, only if *it's not* -- that's equal to showing
// the prefix only for ambiguous references, not for overloaded ones.
def needsPrefix: Boolean = {
- if (owner != bSym.owner && (normalizeTemplate(owner) != inTpl.sym))
+ if ((owner != bSym.owner || preSym.isRefinementClass) && (normalizeTemplate(owner) != inTpl.sym))
return true
+ // don't get tricked into prefixng method type params and existentials:
+ // I tried several tricks BUT adding the method for which I'm creating the type => that simply won't scale,
+ // as ValueParams are independent of their parent member, and I really don't want to add this information to
+ // all terms, as we're already over the allowed memory footprint
+ if (aSym.isTypeParameterOrSkolem || aSym.isExistentiallyBound /* existential or existential skolem */)
+ return false
for (tpl <- inTpl.sym.ownerChain) {
tpl.info.member(bSym.name) match {
@@ -137,8 +141,16 @@ trait ModelFactoryTypeSupport {
val prefix =
if (!settings.docNoPrefixes.value && needsPrefix && (bSym != AnyRefClass /* which we normalize */)) {
- val qualifiedName = makeQualifiedName(owner, Some(inTpl.sym))
- if (qualifiedName != "") qualifiedName + "." else ""
+ if (!owner.isRefinementClass) {
+ val qName = makeQualifiedName(owner, Some(inTpl.sym))
+ if (qName != "") qName + "." else ""
+ }
+ else {
+ nameBuffer append "("
+ appendType0(pre)
+ nameBuffer append ")#"
+ "" // we already appended the prefix
+ }
} else ""
//DEBUGGING:
@@ -175,15 +187,117 @@ trait ModelFactoryTypeSupport {
case NullaryMethodType(result) =>
nameBuffer append '⇒'
appendType0(result)
+
/* Polymorphic types */
case PolyType(tparams, result) => assert(tparams.nonEmpty)
-// throw new Error("Polymorphic type '" + tpe + "' cannot be printed as a type")
def typeParamsToString(tps: List[Symbol]): String = if (tps.isEmpty) "" else
tps.map{tparam =>
tparam.varianceString + tparam.name + typeParamsToString(tparam.typeParams)
}.mkString("[", ", ", "]")
nameBuffer append typeParamsToString(tparams)
appendType0(result)
+
+ case et@ExistentialType(quantified, underlying) =>
+
+ def appendInfoStringReduced(sym: Symbol, tp: Type): Unit = {
+ if (sym.isType && !sym.isAliasType && !sym.isClass) {
+ tp match {
+ case PolyType(tparams, _) =>
+ nameBuffer append "["
+ appendTypes0(tparams.map(_.tpe), ", ")
+ nameBuffer append "]"
+ case _ =>
+ }
+ tp.resultType match {
+ case rt @ TypeBounds(_, _) =>
+ appendType0(rt)
+ case rt =>
+ nameBuffer append " <: "
+ appendType0(rt)
+ }
+ } else {
+ // fallback to the Symbol infoString
+ nameBuffer append sym.infoString(tp)
+ }
+ }
+
+ def appendClauses = {
+ nameBuffer append " forSome {"
+ var first = true
+ val qset = quantified.toSet
+ for (sym <- quantified) {
+ if (!first) { nameBuffer append ", " } else first = false
+ if (sym.isSingletonExistential) {
+ nameBuffer append "val "
+ nameBuffer append tpnme.dropSingletonName(sym.name)
+ nameBuffer append ": "
+ appendType0(dropSingletonType(sym.info.bounds.hi))
+ } else {
+ if (sym.flagString != "") nameBuffer append (sym.flagString + " ")
+ if (sym.keyString != "") nameBuffer append (sym.keyString + " ")
+ nameBuffer append sym.varianceString
+ nameBuffer append sym.nameString
+ appendInfoStringReduced(sym, sym.info)
+ }
+ }
+ nameBuffer append "}"
+ }
+
+ underlying match {
+ case TypeRef(pre, sym, args) if et.isRepresentableWithWildcards =>
+ appendType0(typeRef(pre, sym, Nil))
+ nameBuffer append "["
+ var first = true
+ val qset = quantified.toSet
+ for (arg <- args) {
+ if (!first) { nameBuffer append ", " } else first = false
+ arg match {
+ case TypeRef(_, sym, _) if (qset contains sym) =>
+ nameBuffer append "_"
+ appendInfoStringReduced(sym, sym.info)
+ case arg =>
+ appendType0(arg)
+ }
+ }
+ nameBuffer append "]"
+ case MethodType(_, _) | NullaryMethodType(_) | PolyType(_, _) =>
+ nameBuffer append "("
+ appendType0(underlying)
+ nameBuffer append ")"
+ appendClauses
+ case _ =>
+ appendType0(underlying)
+ appendClauses
+ }
+
+ case tb@TypeBounds(lo, hi) =>
+ if (tb.lo != TypeBounds.empty.lo) {
+ nameBuffer append " >: "
+ appendType0(lo)
+ }
+ if (tb.hi != TypeBounds.empty.hi) {
+ nameBuffer append " <: "
+ appendType0(hi)
+ }
+ // case tpen: ThisType | SingleType | SuperType =>
+ // if (tpen.isInstanceOf[ThisType] && tpen.asInstanceOf[ThisType].sym.isEffectiveRoot) {
+ // appendType0 typeRef(NoPrefix, sym, Nil)
+ // } else {
+ // val underlying =
+ // val pre = underlying.typeSymbol.skipPackageObject
+ // if (pre.isOmittablePrefix) pre.fullName + ".type"
+ // else prefixString + "type"
+ case tpen@ThisType(sym) =>
+ appendType0(typeRef(NoPrefix, sym, Nil))
+ nameBuffer append ".this"
+ if (!tpen.underlying.typeSymbol.skipPackageObject.isOmittablePrefix) nameBuffer append ".type"
+ case tpen@SuperType(thistpe, supertpe) =>
+ nameBuffer append "super["
+ appendType0(supertpe)
+ nameBuffer append "]"
+ case tpen@SingleType(pre, sym) =>
+ appendType0(typeRef(pre, sym, Nil))
+ if (!tpen.underlying.typeSymbol.skipPackageObject.isOmittablePrefix) nameBuffer append ".type"
case tpen =>
nameBuffer append tpen.toString
}
diff --git a/test/scaladoc/resources/SI-3314.scala b/test/scaladoc/resources/SI-3314.scala
index e5773a4970..9e0afdce9d 100644
--- a/test/scaladoc/resources/SI-3314.scala
+++ b/test/scaladoc/resources/SI-3314.scala
@@ -1,5 +1,6 @@
package scala.test.scaladoc {
+ // testing inherited <documented> templates (Enum.Value is included in the source, thus is documented in scaladoc)
package test1 {
class Enum {
abstract class Value
@@ -12,6 +13,8 @@ package scala.test.scaladoc {
}
}
+ // testing inherited <not documented> templates (scala.Enumeration.Value is taken from the library, thus is not
+ // documented in the scaladoc pages -- but should be inherited to make things clear!)
package test2 {
trait WeekDayTrait extends Enumeration {
type WeekDay = Value
@@ -67,4 +70,16 @@ package scala.test.scaladoc {
def isWorkingDay9(d: WeekDayObject.Value) = ! (d == Sat || d == Sun)
}
}
+
+ // testing type lambdas and useless prefixes (should be referenced as T instead of foo.T in the first example)
+ package test3 {
+ import language.higherKinds
+ object `package` {
+ trait T
+ trait A
+ trait X
+ def foo[T](x: T) = 7
+ def bar[A](x: ({type Lambda[X] <: Either[A, X]})#Lambda[String]) = 5
+ }
+ }
}
diff --git a/test/scaladoc/run/SI-3314.scala b/test/scaladoc/run/SI-3314.scala
index 3b5c658078..fe220b08af 100644
--- a/test/scaladoc/run/SI-3314.scala
+++ b/test/scaladoc/run/SI-3314.scala
@@ -6,7 +6,7 @@ object Test extends ScaladocModelTest {
override def resourceFile = "SI-3314.scala"
// no need for special settings
- def scaladocSettings = ""
+ def scaladocSettings = "-feature"
def testModel(rootPackage: Package) = {
// get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
@@ -15,6 +15,10 @@ object Test extends ScaladocModelTest {
// just need to check the member exists, access methods will throw an error if there's a problem
val base = rootPackage._package("scala")._package("test")._package("scaladoc")
+
+
+ // test1
+
val test1 = base._package("test1")
val test1Value = test1._class("Enum")._method("Value").resultType
assert(test1Value.name == "Value", test1Value.name + " == Value")
@@ -26,6 +30,9 @@ object Test extends ScaladocModelTest {
assert(test1Constants.refEntity(0)._1 == LinkToMember(test1._object("Constants")._class("Value"), test1._object("Constants")),
test1Constants.refEntity(0)._1 + " == LinkToMember(test1.Enum.Value)")
+
+ // test2
+
val test2 = base._package("test2")
def testDefinition(doc: DocTemplateEntity) = {
for (day <- List("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")) {
@@ -70,5 +77,15 @@ object Test extends ScaladocModelTest {
testUsage(test2._object("UserObject"))
testUsage(test2._class("UserClass"))
testUsage(test2._trait("UserTrait"))
+
+
+ // test3
+ val test3 = base._package("test3")
+ val foo = test3._method("foo")
+ assert(foo.valueParams(0)(0).resultType.name == "T",
+ foo.valueParams(0)(0).resultType.name + " == T")
+ val bar = test3._method("bar")
+ assert(bar.valueParams(0)(0).resultType.name == "(AnyRef { type Lambda[X] <: Either[A,X] })#Lambda[String]",
+ bar.valueParams(0)(0).resultType.name + " == (AnyRef { type Lambda[X] <: Either[A,X] })#Lambda[String]")
}
} \ No newline at end of file
diff --git a/test/scaladoc/run/SI-4887.check b/test/scaladoc/run/SI-4887.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/SI-4887.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/SI-4887.scala b/test/scaladoc/run/SI-4887.scala
new file mode 100644
index 0000000000..af83344613
--- /dev/null
+++ b/test/scaladoc/run/SI-4887.scala
@@ -0,0 +1,46 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def code = """
+ package scala.test.scaladoc.existentials {
+ import language.higherKinds
+ import language.existentials
+
+ class X[T, U, V]
+
+ trait TEST {
+ type T
+ type U
+ type A
+ def foo1(x: X[T, U, _]) = 3
+ def foo2(x: X[Z[_], U, z.type] forSome {type Z[_] <: { def z: String }; val z: Z[_ <: Int]}) = 4
+ def foo3(x: X[Z, Z, V] forSome { type Z <: T; type V <: T }) = 6
+ }
+ }
+ """
+
+ // no need for special settings
+ def scaladocSettings = "-feature"
+
+ def testModel(rootPackage: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ val base = rootPackage._package("scala")._package("test")._package("scaladoc")._package("existentials")
+ val TEST = base._trait("TEST")
+
+ val foo1 = TEST._method("foo1")
+ assert(foo1.valueParams(0)(0).resultType.name == "X[T, U, _]",
+ foo1.valueParams(0)(0).resultType.name + " == X[T, U, _]")
+
+ val foo2 = TEST._method("foo2")
+ assert(foo2.valueParams(0)(0).resultType.name == "X[Z[_], U, _ <: [_]AnyRef { def z: String } with Singleton]",
+ foo2.valueParams(0)(0).resultType.name + " == X[Z[_], U, _ <: [_]AnyRef { def z: String } with Singleton]")
+
+ val foo3 = TEST._method("foo3")
+ assert(foo3.valueParams(0)(0).resultType.name == "X[Z, Z, V] forSome {type Z <: T, type V <: T}",
+ foo3.valueParams(0)(0).resultType.name + " == X[Z, Z, V] forSome {type Z <: T, type V <: T}")
+ }
+} \ No newline at end of file