@@ -56,7 +56,7 @@ trait MemberLookup {
56
56
57
57
query match {
58
58
case Query .StrictMemberId (id) =>
59
- localLookup(id , nearest).nextOption .map(_ -> id)
59
+ downwardLookup( List (id) , nearest).map(_ -> id)
60
60
case Query .QualifiedId (Query .Qual .This , _, rest) =>
61
61
downwardLookup(rest.asList, nearestCls).map(_ -> rest.join)
62
62
case Query .QualifiedId (Query .Qual .Package , _, rest) =>
@@ -101,43 +101,37 @@ trait MemberLookup {
101
101
sym.isCompleted && sym.info.exists
102
102
}
103
103
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 ] = {
105
108
import quotes .reflect ._
106
109
107
110
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
-
118
111
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
+ }
124
117
125
118
def hackResolveModule (s : Symbol ): Symbol =
126
119
if s.flags.is(Flags .Module ) then s.moduleClass else s
127
120
128
121
// val syms0 = syms.toList
129
122
// val matched0 = syms0.filter(matches)
130
123
// 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: {{{")
132
125
// syms0.foreach { s => println(s"\t$s") }
133
126
// println("}}}")
134
127
// val matched = matched0.iterator
135
128
136
129
// def showMatched() = matched0.foreach { s =>
137
130
// println(s"\t $s")
138
131
// }
139
- // println(s"localLookup in class ${owner} for `$q`{forceTerm=$forceTerm}: ")
132
+ // println(s"localLookup in class ${owner} for `${sel.ident}`{kind=${sel.kind}}:{{{ ")
140
133
// showMatched()
134
+ // println("}}}")
141
135
142
136
val matched = syms.filter(matches)
143
137
matched.map(hackResolveModule)
@@ -164,18 +158,32 @@ trait MemberLookup {
164
158
case None => Iterator .empty
165
159
}
166
160
case _ =>
167
- findMatch(hackMembersOf(owner))
161
+ val owner0 =
162
+ if owner.flags.is(Flags .Module ) then owner.moduleClass else owner
163
+ findMatch(hackMembersOf(owner0))
168
164
}
169
165
}
170
166
171
167
private def downwardLookup (using Quotes )(query : List [String ], owner : quotes.reflect.Symbol ): Option [quotes.reflect.Symbol ] = {
172
168
import quotes .reflect ._
173
169
query match {
174
170
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
+ }
176
184
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
179
187
180
188
if lookedUp.isEmpty then None else {
181
189
// tm/tp - term/type symbols which we looked up and which allow further lookup
@@ -198,4 +206,25 @@ trait MemberLookup {
198
206
}
199
207
}
200
208
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