3131import java .io .IOException ;
3232import java .io .InputStream ;
3333import java .io .OutputStream ;
34+ import java .lang .ProcessBuilder .Redirect ;
3435import java .net .InetAddress ;
3536import java .net .Socket ;
3637import java .net .URI ;
6869import org .eclipse .lsp4j .WorkDoneProgressCreateParams ;
6970import org .eclipse .lsp4j .WorkspaceFolder ;
7071import org .eclipse .lsp4j .jsonrpc .Launcher ;
72+ import org .rascalmpl .ideservices .GsonUtils ;
7173import org .rascalmpl .uri .URIUtil ;
7274import org .rascalmpl .vscode .lsp .parametric .LanguageRegistry .LanguageParameter ;
7375import org .rascalmpl .vscode .lsp .parametric .routing .RoutingTextDocumentService ;
7476import org .rascalmpl .vscode .lsp .parametric .routing .RoutingWorkspaceService ;
77+ import org .rascalmpl .vscode .lsp .util .NamedThreadPool ;
7578import org .rascalmpl .vscode .lsp .util .Router ;
7679
7780import io .usethesource .vallang .IInteger ;
@@ -140,24 +143,29 @@ public static String extension(ISourceLocation doc) {
140143
141144 private @ Nullable CompletableFuture <IBaseLanguageServerExtensions > startServer (LanguageParameter lang ) {
142145 try {
143- var classPath = System .getProperty ("java.class.path" );
144146 InputStream in ;
145147 OutputStream out ;
146148 Runnable onExit ;
147149 if (DEPLOY_MODE ) {
150+ // TODO Figure out Rascal/Rascal-LSP versions/class path
151+ logger .info ("Starting LSP process for {}" , lang .getName ());
152+ logger .debug ("{} runs with Rascal {} and Rascal-LSP {}" , lang .getName (), "x.xx.xx" , "y.yy.yy" );
148153 // In deployment, we start a process and connect to it via input/output streams
149- var proc = new ProcessBuilder ("java"
154+ var classPath = System .getProperty ("java.class.path" );
155+ var proc = new ProcessBuilder (ProcessHandle .current ().info ().command ().get ()
150156 , "-Dlog4j2.configurationFactory=org.rascalmpl.vscode.lsp.log.LogJsonConfiguration"
151157 , "-Dlog4j2.level=DEBUG"
152158 , "-Drascal.fallbackResolver=org.rascalmpl.vscode.lsp.uri.FallbackResolver"
153- , "-Drascal.lsp.deploy=" + DEPLOY_MODE
159+ , "-Drascal.lsp.deploy=true"
154160 , "-Drascal.compilerClasspath=" + classPath
155- , "-cp" + classPath
161+ , "-Xmx2048M"
162+ , "-cp" , classPath
156163 , "org.rascalmpl.vscode.lsp.parametric.ParametricLanguageServer"
157- ).start ();
164+ ).redirectError (Redirect .INHERIT ).start ();
165+
166+ logger .debug ("Launched language server on process {}" , proc .pid ());
158167 in = proc .getInputStream ();
159168 out = proc .getOutputStream ();
160- // TODO Do we need to close the process here? Or is this triggered after the process exits?
161169 onExit = () -> {};
162170 } else {
163171 // In development, we expect the server to have been launched on a pre-agreed port
@@ -168,9 +176,10 @@ public static String extension(ISourceLocation doc) {
168176 out = socket .getOutputStream ();
169177 onExit = () -> {
170178 try {
179+ logger .debug ("Closing socket for language {} on port" , lang .getName (), port );
171180 socket .close ();
172181 } catch (IOException e ) {
173- logger .error ("Closing socket for language {} on port {} failed" , lang .getName (), port );
182+ logger .error ("Closing socket failed" , lang .getName (), port );
174183 }
175184 };
176185 }
@@ -179,9 +188,12 @@ public static String extension(ISourceLocation doc) {
179188 .setLocalService (this )
180189 .setInput (in )
181190 .setOutput (out )
191+ .configureGson (GsonUtils .complexAsJsonObject ()) // Only needed if we want to communicate IValues
192+ .setExecutorService (NamedThreadPool .single ("parametric-lsp-router-out" ))
182193 .create ();
183194
184- scheduleShutdown (serverLauncher .startListening (), lang , onExit );
195+ var runner = serverLauncher .startListening ();
196+ scheduleShutdown (runner , lang , onExit );
185197 var server = serverLauncher .getRemoteProxy ();
186198 var delegateServerCaps = server .initialize (delegateInitializationParams ());
187199
@@ -197,6 +209,7 @@ private void scheduleShutdown(Future<Void> server, LanguageParameter lang, Runna
197209 getExecutor ().execute (() -> {
198210 try {
199211 server .get ();
212+ logger .info ("Language server for {} terminated gracefully" , lang .getName ());
200213 } catch (CancellationException | ExecutionException | InterruptedException e ) {
201214 logger .error ("Language server for {} crashed" , lang .getName (), e );
202215 }
0 commit comments