@@ -16,6 +16,7 @@ import dotty.tools.dotc.core.Contexts.Context
16
16
import dotty .tools .dotc .core .Phases
17
17
import dotty .tools .dotc .core .StdNames .nme
18
18
import dotty .tools .dotc .core .Flags
19
+ import dotty .tools .dotc .core .Names .DerivedName
19
20
import dotty .tools .dotc .interactive .Interactive
20
21
import dotty .tools .dotc .interactive .Completion
21
22
import dotty .tools .dotc .interactive .InteractiveDriver
@@ -38,7 +39,8 @@ import org.eclipse.lsp4j.TextEdit
38
39
39
40
class CompletionProvider (
40
41
search : SymbolSearch ,
41
- driver : InteractiveDriver ,
42
+ cachingDriver : InteractiveDriver ,
43
+ freshDriver : () => InteractiveDriver ,
42
44
params : OffsetParams ,
43
45
config : PresentationCompilerConfig ,
44
46
buildTargetIdentifier : String ,
@@ -50,6 +52,16 @@ class CompletionProvider(
50
52
51
53
val (wasCursorApplied, code) = applyCompletionCursor(params)
52
54
val sourceFile = SourceFile .virtual(uri, code)
55
+
56
+ /** Creating a new fresh driver is way slower than reusing existing one,
57
+ * but runnig a compilation has side effects that modifies the state of the driver.
58
+ * We don't want to affect cachingDriver state with compilation including "CURSOR" suffix.
59
+ *
60
+ * We could in theory save this fresh driver for reuse, but it is a choice between extra memory usage and speed.
61
+ * The scenario in which "CURSOR" is applied (empty query or query equal to any keyword) has a slim chance of happening.
62
+ */
63
+
64
+ val driver = if wasCursorApplied then freshDriver() else cachingDriver
53
65
driver.run(uri, sourceFile)
54
66
55
67
given ctx : Context = driver.currentCtx
@@ -61,11 +73,12 @@ class CompletionProvider(
61
73
val adjustedPath = Interactive .resolveTypedOrUntypedPath(tpdPath0, pos)(using newctx)
62
74
63
75
val tpdPath = tpdPath0 match
64
- // $1$ // FIXME add check for a $1$ name to make sure we only do the below in lifting case
65
- case Select (qual, name) :: tail if qual.symbol.is(Flags .Synthetic ) =>
66
- qual.symbol.defTree match
67
- case valdef : ValDef => Select (valdef.rhs, name) :: tail
68
- case _ => tpdPath0
76
+ case Select (qual, name) :: tail
77
+ // If for any reason we end up in param after lifting, we want to inline the synthetic val
78
+ if qual.symbol.is(Flags .Synthetic ) && qual.symbol.name.isInstanceOf [DerivedName ] =>
79
+ qual.symbol.defTree match
80
+ case valdef : ValDef => Select (valdef.rhs, name) :: tail
81
+ case _ => tpdPath0
69
82
case _ => tpdPath0
70
83
71
84
0 commit comments