@@ -12,6 +12,7 @@ import util.Positions._, util.SourcePosition
1212import core .Denotations .SingleDenotation
1313import NameKinds .SimpleNameKind
1414import config .Printers .interactiv
15+ import StdNames .nme
1516
1617/** High-level API to get information out of typed trees, designed to be used by IDEs.
1718 *
@@ -137,28 +138,49 @@ object Interactive {
137138 private def computeCompletions (pos : SourcePosition , path : List [Tree ])(implicit ctx : Context ): (Int , List [Symbol ]) = {
138139 val completions = Scopes .newScope.openForMutations
139140
140- val (completionPos, prefix) = path match {
141+ val (completionPos, prefix, termOnly, typeOnly ) = path match {
141142 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)
147150 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)
150167
151168 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)
154170
155171 def addMember (site : Type , name : Name ) =
156172 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)
159174
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+ }
162184
163185 def getImportCompletions (ictx : Context ): Unit = {
164186 implicit val ctx = ictx
@@ -171,7 +193,7 @@ object Interactive {
171193 for (renamed <- imp.reverseMapping.keys) addImport(renamed)
172194 for (imported <- imp.originals if ! imp.excluded.contains(imported)) addImport(imported)
173195 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))
175197 addMember(imp.site, mbr.name)
176198 }
177199 }
@@ -180,15 +202,11 @@ object Interactive {
180202 implicit val ctx = ictx
181203
182204 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 _ =>
192210 }
193211 }
194212 else if (ctx.scope != null ) ctx.scope.foreach(add)
@@ -204,22 +222,14 @@ object Interactive {
204222 }
205223
206224 def getMemberCompletions (site : Type ): Unit = {
207- for (mbr <- allMembers (site)) addMember(site, mbr.name)
225+ for (mbr <- accessibleMembers (site)) addMember(site, mbr.name)
208226 }
209227
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)
221231 }
222- interactiv.println(i " completion = ${completions.toList}%, % " )
232+ interactiv.println(i " completion with pos = $pos , prefix = $prefix , termOnly = $termOnly , typeOnly = $typeOnly = ${completions.toList}%, % " )
223233 (completionPos, completions.toList)
224234 }
225235
0 commit comments