Skip to content

Commit 21aa3b8

Browse files
committed
improvement: Look up isAccessible lazily
1 parent 701fa8a commit 21aa3b8

18 files changed

+140
-206
lines changed

Diff for: compiler/src/dotty/tools/dotc/interactive/Completion.scala

+29-9
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ case class Completion(label: String, description: String, symbols: List[Symbol])
4848

4949
object Completion:
5050

51+
def scopeContext(pos: SourcePosition)(using Context): CompletionResult =
52+
val tpdPath = Interactive.pathTo(ctx.compilationUnit.tpdTree, pos.span)
53+
val completionContext = Interactive.contextOfPath(tpdPath).withPhase(Phases.typerPhase)
54+
inContext(completionContext):
55+
val untpdPath = Interactive.resolveTypedOrUntypedPath(tpdPath, pos)
56+
val mode = completionMode(untpdPath, pos)
57+
val rawPrefix = completionPrefix(untpdPath, pos)
58+
val completer = new Completer(mode, pos, untpdPath, _ => true)
59+
completer.scopeCompletions
60+
5161
/** Get possible completions from tree at `pos`
5262
*
5363
* @return offset and list of symbols for possible completions
@@ -220,11 +230,11 @@ object Completion:
220230
val result = adjustedPath match
221231
// Ignore synthetic select from `This` because in code it was `Ident`
222232
// See example in dotty.tools.languageserver.CompletionTest.syntheticThis
223-
case tpd.Select(qual @ tpd.This(_), _) :: _ if qual.span.isSynthetic => completer.scopeCompletions
233+
case tpd.Select(qual @ tpd.This(_), _) :: _ if qual.span.isSynthetic => completer.scopeCompletions.names
224234
case tpd.Select(qual, _) :: _ if qual.typeOpt.hasSimpleKind => completer.selectionCompletions(qual)
225235
case tpd.Select(qual, _) :: _ => Map.empty
226236
case (tree: tpd.ImportOrExport) :: _ => completer.directMemberCompletions(tree.expr)
227-
case _ => completer.scopeCompletions
237+
case _ => completer.scopeCompletions.names
228238

229239
interactiv.println(i"""completion info with pos = $pos,
230240
| term = ${completer.mode.is(Mode.Term)},
@@ -358,7 +368,7 @@ object Completion:
358368
* (even if the import follows it syntactically)
359369
* - a more deeply nested import shadowing a member or a local definition causes an ambiguity
360370
*/
361-
def scopeCompletions(using context: Context): CompletionMap =
371+
def scopeCompletions(using context: Context): CompletionResult =
362372

363373
/** Temporary data structure representing denotations with the same name introduced in a given scope
364374
* as a member of a type, by a local definition or by an import clause
@@ -369,14 +379,19 @@ object Completion:
369379
ScopedDenotations(denots.filter(includeFn), ctx)
370380

371381
val mappings = collection.mutable.Map.empty[Name, List[ScopedDenotations]].withDefaultValue(List.empty)
382+
val renames = collection.mutable.Map.empty[Name, Name]
372383
def addMapping(name: Name, denots: ScopedDenotations) =
373384
mappings(name) = mappings(name) :+ denots
374385

375386
ctx.outersIterator.foreach { case ctx @ given Context =>
376387
if ctx.isImportContext then
377-
importedCompletions.foreach { (name, denots) =>
388+
val imported = importedCompletions
389+
imported.names.foreach { (name, denots) =>
378390
addMapping(name, ScopedDenotations(denots, ctx, include(_, name)))
379391
}
392+
imported.renames.foreach { (name, newName) =>
393+
renames(name) = newName
394+
}
380395
else if ctx.owner.isClass then
381396
accessibleMembers(ctx.owner.thisType)
382397
.groupByName.foreach { (name, denots) =>
@@ -430,7 +445,7 @@ object Completion:
430445
}
431446
}
432447

433-
resultMappings
448+
CompletionResult(resultMappings, renames.toMap)
434449
end scopeCompletions
435450

436451
/** Widen only those types which are applied or are exactly nothing
@@ -472,13 +487,16 @@ object Completion:
472487
/** Completions introduced by imports directly in this context.
473488
* Completions from outer contexts are not included.
474489
*/
475-
private def importedCompletions(using Context): CompletionMap =
490+
private def importedCompletions(using Context): CompletionResult =
476491
val imp = ctx.importInfo
492+
val renames = collection.mutable.Map.empty[Name, Name]
477493

478494
if imp == null then
479-
Map.empty
495+
CompletionResult(Map.empty, Map.empty)
480496
else
481497
def fromImport(name: Name, nameInScope: Name): Seq[(Name, SingleDenotation)] =
498+
if name != nameInScope then
499+
renames(name) = nameInScope
482500
imp.site.member(name).alternatives
483501
.collect { case denot if include(denot, nameInScope) => nameInScope -> denot }
484502

@@ -506,7 +524,8 @@ object Completion:
506524
fromImport(original.toTypeName, nameInScope.toTypeName)
507525
}.toSeq.groupByName
508526

509-
givenImports ++ wildcardMembers ++ explicitMembers
527+
val results = givenImports ++ wildcardMembers ++ explicitMembers
528+
CompletionResult(results, renames.toMap)
510529
end importedCompletions
511530

512531
/** Completions from implicit conversions including old style extensions using implicit classes */
@@ -584,7 +603,7 @@ object Completion:
584603

585604
// 1. The extension method is visible under a simple name, by being defined or inherited or imported in a scope enclosing the reference.
586605
val termCompleter = new Completer(Mode.Term, pos, untpdPath, matches)
587-
val extMethodsInScope = termCompleter.scopeCompletions.toList.flatMap:
606+
val extMethodsInScope = termCompleter.scopeCompletions.names.toList.flatMap:
588607
case (name, denots) => denots.collect:
589608
case d: SymDenotation if d.isTerm && d.termRef.symbol.is(Extension) => (d.termRef, name.asTermName)
590609

@@ -686,6 +705,7 @@ object Completion:
686705

687706
private type CompletionMap = Map[Name, Seq[SingleDenotation]]
688707

708+
case class CompletionResult(names: Map[Name, Seq[SingleDenotation]], renames: Map[Name, Name])
689709
/**
690710
* The completion mode: defines what kinds of symbols should be included in the completion
691711
* results.

Diff for: presentation-compiler/src/main/dotty/tools/pc/AutoImports.scala

+21-15
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ import dotty.tools.dotc.core.Contexts.*
1111
import dotty.tools.dotc.core.Flags.*
1212
import dotty.tools.dotc.core.Names.*
1313
import dotty.tools.dotc.core.Symbols.*
14+
import dotty.tools.dotc.core.StdNames.nme
1415
import dotty.tools.dotc.util.SourcePosition
1516
import dotty.tools.dotc.util.Spans
1617
import dotty.tools.pc.utils.InteractiveEnrichments.*
1718

1819
import org.eclipse.lsp4j as l
20+
import dotty.tools.dotc.config.PathResolver.ppcp
1921

2022
object AutoImports:
2123

@@ -40,7 +42,7 @@ object AutoImports:
4042
case class Select(qual: SymbolIdent, name: String) extends SymbolIdent:
4143
def value: String = s"${qual.value}.$name"
4244

43-
def direct(name: String): SymbolIdent = Direct(name)
45+
def direct(name: Name)(using Context): SymbolIdent = Direct(name.decoded)
4446

4547
def fullIdent(symbol: Symbol)(using Context): SymbolIdent =
4648
val symbols = symbol.ownersIterator.toList
@@ -49,11 +51,11 @@ object AutoImports:
4951

5052
symbols match
5153
case head :: tail =>
52-
tail.foldLeft(direct(head.nameBackticked))((acc, next) =>
54+
tail.foldLeft(direct(head.name))((acc, next) =>
5355
Select(acc, next.nameBackticked)
5456
)
5557
case Nil =>
56-
SymbolIdent.direct("<no symbol>")
58+
SymbolIdent.direct(nme.NoSymbol)
5759

5860
end SymbolIdent
5961

@@ -62,20 +64,20 @@ object AutoImports:
6264

6365
object ImportSel:
6466
final case class Direct(sym: Symbol) extends ImportSel
65-
final case class Rename(sym: Symbol, rename: String) extends ImportSel
67+
final case class Rename(sym: Symbol, rename: Name) extends ImportSel
6668

6769
case class SymbolImport(
6870
sym: Symbol,
6971
ident: SymbolIdent,
7072
importSel: Option[ImportSel]
7173
):
7274

73-
def name: String = ident.value
75+
def name(using Context): String = ident.value
7476

7577
object SymbolImport:
7678

7779
def simple(sym: Symbol)(using Context): SymbolImport =
78-
SymbolImport(sym, SymbolIdent.direct(sym.nameBackticked), None)
80+
SymbolImport(sym, SymbolIdent.direct(sym.name), None)
7981

8082
/**
8183
* Returns AutoImportsGenerator
@@ -97,8 +99,8 @@ object AutoImports:
9799

98100
import indexedContext.ctx
99101

100-
val importPos = autoImportPosition(pos, text, tree, comments)
101-
val renameConfig: Map[Symbol, String] = AutoImport.renameConfigMap(config)
102+
val importPos = autoImportPosition(pos, text, tree, comments) // TODO: add rename config
103+
val renameConfig: Map[Symbol, Name] = Map.empty //AutoImport.renameConfigMap(config).collect { case (k, v) => k -> indexedContext.find(v) }
102104

103105
val renames =
104106
(sym: Symbol) =>
@@ -143,7 +145,7 @@ object AutoImports:
143145
val pos: SourcePosition,
144146
importPosition: AutoImportPosition,
145147
indexedContext: IndexedContext,
146-
renames: Symbol => Option[String]
148+
renames: Symbol => Option[Name]
147149
):
148150

149151
import indexedContext.ctx
@@ -190,7 +192,7 @@ object AutoImports:
190192
)
191193
else
192194
(
193-
SymbolIdent.direct(symbol.nameBackticked),
195+
SymbolIdent.direct(symbol.name),
194196
Some(ImportSel.Direct(symbol)),
195197
)
196198
end val
@@ -205,7 +207,7 @@ object AutoImports:
205207
renames(owner) match
206208
case Some(rename) =>
207209
val importSel =
208-
if rename != owner.showName then
210+
if rename != owner.name then
209211
Some(ImportSel.Rename(owner, rename)).filter(_ =>
210212
!indexedContext.hasRename(owner, rename)
211213
)
@@ -223,14 +225,18 @@ object AutoImports:
223225
importSel
224226
)
225227
case None =>
228+
val reverse = symbol.ownersIterator.toList.reverse
229+
val fullName = reverse.drop(1).foldLeft(SymbolIdent.direct(reverse.head.name)){
230+
case (acc, sym) => SymbolIdent.Select(acc, sym.nameBackticked(false))
231+
} // TODO fullName should work
226232
SymbolImport(
227233
symbol,
228-
SymbolIdent.direct(symbol.fullNameBackticked),
234+
SymbolIdent.Select(SymbolIdent.direct(owner.name), symbol.nameBackticked(false)),
229235
None
230236
)
231237
end match
232238
case IndexedContext.Result.InScope =>
233-
val direct = renames(symbol).getOrElse(symbol.nameBackticked)
239+
val direct = renames(symbol).getOrElse(symbol.name)
234240
SymbolImport(symbol, SymbolIdent.direct(direct), None)
235241
end match
236242
end inferSymbolImport
@@ -267,13 +273,13 @@ object AutoImports:
267273
end renderImports
268274

269275
private def importName(sym: Symbol): String =
270-
if indexedContext.importContext.toplevelClashes(sym) then
276+
if indexedContext.toplevelClashes(sym) then
271277
s"_root_.${sym.fullNameBackticked(false)}"
272278
else
273279
sym.ownersIterator.zipWithIndex.foldLeft((List.empty[String], false)) { case ((acc, isDone), (sym, idx)) =>
274280
if(isDone || sym.isEmptyPackage || sym.isRoot) (acc, true)
275281
else indexedContext.rename(sym) match
276-
case Some(renamed) => (renamed :: acc, true)
282+
case Some(renamed) => (renamed.decoded :: acc, true)
277283
case None if !sym.isPackageObject => (sym.nameBackticked(false) :: acc, false)
278284
case None => (acc, false)
279285
}._1.mkString(".")

Diff for: presentation-compiler/src/main/dotty/tools/pc/AutoImportsProvider.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ final class AutoImportsProvider(
4444
val path =
4545
Interactive.pathTo(newctx.compilationUnit.tpdTree, pos.span)(using newctx)
4646

47-
val indexedContext = IndexedContext(
48-
Interactive.contextOfPath(path)(using newctx)
47+
val indexedContext = IndexedContext(pos)(
48+
using Interactive.contextOfPath(path)(using newctx)
4949
)
5050
import indexedContext.ctx
5151

@@ -96,7 +96,7 @@ final class AutoImportsProvider(
9696
text,
9797
tree,
9898
unit.comments,
99-
indexedContext.importContext,
99+
indexedContext,
100100
config
101101
)
102102
(sym: Symbol) => generator.forSymbol(sym)

Diff for: presentation-compiler/src/main/dotty/tools/pc/ExtractMethodProvider.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ final class ExtractMethodProvider(
5151
given locatedCtx: Context =
5252
val newctx = driver.currentCtx.fresh.setCompilationUnit(unit)
5353
Interactive.contextOfPath(path)(using newctx)
54-
val indexedCtx = IndexedContext(locatedCtx)
54+
val indexedCtx = IndexedContext(pos)(using locatedCtx)
5555
val printer =
5656
ShortenedTypePrinter(search, IncludeDefaultParam.Never)(using indexedCtx)
5757
def prettyPrint(tpe: Type) =

Diff for: presentation-compiler/src/main/dotty/tools/pc/HoverProvider.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ object HoverProvider:
4949
val path = unit
5050
.map(unit => Interactive.pathTo(unit.tpdTree, pos.span))
5151
.getOrElse(Interactive.pathTo(driver.openedTrees(uri), pos))
52-
val indexedContext = IndexedContext(ctx)
52+
val indexedContext = IndexedContext(pos)(using ctx)
5353

5454
def typeFromPath(path: List[Tree]) =
5555
if path.isEmpty then NoType else path.head.typeOpt
@@ -96,7 +96,7 @@ object HoverProvider:
9696

9797
val printerCtx = Interactive.contextOfPath(path)
9898
val printer = ShortenedTypePrinter(search, IncludeDefaultParam.Include)(
99-
using IndexedContext(printerCtx)
99+
using IndexedContext(pos)(using printerCtx)
100100
)
101101
MetalsInteractive.enclosingSymbolsWithExpressionType(
102102
enclosing,
@@ -134,7 +134,7 @@ object HoverProvider:
134134
.map(_.docstring())
135135
.mkString("\n")
136136

137-
val expresionTypeOpt =
137+
val expresionTypeOpt =
138138
if symbol.name == StdNames.nme.??? then
139139
InferExpectedType(search, driver, params).infer()
140140
else printer.expressionType(exprTpw)

0 commit comments

Comments
 (0)