Skip to content

Commit c79f586

Browse files
committed
Add extension suffixes and fqName to scaladoc searchbar
Extension suffixes in the form of italized 'extension on (...)' allow to separate semantically different methods, which previously would have been displayed as the same in searchbar. File-based location was also replaced with fully qualified name based, in an effort to improve readability.
1 parent 5e7ac1d commit c79f586

File tree

5 files changed

+35
-12
lines changed

5 files changed

+35
-12
lines changed

scaladoc-js/common/css/searchbar.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ div[selected] > .scaladoc-searchbar-inkuire-package {
175175
display: none;
176176
}
177177

178+
#scaladoc-searchbar span.italic {
179+
font-style: italic;
180+
}
181+
178182
#scaladoc-searchbar {
179183
position: fixed;
180184
top: 50px;

scaladoc-js/main/src/searchbar/PageEntry.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import scala.scalajs.js
66
trait PageEntryJS extends js.Object {
77
val n: String = js.native
88
val t: String = js.native
9+
val i: String = js.native
910
val d: String = js.native
1011
val l: String = js.native
1112
val e: Boolean = js.native
@@ -15,6 +16,7 @@ trait PageEntryJS extends js.Object {
1516
case class PageEntry(
1617
fullName: String,
1718
description: String,
19+
extensionTarget: String,
1820
location: String,
1921
isLocationExternal: Boolean,
2022
shortName: String,
@@ -35,6 +37,7 @@ object PageEntry {
3537
def apply(jsObj: PageEntryJS): PageEntry = PageEntry(
3638
jsObj.t,
3739
jsObj.d,
40+
jsObj.i,
3841
jsObj.l,
3942
jsObj.e,
4043
jsObj.n.toLowerCase,

scaladoc-js/main/src/searchbar/SearchbarComponent.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,16 @@ class SearchbarComponent(engine: SearchbarEngine, inkuireEngine: InkuireJSSearch
2323
Globals.pathToRoot + p.location
2424
}
2525

26+
val extensionTargetMessage = if (p.extensionTarget.isEmpty()) {
27+
""
28+
} else {
29+
" extension on " + p.extensionTarget
30+
}
31+
2632
div(cls := "scaladoc-searchbar-row monospace", "result" := "")(
2733
a(href := location)(
2834
p.fullName,
35+
span(cls := "italic")(extensionTargetMessage),
2936
span(cls := "pull-right scaladoc-searchbar-location")(p.description)
3037
).tap { _.onclick = (event: Event) =>
3138
if (document.body.contains(rootDiv)) {

scaladoc-js/main/test/dotty/tools/scaladoc/MatchersTest.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class MatchersTest:
3434
s"$kind $name",
3535
"",
3636
"",
37+
"",
3738
false,
3839
s"$name",
3940
kind,

scaladoc/src/dotty/tools/scaladoc/renderers/Resources.scala

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -132,36 +132,44 @@ trait Resources(using ctx: DocContext) extends Locations, Writer:
132132
case Keyword(s) => s
133133
}.mkString
134134

135-
def mkEntry(dri: DRI, name: String, text: String, descr: String, kind: String) = jsonObject(
135+
def mkEntry(dri: DRI, name: String, text: String, extensionTarget: String, descr: String, kind: String) = jsonObject(
136136
"l" -> jsonString(relativeInternalOrAbsoluteExternalPath(dri)),
137137
"e" -> (if dri.externalLink.isDefined then rawJSON("true") else rawJSON("false")),
138+
"i" -> jsonString(extensionTarget),
138139
"n" -> jsonString(name),
139140
"t" -> jsonString(text),
140141
"d" -> jsonString(descr),
141142
"k" -> jsonString(kind)
142143
)
143144

144-
def processPage(page: Page): Seq[JSON] =
145-
val res = page.content match
145+
def extensionTarget(member: Member): String =
146+
member.kind match
147+
case Kind.Extension(on, _) => flattenToText(on.signature)
148+
case _ => ""
149+
150+
def processPage(page: Page, pageFQName: List[String]): Seq[(JSON, Seq[String])] =
151+
val (res, pageName) = page.content match
146152
case m: Member if m.kind != Kind.RootPackage =>
147-
val descr = m.dri.asFileLocation
148-
def processMember(member: Member): Seq[JSON] =
153+
def processMember(member: Member, fqName: List[String]): Seq[(JSON, Seq[String])] =
149154
val signatureBuilder = ScalaSignatureProvider.rawSignature(member, InlineSignatureBuilder())().asInstanceOf[InlineSignatureBuilder]
150155
val sig = Signature(Plain(member.name)) ++ signatureBuilder.names.reverse
151-
val entry = mkEntry(member.dri, member.name, flattenToText(sig), descr, member.kind.name)
156+
val descr = fqName.mkString(".")
157+
val entry = mkEntry(member.dri, member.name, flattenToText(sig), extensionTarget(member), descr, member.kind.name)
152158
val children = member
153159
.membersBy(m => m.kind != Kind.Package && !m.kind.isInstanceOf[Classlike])
154160
.filter(m => m.origin == Origin.RegularlyDefined && m.inheritedFrom.fold(true)(_.isSourceSuperclassHidden))
155-
Seq(entry) ++ children.flatMap(processMember)
161+
val updatedFqName = fqName :+ member.name
162+
Seq((entry, updatedFqName)) ++ children.flatMap(processMember(_, updatedFqName))
156163

157-
processMember(m)
164+
(processMember(m, pageFQName), m.name)
158165
case _ =>
159-
Seq(mkEntry(page.link.dri, page.link.name, page.link.name, "", "static"))
166+
(Seq((mkEntry(page.link.dri, page.link.name, page.link.name, "", "", "static"), pageFQName)), "")
160167

161-
res ++ page.children.flatMap(processPage)
168+
val updatedFqName = if !pageName.isEmpty then pageFQName :+ pageName else pageFQName
169+
res ++ page.children.flatMap(processPage(_, updatedFqName))
162170

163-
val entries = pages.flatMap(processPage)
164-
Resource.Text(searchDataPath, s"pages = ${jsonList(entries)};")
171+
val entries = pages.flatMap(processPage(_, Nil))
172+
Resource.Text(searchDataPath, s"pages = ${jsonList(entries.map(_._1))};")
165173

166174
def scastieConfiguration() =
167175
Resource.Text(scastieConfigurationPath, s"""scastieConfiguration = "${

0 commit comments

Comments
 (0)