@@ -166,38 +166,59 @@ object Interactive {
166
166
private def computeCompletions (pos : SourcePosition , path : List [Tree ])(implicit ctx : Context ): (Int , List [Symbol ]) = {
167
167
val completions = Scopes .newScope.openForMutations
168
168
169
+ type Mode = Int
170
+ object Mode {
171
+ /** No symbol should be included */
172
+ val None : Mode = 0
173
+
174
+ /** Term symbols are allowed */
175
+ val Term : Mode = 1
176
+
177
+ /** Type symbols are allowed */
178
+ val Type : Mode = 2
179
+
180
+ /** Both term and type symbols are allowed */
181
+ val Import : Mode = Term | Type
182
+
183
+ /** Does `m0` include `m1`? */
184
+ def is (m0 : Mode , m1 : Mode ): Boolean = (m0 & m1) == m1
185
+ }
186
+
169
187
/**
170
188
* The information about the current completion.
171
189
*
172
- * @param position The position where the completion result should be inserted.
173
- * @param prefix A prefix that potential completion results must match.
174
- * @param termOnly If set, only terms should be considered as completion results.
175
- * @param typeOnly If set, only types should be considered as completion results.
176
- * @param inImport If set, indicates that this is the completion of an import node.
190
+ * @param offset The offset where the completion result should be inserted.
191
+ * @param prefix A prefix that potential completion results must match.
192
+ * @param mode The completion mode.
177
193
*/
178
- case class CompletionInfo (position : Int , prefix : String , termOnly : Boolean , typeOnly : Boolean , inImport : Boolean )
194
+ case class CompletionInfo (offset : Int , prefix : String , mode : Mode )
179
195
180
196
/**
181
197
* Extract basic info about completion location and the kind of symbols to include.
182
198
*
183
199
* @param path The path to the position where completion happens
184
200
* @param inImport If set, indicates that this is the completion of an import node. When
185
201
* completing imports, both types and terms are always included.
186
- * @return The completion info
202
+ * @return The information about completion (offset, kinds of symbol, etc.)
187
203
*/
188
204
def completionInfo (path : List [Tree ], inImport : Boolean ): CompletionInfo = path match {
189
205
case (ref : RefTree ) :: _ =>
190
206
if (ref.name == nme.ERROR )
191
- CompletionInfo (ref.pos.point, " " , false , false , inImport)
192
- else
207
+ CompletionInfo (ref.pos.point, " " , Mode .None )
208
+ else {
209
+ val mode =
210
+ if (inImport) Mode .Import
211
+ else if (ref.name.isTermName) Mode .Term
212
+ else Mode .Type
213
+
193
214
CompletionInfo (
194
215
ref.pos.point,
195
216
ref.name.toString.take(pos.pos.point - ref.pos.point),
196
- ! inImport && ref.name.isTermName, // Types and terms are always accepted in imports
197
- ! inImport && ref.name.isTypeName,
198
- inImport)
217
+ mode)
218
+ }
219
+
199
220
case _ =>
200
- CompletionInfo (0 , " " , false , false , false )
221
+ CompletionInfo (0 , " " , Mode . None )
201
222
}
202
223
203
224
val info = path match {
@@ -208,7 +229,7 @@ object Interactive {
208
229
209
230
case (imp : Import ) :: _ =>
210
231
imp.selectors.find(_.pos.contains(pos.pos)) match {
211
- case None => CompletionInfo (imp.expr.pos.point, " " , false , false , true )
232
+ case None => CompletionInfo (imp.expr.pos.point, " " , Mode . Import )
212
233
case Some (sel) => completionInfo(sel.asInstanceOf [tpd.Tree ] :: Nil , /* inImport = */ true )
213
234
}
214
235
@@ -228,18 +249,20 @@ object Interactive {
228
249
* as completion results. However, if a user explicitly writes all '$' characters in an
229
250
* identifier, we should complete the rest.
230
251
*/
231
- def include (sym : Symbol ) =
252
+ def include (sym : Symbol ) = {
232
253
sym.name.startsWith(info.prefix) &&
233
254
! sym.name.toString.drop(info.prefix.length).contains('$' ) &&
234
255
! sym.isPrimaryConstructor &&
235
256
(! sym.is(Package ) || ! sym.moduleClass.exists) &&
236
257
! sym.is(allOf(Mutable , Accessor )) &&
237
- (! info.termOnly || sym.isTerm) &&
238
- (! info.typeOnly || sym.isType)
258
+ (
259
+ (Mode .is(info.mode, Mode .Term ) && sym.isTerm)
260
+ || (Mode .is(info.mode, Mode .Type ) && sym.isType)
261
+ )
262
+ }
239
263
240
264
def enter (sym : Symbol ) =
241
265
if (include(sym)) completions.enter(sym)
242
-
243
266
def add (sym : Symbol ) =
244
267
if (sym.exists && ! completions.lookup(sym.name).exists) enter(sym)
245
268
@@ -313,7 +336,7 @@ object Interactive {
313
336
314
337
def getMemberCompletions (qual : Tree ): Unit = {
315
338
addAccessibleMembers(qual.tpe)
316
- if (! info.inImport ) {
339
+ if (! Mode .is( info.mode, Mode . Import ) ) {
317
340
// Implicit conversions do not kick in when importing
318
341
implicitConversionTargets(qual)(ctx.fresh.setExploreTyperState())
319
342
.foreach(addAccessibleMembers(_))
@@ -328,7 +351,7 @@ object Interactive {
328
351
}
329
352
330
353
val completionList =
331
- if (! info.inImport ) completions.toList
354
+ if (! Mode .is( info.mode, Mode . Import ) ) completions.toList
332
355
else {
333
356
// In imports, show only the type symbols when there are multiple options with the same name
334
357
completions.toList.groupBy(_.name.stripModuleClassSuffix.toSimpleName).mapValues {
@@ -338,7 +361,7 @@ object Interactive {
338
361
}
339
362
340
363
interactiv.println(i " completion with pos = $pos, prefix = $info.prefix, termOnly = $info.termOnly, typeOnly = $info.typeOnly = $completionList%, % " )
341
- (info.position , completionList)
364
+ (info.offset , completionList)
342
365
}
343
366
344
367
/** Possible completions of members of `prefix` which are accessible when called inside `boundary` */
0 commit comments