@@ -12,6 +12,7 @@ import util.Positions._, util.SourcePosition
12
12
import core .Denotations .SingleDenotation
13
13
import NameKinds .SimpleNameKind
14
14
import config .Printers .interactiv
15
+ import StdNames .nme
15
16
16
17
/** High-level API to get information out of typed trees, designed to be used by IDEs.
17
18
*
@@ -137,28 +138,49 @@ object Interactive {
137
138
private def computeCompletions (pos : SourcePosition , path : List [Tree ])(implicit ctx : Context ): (Int , List [Symbol ]) = {
138
139
val completions = Scopes .newScope.openForMutations
139
140
140
- val (completionPos, prefix) = path match {
141
+ val (completionPos, prefix, termOnly, typeOnly ) = path match {
141
142
case (ref : RefTree ) :: _ =>
142
- (ref.pos.point, ref.name.toString.take(ref.pos.end - ref.pos.point - 1 ))
143
- case (id @ Ident (name)) :: _ =>
144
- if .pos
145
- getScopeCompletions(ctx)
146
- id.pos.point
143
+ if (ref.name == nme.ERROR )
144
+ (ref.pos.point, " " , false , false )
145
+ else
146
+ (ref.pos.point,
147
+ ref.name.toString.take(pos.pos.point - ref.pos.point),
148
+ ref.name.isTermName,
149
+ ref.name.isTypeName)
147
150
case _ =>
148
- getScopeCompletions(ctx)
149
- 0
151
+ (0 , " " , false , false )
152
+ }
153
+
154
+ /** Include in completion sets only symbols that
155
+ * - start with given name prefix
156
+ * - do not contain '$' except in prefix where it is explicitly written by user
157
+ * - have same term/type kind as name prefix given so far
158
+ */
159
+ def include (sym : Symbol ) =
160
+ sym.name.startsWith(prefix) &&
161
+ ! sym.name.toString.drop(prefix.length).contains('$' ) &&
162
+ (! termOnly || sym.isTerm) &&
163
+ (! typeOnly || sym.isType)
164
+
165
+ def enter (sym : Symbol ) =
166
+ if (include(sym)) completions.enter(sym)
150
167
151
168
def add (sym : Symbol ) =
152
- if (sym.exists && ! completions.lookup(sym.name).exists)
153
- completions.enter(sym)
169
+ if (sym.exists && ! completions.lookup(sym.name).exists) enter(sym)
154
170
155
171
def addMember (site : Type , name : Name ) =
156
172
if (! completions.lookup(name).exists)
157
- for (alt <- site.member(name).alternatives)
158
- completions.enter(alt.symbol)
173
+ for (alt <- site.member(name).alternatives) enter(alt.symbol)
159
174
160
- def allMembers (site : Type , superAccess : Boolean = true ) =
161
- site.membersBasedOnFlags(EmptyFlags , EmptyFlags ).map(_.accessibleFrom(site, superAccess))
175
+ def accessibleMembers (site : Type , superAccess : Boolean = true ): Seq [Symbol ] = site match {
176
+ case site : NamedType if site.symbol.is(Package ) =>
177
+ site.decls.toList.filter(include) // Don't look inside package members -- it's too expensive.
178
+ case _ =>
179
+ site.allMembers.collect {
180
+ case mbr if include(mbr.symbol) => mbr.accessibleFrom(site, superAccess).symbol
181
+ case _ => NoSymbol
182
+ }.filter(_.exists)
183
+ }
162
184
163
185
def getImportCompletions (ictx : Context ): Unit = {
164
186
implicit val ctx = ictx
@@ -171,7 +193,7 @@ object Interactive {
171
193
for (renamed <- imp.reverseMapping.keys) addImport(renamed)
172
194
for (imported <- imp.originals if ! imp.excluded.contains(imported)) addImport(imported)
173
195
if (imp.isWildcardImport)
174
- for (mbr <- allMembers (imp.site) if ! imp.excluded.contains(mbr.name.toTermName))
196
+ for (mbr <- accessibleMembers (imp.site) if ! imp.excluded.contains(mbr.name.toTermName))
175
197
addMember(imp.site, mbr.name)
176
198
}
177
199
}
@@ -180,15 +202,11 @@ object Interactive {
180
202
implicit val ctx = ictx
181
203
182
204
if (ctx.owner.isClass) {
183
- for (sym <- ctx.owner.info.decls) // decls in same class first
184
- addMember(ctx.owner.thisType, sym.name)
185
- if (! ctx.owner.is(Package )) {
186
- for (mbr <- allMembers(ctx.owner.thisType)) // all other members second
187
- addMember(ctx.owner.thisType, mbr.name)
188
- ctx.owner.asClass.classInfo.selfInfo match {
189
- case selfSym : Symbol => add(selfSym)
190
- case _ =>
191
- }
205
+ for (mbr <- accessibleMembers(ctx.owner.thisType))
206
+ addMember(ctx.owner.thisType, mbr.name)
207
+ ctx.owner.asClass.classInfo.selfInfo match {
208
+ case selfSym : Symbol => add(selfSym)
209
+ case _ =>
192
210
}
193
211
}
194
212
else if (ctx.scope != null ) ctx.scope.foreach(add)
@@ -204,22 +222,14 @@ object Interactive {
204
222
}
205
223
206
224
def getMemberCompletions (site : Type ): Unit = {
207
- for (mbr <- allMembers (site)) addMember(site, mbr.name)
225
+ for (mbr <- accessibleMembers (site)) addMember(site, mbr.name)
208
226
}
209
227
210
- val completionPos = path match {
211
- case (sel @ Select (qual, name)) :: _ =>
212
- getMemberCompletions(qual.tpe)
213
- // When completing "`a.foo`, return the members of `a`
214
- sel.pos.point
215
- case (id : Ident ) :: _ =>
216
- getScopeCompletions(ctx)
217
- id.pos.point
218
- case _ =>
219
- getScopeCompletions(ctx)
220
- 0
228
+ path match {
229
+ case (sel @ Select (qual, name)) :: _ => getMemberCompletions(qual.tpe)
230
+ case _ => getScopeCompletions(ctx)
221
231
}
222
- interactiv.println(i " completion = ${completions.toList}%, % " )
232
+ interactiv.println(i " completion with pos = $pos , prefix = $prefix , termOnly = $termOnly , typeOnly = $typeOnly = ${completions.toList}%, % " )
223
233
(completionPos, completions.toList)
224
234
}
225
235
0 commit comments