From 4ddd8eb50a55b09d6ed7fe3900e4c9d065fd8bfb Mon Sep 17 00:00:00 2001 From: Kacper Korban Date: Tue, 17 Aug 2021 14:32:58 +0200 Subject: [PATCH 1/8] Fix displaying multi-line signatures --- scaladoc-testcases/src/tests/hugetype.scala | 39 +++++++++++++++++++ .../resources/dotty_res/styles/scalastyle.css | 10 ++--- .../scaladoc/renderers/MemberRenderer.scala | 7 ++-- .../scaladoc/tasty/ClassLikeSupport.scala | 28 ++++++------- .../tools/scaladoc/tasty/TypesSupport.scala | 10 +++-- 5 files changed, 67 insertions(+), 27 deletions(-) create mode 100644 scaladoc-testcases/src/tests/hugetype.scala diff --git a/scaladoc-testcases/src/tests/hugetype.scala b/scaladoc-testcases/src/tests/hugetype.scala new file mode 100644 index 000000000000..01a1c176bd6f --- /dev/null +++ b/scaladoc-testcases/src/tests/hugetype.scala @@ -0,0 +1,39 @@ +package tests.hugetype + +import compiletime._ +import compiletime.ops.int._ +import scala.annotation.experimental + +/** + * type + * noun + * + * a particular group of people or things that share similar characteristics and form a smaller division of a larger set: + * - There were so many different types of bread that I didn't know which to buy. + * - What type of clothes does she wear? + * - It was dark so I didn't notice what type of car it was. + * - He's the type of man you could take home to your mother. + * - He's very attractive, if you like the blond, athletic type. + * - They sell dried flowers and baskets and that type of thing. + * - We have a range of moisturizers for all different skin types. + * - She was young and she was wearing student-type clothes, so I assumed she was studying here. + * - He took me to a bar full of actor types trying to get noticed. + * + */ +type Take[T <: Tuple, N <: Int] <: Tuple = N match { + case 0 => EmptyTuple + case S[n1] => T match { + case EmptyTuple => EmptyTuple + case x *: xs => x *: Take[xs, n1] + } +} + +/** + * Some important information :o + * + * @param a any value of type forall a. a + * @return Nothing, because I haven't implemented it yet ^^ + */ +@experimental +@deprecated +implicit transparent inline def same[A](a: A): A = ??? diff --git a/scaladoc/resources/dotty_res/styles/scalastyle.css b/scaladoc/resources/dotty_res/styles/scalastyle.css index 679fbc846fb7..d918cba867e9 100644 --- a/scaladoc/resources/dotty_res/styles/scalastyle.css +++ b/scaladoc/resources/dotty_res/styles/scalastyle.css @@ -602,7 +602,7 @@ footer .mode { } .kind { - margin-left: 0.5em; + font-weight: bold; } .other-modifiers a, .other-modifiers a:visited, .other-modifiers span[data-unresolved-link] { @@ -610,7 +610,7 @@ footer .mode { } .documentableElement.expand .modifiers { - display: inline-table; + display: table-cell; min-width: 7em; } @@ -629,7 +629,7 @@ footer .mode { } .expand .signature { - display: inline; + display: table-cell; } .documentableElement { @@ -653,9 +653,7 @@ footer .mode { } .expand.documentableElement>div.header { - display: block; - padding-left: 4.5em; - text-indent: -4.5em; + display: inline-table; } .documentableElement>div .cover { diff --git a/scaladoc/src/dotty/tools/scaladoc/renderers/MemberRenderer.scala b/scaladoc/src/dotty/tools/scaladoc/renderers/MemberRenderer.scala index d62938f16f6d..d02b0bb7248a 100644 --- a/scaladoc/src/dotty/tools/scaladoc/renderers/MemberRenderer.scala +++ b/scaladoc/src/dotty/tools/scaladoc/renderers/MemberRenderer.scala @@ -134,16 +134,17 @@ class MemberRenderer(signatureRenderer: SignatureRenderer)(using DocContext) ext val rawBuilder = ScalaSignatureProvider.rawSignature(member, InlineSignatureBuilder()) val inlineBuilder = rawBuilder.asInstanceOf[InlineSignatureBuilder] - if inlineBuilder.preName.isEmpty then println(member) val kind :: modifiersRevered = inlineBuilder.preName val signature = inlineBuilder.names.reverse Seq( span(cls := "modifiers")( span(cls := "other-modifiers")(modifiersRevered.reverse.map(renderElement)), + ), + div(cls := "signature")( span(cls := "kind")(renderElement(kind)), + renderLink(member.name, member.dri, nameClasses), + span(signature.map(renderElement)) ), - renderLink(member.name, member.dri, nameClasses), - span(cls := "signature")(signature.map(renderElement)), ) def memberIcon(member: Member) = member.kind match { diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala index b1b3cac11e50..69e2ef0c6341 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala @@ -603,20 +603,20 @@ trait ClassLikeSupport: graph: HierarchyGraph = HierarchyGraph.empty, deprecated: Option[Annotation] = None, ) = Member( - name = symbol.normalizedName, - dri = symbol.dri, - kind = kind, - visibility = symbol.getVisibility(), - modifiers = modifiers, - annotations = symbol.getAnnotations(), - signature = signature, - sources = symbol.source, - origin = origin, - inheritedFrom = inheritedFrom, - graph = graph, - docs = symbol.documentation, - deprecated = deprecated - ) + name = symbol.normalizedName, + dri = symbol.dri, + kind = kind, + visibility = symbol.getVisibility(), + modifiers = modifiers, + annotations = symbol.getAnnotations(), + signature = signature, + sources = symbol.source, + origin = origin, + inheritedFrom = inheritedFrom, + graph = graph, + docs = symbol.documentation, + deprecated = deprecated + ) object EvidenceOnlyParameterList type RegularParameterList = Map[String, TypeRepr] diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala index 7156314e40aa..569b948631ad 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala @@ -80,7 +80,7 @@ trait TypesSupport: case _ => false // TODO #23 add support for all types signatures that makes sense - private def inner(using Quotes)(tp: reflect.TypeRepr): DocSignature = + private def inner(using Quotes)(tp: reflect.TypeRepr)(using indent: Int = 0): DocSignature = import reflect._ def noSupported(name: String): DocSignature = println(s"WARN: Unsupported type: $name: ${tp.show}") @@ -251,13 +251,15 @@ trait TypesSupport: case NoPrefix() => Nil case MatchType(bond, sc, cases) => + val caseSpaces = " " * (indent + 2) + val spaces = " " * (indent) val casesTexts = cases.flatMap { case MatchCase(from, to) => - texts(" case ") ++ inner(from) ++ texts(" => ") ++ inner(to) ++ texts("\n") + texts(caseSpaces + "case ") ++ inner(from) ++ texts(" => ") ++ inner(to)(using indent = indent + 2) ++ texts("\n") case TypeLambda(_, _, MatchCase(from, to)) => - texts(" case ") ++ inner(from) ++ texts(" => ") ++ inner(to) ++ texts("\n") + texts(caseSpaces + "case ") ++ inner(from) ++ texts(" => ") ++ inner(to)(using indent = indent + 2) ++ texts("\n") } - inner(sc) ++ texts(" match {\n") ++ casesTexts ++ texts("}") + inner(sc) ++ texts(" match {\n") ++ casesTexts ++ texts(spaces + "}") case ParamRef(TypeLambda(names, _, _), i) => texts(names.apply(i)) From d62c96cf3e2e4fd76ff65f52d5be267d0d1d3a2b Mon Sep 17 00:00:00 2001 From: Kacper Korban Date: Tue, 17 Aug 2021 14:49:31 +0200 Subject: [PATCH 2/8] Add transparent modifier --- scaladoc-testcases/src/tests/hugetype.scala | 1 + scaladoc/resources/dotty_res/styles/scalastyle.css | 4 ++-- scaladoc/src/dotty/tools/scaladoc/api.scala | 1 + scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/scaladoc-testcases/src/tests/hugetype.scala b/scaladoc-testcases/src/tests/hugetype.scala index 01a1c176bd6f..2e88e00abd03 100644 --- a/scaladoc-testcases/src/tests/hugetype.scala +++ b/scaladoc-testcases/src/tests/hugetype.scala @@ -6,6 +6,7 @@ import scala.annotation.experimental /** * type + * * noun * * a particular group of people or things that share similar characteristics and form a smaller division of a larger set: diff --git a/scaladoc/resources/dotty_res/styles/scalastyle.css b/scaladoc/resources/dotty_res/styles/scalastyle.css index d918cba867e9..9380c234fc97 100644 --- a/scaladoc/resources/dotty_res/styles/scalastyle.css +++ b/scaladoc/resources/dotty_res/styles/scalastyle.css @@ -648,7 +648,7 @@ footer .mode { display: table; } -.expand.documentableElement>div { +.documentableElement>div { display: block; } @@ -664,7 +664,7 @@ footer .mode { display: block; } -.expand .doc { +.doc { margin-left: 6.5em; } diff --git a/scaladoc/src/dotty/tools/scaladoc/api.scala b/scaladoc/src/dotty/tools/scaladoc/api.scala index c759bfe75b74..8f9cbfd2f31e 100644 --- a/scaladoc/src/dotty/tools/scaladoc/api.scala +++ b/scaladoc/src/dotty/tools/scaladoc/api.scala @@ -40,6 +40,7 @@ enum Modifier(val name: String, val prefix: Boolean): case Erased extends Modifier("erased", true) case Opaque extends Modifier("opaque", true) case Open extends Modifier("open", true) + case Transparent extends Modifier("transparent", true) case class ExtensionTarget(name: String, typeParams: Seq[TypeParameter], argsLists: Seq[ParametersList], signature: Signature, dri: DRI, position: Long) case class ImplicitConversion(from: DRI, to: DRI) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala index b98436a318c0..443062d8ad22 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala @@ -88,6 +88,7 @@ object SymOps: Flags.Open -> Modifier.Open, Flags.Override -> Modifier.Override, Flags.Case -> Modifier.Case, + Flags.Transparent -> Modifier.Transparent, ).collect { case (flag, mod) if sym.flags.is(flag) => mod } def isHiddenByVisibility(using dctx: DocContext): Boolean = From 3e2399f00cfdc8aa97342e06143f6176e628b710 Mon Sep 17 00:00:00 2001 From: Kacper Korban Date: Tue, 17 Aug 2021 14:59:09 +0200 Subject: [PATCH 3/8] Conditional anchor --- scaladoc/resources/dotty_res/styles/scalastyle.css | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scaladoc/resources/dotty_res/styles/scalastyle.css b/scaladoc/resources/dotty_res/styles/scalastyle.css index 9380c234fc97..dc012296a6f7 100644 --- a/scaladoc/resources/dotty_res/styles/scalastyle.css +++ b/scaladoc/resources/dotty_res/styles/scalastyle.css @@ -693,13 +693,17 @@ footer .mode { display: none; } +.documentableElement:hover .documentableAnchor:before { + display: flex; +} + .documentableAnchor:before { content: "\e901"; /* arrow down */ font-family: "dotty-icons" !important; - transform: rotate(45deg); + transform: rotate(-45deg); font-size: 20px; color: var(--icon-color); - display: flex; + display: none; flex-direction: row; align-items: center; justify-content: center; From 069875de4a8cf4a53dcac58010e4613e8795f830 Mon Sep 17 00:00:00 2001 From: Kacper Korban Date: Tue, 17 Aug 2021 17:35:06 +0200 Subject: [PATCH 4/8] Tweak css --- scaladoc-testcases/src/tests/hugetype.scala | 10 +++++---- .../resources/dotty_res/styles/scalastyle.css | 21 ++++++++----------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/scaladoc-testcases/src/tests/hugetype.scala b/scaladoc-testcases/src/tests/hugetype.scala index 2e88e00abd03..0744d6d1f750 100644 --- a/scaladoc-testcases/src/tests/hugetype.scala +++ b/scaladoc-testcases/src/tests/hugetype.scala @@ -5,10 +5,6 @@ import compiletime.ops.int._ import scala.annotation.experimental /** - * type - * - * noun - * * a particular group of people or things that share similar characteristics and form a smaller division of a larger set: * - There were so many different types of bread that I didn't know which to buy. * - What type of clothes does she wear? @@ -38,3 +34,9 @@ type Take[T <: Tuple, N <: Int] <: Tuple = N match { @experimental @deprecated implicit transparent inline def same[A](a: A): A = ??? + +trait Parent[X, A[_], B[_, _]] + +trait HugeTrait[X] extends Parent[X, HugeTrait, Map] + +trait EvenBiggerTrait[X, Y] extends Parent[X, Seq, EvenBiggerTrait] diff --git a/scaladoc/resources/dotty_res/styles/scalastyle.css b/scaladoc/resources/dotty_res/styles/scalastyle.css index dc012296a6f7..75fac599e063 100644 --- a/scaladoc/resources/dotty_res/styles/scalastyle.css +++ b/scaladoc/resources/dotty_res/styles/scalastyle.css @@ -262,6 +262,7 @@ th { padding-left: calc(1.015 * var(--side-width)); padding-right: calc(0.15 * var(--side-width)); box-sizing: border-box; + text-decoration: none; } #sideMenu2 a span:not(.micon) { @@ -582,13 +583,12 @@ footer .mode { .documentableElement .modifiers { display: table-cell; - padding-right: 0.5em; min-width: 10em; max-width: 10em; width: 10em; overflow: hidden; - direction: rtl; - white-space: nowrap; + text-align: right; + white-space: break-spaces; text-indent: 0em; } @@ -611,7 +611,6 @@ footer .mode { .documentableElement.expand .modifiers { display: table-cell; - min-width: 7em; } .documentableElement .signature { @@ -622,6 +621,11 @@ footer .mode { .signature.monospace { padding: 8px; + display: flex; +} + +.signature.monospace .modifiers { + white-space: break-spaces; } .signature a, .signature a:visited, .signature span[data-unresolved-link] { @@ -648,10 +652,6 @@ footer .mode { display: table; } -.documentableElement>div { - display: block; -} - .expand.documentableElement>div.header { display: inline-table; } @@ -664,10 +664,6 @@ footer .mode { display: block; } -.doc { - margin-left: 6.5em; -} - .doc code { padding: 0; } @@ -682,6 +678,7 @@ footer .mode { } .documentableElement .annotations { color: var(--grey600); + margin-left: 10em; display: none; } From a57756dc34f544f64af16a5362d58ae4866557a8 Mon Sep 17 00:00:00 2001 From: Kacper Korban Date: Tue, 17 Aug 2021 17:54:09 +0200 Subject: [PATCH 5/8] Fix displaying F-bounds in inheritance --- scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala index 569b948631ad..ed79da0e83b8 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala @@ -99,6 +99,9 @@ trait TypesSupport: inner(tpe) :+ text("*") case AnnotatedType(tpe, _) => inner(tpe) + case tl @ TypeLambda(params, paramBounds, resType@AppliedType(tpe, args)) + if paramBounds.map(inner).forall(_.isEmpty) && params.zip(args.map(inner)).forall(List(_) == _) => + inner(tpe) case tl @ TypeLambda(params, paramBounds, resType) => texts("[") ++ commas(params.zip(paramBounds).map { (name, typ) => val normalizedName = if name.matches("_\\$\\d*") then "_" else name From 6febf5cbca6a325ce0ca637e55edec8c5b43f0eb Mon Sep 17 00:00:00 2001 From: Kacper Korban Date: Tue, 17 Aug 2021 18:11:41 +0200 Subject: [PATCH 6/8] Tweak css a bit more --- scaladoc/resources/dotty_res/styles/scalastyle.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scaladoc/resources/dotty_res/styles/scalastyle.css b/scaladoc/resources/dotty_res/styles/scalastyle.css index 75fac599e063..f3e568f48c77 100644 --- a/scaladoc/resources/dotty_res/styles/scalastyle.css +++ b/scaladoc/resources/dotty_res/styles/scalastyle.css @@ -622,6 +622,7 @@ footer .mode { .signature.monospace { padding: 8px; display: flex; + border-radius: 3px; } .signature.monospace .modifiers { @@ -636,6 +637,10 @@ footer .mode { display: table-cell; } +.documentableFilter { + border-radius: 3px; +} + .documentableElement { color: var(--symbol-fg); white-space: normal; @@ -646,6 +651,7 @@ footer .mode { background: var(--documentable-bg); border-left: 0.25em solid transparent; margin: 0.5em 0; + border-radius: 3px; } .documentableElement>div { From 7d70ee886303b3d639da7dc31e0423b3f85da8d8 Mon Sep 17 00:00:00 2001 From: Kacper Korban Date: Wed, 18 Aug 2021 10:55:32 +0200 Subject: [PATCH 7/8] Fix tests --- .../test/dotty/tools/scaladoc/signatures/SignatureTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scaladoc/test/dotty/tools/scaladoc/signatures/SignatureTest.scala b/scaladoc/test/dotty/tools/scaladoc/signatures/SignatureTest.scala index c232f03a63a1..ebd53db8c77e 100644 --- a/scaladoc/test/dotty/tools/scaladoc/signatures/SignatureTest.scala +++ b/scaladoc/test/dotty/tools/scaladoc/signatures/SignatureTest.scala @@ -119,7 +119,7 @@ abstract class SignatureTest( val sigPrefix = elem.select(".header .signature").textNodes match case list if list.size > 0 && list.get(0).getWholeText().startsWith(" ") => " " case _ => "" - val all = s"$annotations$other $kind $name$sigPrefix$signature".trim() + val all = s"$annotations$other $sigPrefix$signature".trim() signatures += all } From da43aa7cb16391abb8ae2532bab80c6892dfebf8 Mon Sep 17 00:00:00 2001 From: Kacper Korban Date: Wed, 18 Aug 2021 16:07:08 +0200 Subject: [PATCH 8/8] Add infix flag and change longer modifiers to display as ellipsis --- scaladoc-testcases/src/tests/hugetype.scala | 24 ++++++++++++------- .../resources/dotty_res/styles/scalastyle.css | 9 ++++++- scaladoc/src/dotty/tools/scaladoc/api.scala | 1 + .../dotty/tools/scaladoc/tasty/SymOps.scala | 4 +++- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/scaladoc-testcases/src/tests/hugetype.scala b/scaladoc-testcases/src/tests/hugetype.scala index 0744d6d1f750..2f0f7f79540b 100644 --- a/scaladoc-testcases/src/tests/hugetype.scala +++ b/scaladoc-testcases/src/tests/hugetype.scala @@ -25,15 +25,21 @@ type Take[T <: Tuple, N <: Int] <: Tuple = N match { } } -/** - * Some important information :o - * - * @param a any value of type forall a. a - * @return Nothing, because I haven't implemented it yet ^^ - */ -@experimental -@deprecated -implicit transparent inline def same[A](a: A): A = ??? +trait E: + @experimental + @deprecated + protected implicit def same[A](a: A): A + +trait XD extends E: + /** + * Some important information :o + * + * @param a any value of type forall a. a + * @return Nothing, because I haven't implemented it yet ^^ + */ + @experimental + @deprecated + protected override final implicit transparent inline abstract infix def same[A](a: A): A = a trait Parent[X, A[_], B[_, _]] diff --git a/scaladoc/resources/dotty_res/styles/scalastyle.css b/scaladoc/resources/dotty_res/styles/scalastyle.css index f3e568f48c77..4657d59b0673 100644 --- a/scaladoc/resources/dotty_res/styles/scalastyle.css +++ b/scaladoc/resources/dotty_res/styles/scalastyle.css @@ -588,8 +588,15 @@ footer .mode { width: 10em; overflow: hidden; text-align: right; - white-space: break-spaces; + white-space: nowrap; + text-overflow: ellipsis; text-indent: 0em; + padding-right: 0.5em; +} + +.documentableElement.expand .modifiers { + white-space: break-spaces; + text-overflow: unset; } .documentableElement .docs { diff --git a/scaladoc/src/dotty/tools/scaladoc/api.scala b/scaladoc/src/dotty/tools/scaladoc/api.scala index 8f9cbfd2f31e..b96e3f219740 100644 --- a/scaladoc/src/dotty/tools/scaladoc/api.scala +++ b/scaladoc/src/dotty/tools/scaladoc/api.scala @@ -41,6 +41,7 @@ enum Modifier(val name: String, val prefix: Boolean): case Opaque extends Modifier("opaque", true) case Open extends Modifier("open", true) case Transparent extends Modifier("transparent", true) + case Infix extends Modifier("infix", true) case class ExtensionTarget(name: String, typeParams: Seq[TypeParameter], argsLists: Seq[ParametersList], signature: Signature, dri: DRI, position: Long) case class ImplicitConversion(from: DRI, to: DRI) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala index 443062d8ad22..bcc84d0603dc 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala @@ -70,6 +70,7 @@ object SymOps: case (None, None, (false, true, true)) => Visibility.Protected(ThisScope) case (None, None, (false, true, false)) => Visibility.Protected(implicitScope(sym.owner)) case (None, None, (false, false, false)) => Visibility.Unrestricted + case (None, None, (true, true, false)) => Visibility.Protected(ThisScope) case _ => throw new Exception(s"Visibility for symbol $sym cannot be determined") @@ -83,12 +84,13 @@ object SymOps: Flags.Abstract -> Modifier.Abstract, Flags.Deferred -> Modifier.Deferred, Flags.Implicit -> Modifier.Implicit, + Flags.Infix -> Modifier.Infix, + Flags.Transparent -> Modifier.Transparent, Flags.Inline -> Modifier.Inline, Flags.Lazy -> Modifier.Lazy, Flags.Open -> Modifier.Open, Flags.Override -> Modifier.Override, Flags.Case -> Modifier.Case, - Flags.Transparent -> Modifier.Transparent, ).collect { case (flag, mod) if sym.flags.is(flag) => mod } def isHiddenByVisibility(using dctx: DocContext): Boolean =