diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala | 126 | ||||
-rw-r--r-- | test/scaladoc/resources/SI-3314.scala | 15 | ||||
-rw-r--r-- | test/scaladoc/run/SI-3314.scala | 19 | ||||
-rw-r--r-- | test/scaladoc/run/SI-4887.check | 1 | ||||
-rw-r--r-- | test/scaladoc/run/SI-4887.scala | 46 |
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 |