@@ -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+ }
0 commit comments