Skip to content

Commit 640eb20

Browse files
committed
Scaladoc: in def lookup, at last stage prefer type to term
This results in similar queries to what we had previously and prepares for listing members in a different way.
1 parent f2e0a4c commit 640eb20

File tree

2 files changed

+54
-25
lines changed

2 files changed

+54
-25
lines changed

scaladoc/src/dotty/tools/scaladoc/tasty/comments/MemberLookup.scala

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ trait MemberLookup {
5656

5757
query match {
5858
case Query.StrictMemberId(id) =>
59-
localLookup(id, nearest).nextOption.map(_ -> id)
59+
downwardLookup(List(id), nearest).map(_ -> id)
6060
case Query.QualifiedId(Query.Qual.This, _, rest) =>
6161
downwardLookup(rest.asList, nearestCls).map(_ -> rest.join)
6262
case Query.QualifiedId(Query.Qual.Package, _, rest) =>
@@ -101,43 +101,37 @@ trait MemberLookup {
101101
sym.isCompleted && sym.info.exists
102102
}
103103

104-
private def localLookup(using Quotes)(query: String, owner: quotes.reflect.Symbol): Iterator[quotes.reflect.Symbol] = {
104+
private def localLookup(using Quotes)(
105+
sel: MemberLookup.Selector,
106+
owner: quotes.reflect.Symbol
107+
): Iterator[quotes.reflect.Symbol] = {
105108
import quotes.reflect._
106109

107110
def findMatch(syms: Iterator[Symbol]): Iterator[Symbol] = {
108-
// Scaladoc overloading support allows terminal * (and they're meaningless)
109-
val cleanQuery = query.stripSuffix("*")
110-
val (q, forceTerm, forceType) =
111-
if cleanQuery endsWith "$" then
112-
(cleanQuery.init, true, false)
113-
else if cleanQuery endsWith "!" then
114-
(cleanQuery.init, false, true)
115-
else
116-
(cleanQuery, false, false)
117-
118111
def matches(s: Symbol): Boolean =
119-
s.name == q && (
120-
if forceTerm then s.isTerm
121-
else if forceType then s.isType
122-
else true
123-
)
112+
s.name == sel.ident && sel.kind.match {
113+
case MemberLookup.SelectorKind.ForceTerm => s.isTerm
114+
case MemberLookup.SelectorKind.ForceType => s.isType
115+
case MemberLookup.SelectorKind.NoForce => true
116+
}
124117

125118
def hackResolveModule(s: Symbol): Symbol =
126119
if s.flags.is(Flags.Module) then s.moduleClass else s
127120

128121
// val syms0 = syms.toList
129122
// val matched0 = syms0.filter(matches)
130123
// if matched0.isEmpty then
131-
// println(s"Failed to look up $q in $owner; all members: {{{")
124+
// println(s"Failed to look up ${sel.ident} in $owner; all members: {{{")
132125
// syms0.foreach { s => println(s"\t$s") }
133126
// println("}}}")
134127
// val matched = matched0.iterator
135128

136129
// def showMatched() = matched0.foreach { s =>
137130
// println(s"\t $s")
138131
// }
139-
// println(s"localLookup in class ${owner} for `$q`{forceTerm=$forceTerm}:")
132+
// println(s"localLookup in class ${owner} for `${sel.ident}`{kind=${sel.kind}}:{{{")
140133
// showMatched()
134+
// println("}}}")
141135

142136
val matched = syms.filter(matches)
143137
matched.map(hackResolveModule)
@@ -164,18 +158,32 @@ trait MemberLookup {
164158
case None => Iterator.empty
165159
}
166160
case _ =>
167-
findMatch(hackMembersOf(owner))
161+
val owner0 =
162+
if owner.flags.is(Flags.Module) then owner.moduleClass else owner
163+
findMatch(hackMembersOf(owner0))
168164
}
169165
}
170166

171167
private def downwardLookup(using Quotes)(query: List[String], owner: quotes.reflect.Symbol): Option[quotes.reflect.Symbol] = {
172168
import quotes.reflect._
173169
query match {
174170
case Nil => None
175-
case q :: Nil => localLookup(q, owner).nextOption
171+
case q :: Nil =>
172+
val sel = MemberLookup.Selector.fromString(q)
173+
sel.kind match {
174+
case MemberLookup.SelectorKind.NoForce =>
175+
val lookedUp = localLookup(sel, owner).toSeq
176+
// note: those flag lookups are necessary b/c for objects we return their classes
177+
lookedUp.find(s => s.isType && !s.flags.is(Flags.Module)).orElse(
178+
lookedUp.find(s => s.isTerm || s.flags.is(Flags.Module))
179+
)
180+
case _ =>
181+
localLookup(sel, owner).nextOption
182+
183+
}
176184
case q :: qs =>
177-
val lookedUp =
178-
localLookup(q, owner).toSeq
185+
val sel = MemberLookup.Selector.fromString(q)
186+
val lookedUp = localLookup(sel, owner).toSeq
179187

180188
if lookedUp.isEmpty then None else {
181189
// tm/tp - term/type symbols which we looked up and which allow further lookup
@@ -198,4 +206,25 @@ trait MemberLookup {
198206
}
199207
}
200208

201-
object MemberLookup extends MemberLookup
209+
object MemberLookup extends MemberLookup {
210+
enum SelectorKind {
211+
case ForceTerm
212+
case ForceType
213+
case NoForce
214+
}
215+
216+
case class Selector(ident: String, kind: SelectorKind)
217+
object Selector {
218+
def fromString(str: String) = {
219+
// Scaladoc overloading support allows terminal * (and they're meaningless)
220+
val cleanStr = str.stripSuffix("*")
221+
222+
if cleanStr endsWith "$" then
223+
Selector(cleanStr.init, SelectorKind.ForceTerm)
224+
else if cleanStr endsWith "!" then
225+
Selector(cleanStr.init, SelectorKind.ForceType)
226+
else
227+
Selector(cleanStr, SelectorKind.NoForce)
228+
}
229+
}
230+
}

scaladoc/test/dotty/tools/scaladoc/tasty/comments/MemberLookupTests.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class LookupTestCases[Q <: Quotes](val q: Quotes) {
6565
cls("tests.A") -> "AA!" -> cls("tests.A").tpe("AA"),
6666
cls("tests.A") -> "AA$" -> cls("tests.A").fld("AA"),
6767

68-
cls("tests.C") -> "CC" -> cls("tests.C").fld("CC"),
68+
cls("tests.C") -> "CC" -> cls("tests.C").tpe("CC"),
6969
cls("tests.C") -> "CC$" -> cls("tests.C").fld("CC"),
7070
cls("tests.C") -> "CC!" -> cls("tests.C").tpe("CC"),
7171

0 commit comments

Comments
 (0)