Skip to content

Commit 93b65e3

Browse files
committed
Add tests, don't cache when CURSOR is added
[Cherry-picked 7205f20][modified]
1 parent e107f7c commit 93b65e3

27 files changed

+259
-95
lines changed

compiler/src/dotty/tools/dotc/ast/NavigateAST.scala

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,24 +75,41 @@ object NavigateAST {
7575
def pathTo(span: Span, from: List[Positioned], skipZeroExtent: Boolean = false)(using Context): List[Positioned] = {
7676
def childPath(it: Iterator[Any], path: List[Positioned]): List[Positioned] = {
7777
var bestFit: List[Positioned] = path
78-
while (it.hasNext) {
79-
val path1 = it.next() match {
80-
// FIXME this has to be changed to deterministicaly find recoveed tree
81-
case untpd.Select(qual, name) if name == StdNames.nme.??? => path
78+
while (it.hasNext) do
79+
val path1 = it.next() match
80+
case sel: untpd.Select if isTreeFromRecovery(sel) => path
8281
case p: Positioned if !p.isInstanceOf[Closure[?]] => singlePath(p, path)
8382
case m: untpd.Modifiers => childPath(m.productIterator, path)
8483
case xs: List[?] => childPath(xs.iterator, path)
8584
case _ => path
86-
}
87-
if ((path1 ne path) &&
88-
((bestFit eq path) ||
89-
bestFit.head.span != path1.head.span &&
90-
envelops(bestFit.head.span, path1.head.span)))
85+
86+
if (path1 ne path) && ((bestFit eq path) || isBetterFit(bestFit, path1)) then
9187
bestFit = path1
92-
}
88+
9389
bestFit
9490
}
9591

92+
/**
93+
* When choosing better fit we compare spans. If candidate span has starting or ending point inside (exclusive)
94+
* current best fit it is selected as new best fit. This means that same spans are failing the first predicate.
95+
*
96+
* In case when spans start and end at same offsets we prefer non synthethic one.
97+
*/
98+
def isBetterFit(currentBest: List[Positioned], candidate: List[Positioned]): Boolean =
99+
if currentBest.isEmpty && candidate.nonEmpty then true
100+
else if currentBest.nonEmpty && candidate.nonEmpty then
101+
val bestSpan= currentBest.head.span
102+
val candidateSpan = candidate.head.span
103+
104+
bestSpan != candidateSpan &&
105+
envelops(bestSpan, candidateSpan) ||
106+
bestSpan.contains(candidateSpan) && bestSpan.isSynthetic && !candidateSpan.isSynthetic
107+
else false
108+
109+
110+
def isTreeFromRecovery(p: untpd.Select): Boolean =
111+
p.name == StdNames.nme.??? && p.qualifier.symbol.name == StdNames.nme.Predef && p.span.isSynthetic
112+
96113
def envelops(a: Span, b: Span): Boolean =
97114
!b.exists || a.exists && (
98115
(a.start < b.start && a.end >= b.end ) || (a.start <= b.start && a.end > b.end)

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ object Parsers {
398398
false
399399
}
400400

401-
def errorTermTree(start: Offset): Tree = atSpan(start, in.offset, in.offset) { unimplementedExpr }
401+
def errorTermTree(start: Offset): Tree = atSpan(Span(start, in.offset)) { unimplementedExpr }
402402

403403
private var inFunReturnType = false
404404
private def fromWithinReturnType[T](body: => T): T = {

language-server/test/dotty/tools/languageserver/CompletionTest.scala

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1705,15 +1705,6 @@ class CompletionTest {
17051705
("getOrElse", Method, "[V1 >: String](key: Int, default: => V1): V1"),
17061706
))
17071707

1708-
@Test def testtest: Unit =
1709-
code"""|object M {
1710-
| def sel$m1
1711-
|}
1712-
|"""
1713-
.completion(m1, Set(
1714-
("getOrElse", Method, "[V1 >: String](key: Int, default: => V1): V1"),
1715-
))
1716-
17171708
@Test def noEnumCompletionInNewContext: Unit =
17181709
code"""|enum TestEnum:
17191710
| case TestCase

language-server/test/dotty/tools/languageserver/HoverTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ class HoverTest {
227227
@Test def enums: Unit = {
228228
code"""|package example
229229
|enum TestEnum3:
230-
| case ${m1}A${m2} // no tooltip
230+
| case ${m1}A${m2} // no tooltip
231231
|
232232
|"""
233233
.hover(m1 to m2, hoverContent("example.TestEnum3"))

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import dotty.tools.dotc.core.Symbols.*
1313
import dotty.tools.dotc.interactive.Interactive
1414
import dotty.tools.dotc.interactive.InteractiveDriver
1515
import dotty.tools.dotc.util.SourceFile
16-
import dotty.tools.pc.AutoImports.*
1716
import dotty.tools.pc.completions.CompletionPos
1817
import dotty.tools.pc.utils.InteractiveEnrichments.*
1918

presentation-compiler/src/main/dotty/tools/pc/MetalsDriver.scala renamed to presentation-compiler/src/main/dotty/tools/pc/CachingDriver.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ import dotty.tools.dotc.interactive.InteractiveDriver
77
import dotty.tools.dotc.reporting.Diagnostic
88
import dotty.tools.dotc.util.SourceFile
99

10+
import scala.compiletime.uninitialized
11+
1012
/**
11-
* MetalsDriver is a wrapper class that provides a compilation cache for InteractiveDriver.
12-
* MetalsDriver skips running compilation if
13+
* CachingDriver is a wrapper class that provides a compilation cache for InteractiveDriver.
14+
* CachingDriver skips running compilation if
1315
* - the target URI of `run` is the same as the previous target URI
1416
* - the content didn't change since the last compilation.
1517
*
@@ -25,11 +27,9 @@ import dotty.tools.dotc.util.SourceFile
2527
* To avoid the complexity related to currentCtx,
2628
* we decided to cache only when the target URI only if the same as the previous run.
2729
*/
28-
class MetalsDriver(
29-
override val settings: List[String]
30-
) extends InteractiveDriver(settings):
30+
class CachingDriver(override val settings: List[String]) extends InteractiveDriver(settings):
3131

32-
@volatile private var lastCompiledURI: URI = _
32+
@volatile private var lastCompiledURI: URI = uninitialized
3333

3434
private def alreadyCompiled(uri: URI, content: Array[Char]): Boolean =
3535
compilationUnits.get(uri) match
@@ -53,4 +53,4 @@ class MetalsDriver(
5353
lastCompiledURI = uri
5454
diags
5555

56-
end MetalsDriver
56+
end CachingDriver

presentation-compiler/src/main/dotty/tools/pc/PcInlayHintsProvider.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import scala.meta.internal.pc.LabelPart.*
1414
import scala.meta.pc.InlayHintsParams
1515
import scala.meta.pc.SymbolSearch
1616

17-
import dotty.tools.dotc.ast.tpd
1817
import dotty.tools.dotc.ast.tpd.*
1918
import dotty.tools.dotc.core.Contexts.Context
2019
import dotty.tools.dotc.core.Flags

presentation-compiler/src/main/dotty/tools/pc/Scala3CompilerAccess.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ import scala.meta.internal.pc.CompilerAccess
88
import scala.meta.pc.PresentationCompilerConfig
99

1010
import dotty.tools.dotc.reporting.StoreReporter
11+
import dotty.tools.dotc.interactive.InteractiveDriver
1112

1213
class Scala3CompilerAccess(
1314
config: PresentationCompilerConfig,
1415
sh: Option[ScheduledExecutorService],
1516
newCompiler: () => Scala3CompilerWrapper
1617
)(using ec: ExecutionContextExecutor, rc: ReportContext)
17-
extends CompilerAccess[StoreReporter, MetalsDriver](
18+
extends CompilerAccess[StoreReporter, InteractiveDriver](
1819
config,
1920
sh,
2021
newCompiler,

presentation-compiler/src/main/dotty/tools/pc/Scala3CompilerWrapper.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import scala.meta.internal.pc.CompilerWrapper
44
import scala.meta.internal.pc.ReporterAccess
55

66
import dotty.tools.dotc.reporting.StoreReporter
7+
import dotty.tools.dotc.interactive.InteractiveDriver
78

8-
class Scala3CompilerWrapper(driver: MetalsDriver)
9-
extends CompilerWrapper[StoreReporter, MetalsDriver]:
9+
class Scala3CompilerWrapper(driver: InteractiveDriver)
10+
extends CompilerWrapper[StoreReporter, InteractiveDriver]:
1011

11-
override def compiler(): MetalsDriver = driver
12+
override def compiler(): InteractiveDriver = driver
1213

1314
override def resetReporter(): Unit =
1415
val ctx = driver.currentCtx

presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@ import dotty.tools.pc.completions.CompletionProvider
3333
import dotty.tools.pc.InferExpectedType
3434
import dotty.tools.pc.completions.OverrideCompletions
3535
import dotty.tools.pc.buildinfo.BuildInfo
36+
import dotty.tools.pc.SymbolInformationProvider
37+
import dotty.tools.dotc.interactive.InteractiveDriver
3638

3739
import org.eclipse.lsp4j.DocumentHighlight
3840
import org.eclipse.lsp4j.TextEdit
3941
import org.eclipse.lsp4j as l
40-
import dotty.tools.pc.SymbolInformationProvider
42+
4143

4244
case class ScalaPresentationCompiler(
4345
buildTargetIdentifier: String = "",
@@ -76,14 +78,20 @@ case class ScalaPresentationCompiler(
7678
override def withReportsLoggerLevel(level: String): PresentationCompiler =
7779
copy(reportsLevel = ReportLevel.fromString(level))
7880

79-
val compilerAccess: CompilerAccess[StoreReporter, MetalsDriver] =
81+
val compilerAccess: CompilerAccess[StoreReporter, InteractiveDriver] =
8082
Scala3CompilerAccess(
8183
config,
8284
sh,
83-
() => new Scala3CompilerWrapper(newDriver)
84-
)(using
85-
ec
86-
)
85+
() => new Scala3CompilerWrapper(CachingDriver(driverSettings))
86+
)(using ec)
87+
88+
val driverSettings =
89+
val implicitSuggestionTimeout = List("-Ximport-suggestion-timeout", "0")
90+
val defaultFlags = List("-color:never")
91+
val filteredOptions = removeDoubleOptions(options.filterNot(forbiddenOptions))
92+
93+
filteredOptions ::: defaultFlags ::: implicitSuggestionTimeout ::: "-classpath" :: classpath
94+
.mkString(File.pathSeparator) :: Nil
8795

8896
private def removeDoubleOptions(options: List[String]): List[String] =
8997
options match
@@ -92,19 +100,6 @@ case class ScalaPresentationCompiler(
92100
case head :: tail => head :: removeDoubleOptions(tail)
93101
case Nil => options
94102

95-
def newDriver: MetalsDriver =
96-
val implicitSuggestionTimeout = List("-Ximport-suggestion-timeout", "0")
97-
val defaultFlags = List("-color:never")
98-
val filteredOptions = removeDoubleOptions(
99-
options.filterNot(forbiddenOptions)
100-
)
101-
val settings =
102-
filteredOptions ::: defaultFlags ::: implicitSuggestionTimeout ::: "-classpath" :: classpath
103-
.mkString(
104-
File.pathSeparator
105-
) :: Nil
106-
new MetalsDriver(settings)
107-
108103
override def semanticTokens(
109104
params: VirtualFileParams
110105
): CompletableFuture[ju.List[Node]] =
@@ -146,6 +141,7 @@ case class ScalaPresentationCompiler(
146141
new CompletionProvider(
147142
search,
148143
driver,
144+
() => InteractiveDriver(driverSettings),
149145
params,
150146
config,
151147
buildTargetIdentifier,

0 commit comments

Comments
 (0)