Skip to content

Commit 7205f20

Browse files
committed
Add tests, don't cache when CURSOR is added
1 parent 748d439 commit 7205f20

27 files changed

+256
-94
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
@@ -406,7 +406,7 @@ object Parsers {
406406
false
407407
}
408408

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

411411
private var inFunReturnType = false
412412
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
@@ -1706,15 +1706,6 @@ class CompletionTest {
17061706
("getOrElse", Method, "[V1 >: String](key: Int, default: => V1): V1"),
17071707
))
17081708

1709-
@Test def testtest: Unit =
1710-
code"""|object M {
1711-
| def sel$m1
1712-
|}
1713-
|"""
1714-
.completion(m1, Set(
1715-
("getOrElse", Method, "[V1 >: String](key: Int, default: => V1): V1"),
1716-
))
1717-
17181709
@Test def noEnumCompletionInNewContext: Unit =
17191710
code"""|enum TestEnum:
17201711
| 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: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import dotty.tools.dotc.util.SourceFile
1010
import scala.compiletime.uninitialized
1111

1212
/**
13-
* MetalsDriver is a wrapper class that provides a compilation cache for InteractiveDriver.
14-
* MetalsDriver skips running compilation if
13+
* CachingDriver is a wrapper class that provides a compilation cache for InteractiveDriver.
14+
* CachingDriver skips running compilation if
1515
* - the target URI of `run` is the same as the previous target URI
1616
* - the content didn't change since the last compilation.
1717
*
@@ -27,9 +27,7 @@ import scala.compiletime.uninitialized
2727
* To avoid the complexity related to currentCtx,
2828
* we decided to cache only when the target URI only if the same as the previous run.
2929
*/
30-
class MetalsDriver(
31-
override val settings: List[String]
32-
) extends InteractiveDriver(settings):
30+
class CachingDriver(override val settings: List[String]) extends InteractiveDriver(settings):
3331

3432
@volatile private var lastCompiledURI: URI = uninitialized
3533

@@ -55,4 +53,4 @@ class MetalsDriver(
5553
lastCompiledURI = uri
5654
diags
5755

58-
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)