@@ -25,6 +25,7 @@ import reporting._, reporting.diagnostic.MessageContainer
25
25
import util ._
26
26
import interactive ._ , interactive .InteractiveDriver ._
27
27
import Interactive .Include
28
+ import config .Printers .interactiv
28
29
29
30
import languageserver .config .ProjectConfig
30
31
@@ -68,12 +69,40 @@ class DottyLanguageServer extends LanguageServer
68
69
val classpathFlags = List (" -classpath" , (config.classDirectory +: config.dependencyClasspath).mkString(File .pathSeparator))
69
70
val sourcepathFlags = List (" -sourcepath" , config.sourceDirectories.mkString(File .pathSeparator), " -scansource" )
70
71
val settings = defaultFlags ++ config.compilerArguments.toList ++ classpathFlags ++ sourcepathFlags
71
- myDrivers.put (config, new InteractiveDriver (settings) )
72
+ myDrivers(config) = new InteractiveDriver (settings)
72
73
}
73
74
}
74
75
myDrivers
75
76
}
76
77
78
+ /** Restart all presentation compiler drivers, copying open files over */
79
+ private def restart () = thisServer.synchronized {
80
+ interactiv.println(" restarting presentation compiler" )
81
+ val driverConfigs = for ((config, driver) <- myDrivers.toList) yield
82
+ (config, new InteractiveDriver (driver.settings), driver.openedFiles)
83
+ for ((config, driver, _) <- driverConfigs)
84
+ myDrivers(config) = driver
85
+ System .gc()
86
+ for ((_, driver, opened) <- driverConfigs; (uri, source) <- opened)
87
+ driver.run(uri, source)
88
+ if (Memory .isCritical())
89
+ println(s " WARNING: Insufficient memory to run Scala language server on these projects. " )
90
+ }
91
+
92
+ private def checkMemory () =
93
+ if (Memory .isCritical())
94
+ CompletableFutures .computeAsync { _ => restart(); new Object () }
95
+ // new Object() necessary or we get a BootstrapMethodError:
96
+ //
97
+ // Caused by: java.lang.invoke.LambdaConversionException: Type mismatch for lambda expected return: void is not convertible to class java.lang.Object
98
+ // at java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:286)
99
+ // at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:303)
100
+ // at java.lang.invoke.CallSite.makeSite(CallSite.java:302)
101
+ // ... 11 more
102
+ //
103
+ // This looks like a problem with Dottys code generation for void-returning closures passed
104
+ // to Java methods. (or SAM functions in general?)
105
+
77
106
/** The driver instance responsible for compiling `uri` */
78
107
def driverFor (uri : URI ): InteractiveDriver = {
79
108
val matchingConfig =
@@ -102,10 +131,11 @@ class DottyLanguageServer extends LanguageServer
102
131
}
103
132
104
133
private [this ] def computeAsync [R ](fun : CancelChecker => R ): CompletableFuture [R ] =
105
- CompletableFutures .computeAsync({( cancelToken : CancelChecker ) =>
134
+ CompletableFutures .computeAsync { cancelToken =>
106
135
// We do not support any concurrent use of the compiler currently.
107
136
thisServer.synchronized {
108
137
cancelToken.checkCanceled()
138
+ checkMemory()
109
139
try {
110
140
fun(cancelToken)
111
141
} catch {
@@ -114,7 +144,7 @@ class DottyLanguageServer extends LanguageServer
114
144
throw ex
115
145
}
116
146
}
117
- })
147
+ }
118
148
119
149
override def initialize (params : InitializeParams ) = computeAsync { cancelToken =>
120
150
rootUri = params.getRootUri
@@ -150,6 +180,7 @@ class DottyLanguageServer extends LanguageServer
150
180
}
151
181
152
182
override def didOpen (params : DidOpenTextDocumentParams ): Unit = thisServer.synchronized {
183
+ checkMemory()
153
184
val document = params.getTextDocument
154
185
val uri = new URI (document.getUri)
155
186
val driver = driverFor(uri)
@@ -163,6 +194,7 @@ class DottyLanguageServer extends LanguageServer
163
194
}
164
195
165
196
override def didChange (params : DidChangeTextDocumentParams ): Unit = thisServer.synchronized {
197
+ checkMemory()
166
198
val document = params.getTextDocument
167
199
val uri = new URI (document.getUri)
168
200
val driver = driverFor(uri)
0 commit comments