Skip to content

Commit

Permalink
engine-runner shall not depend on language-server (#10536)
Browse files Browse the repository at this point in the history
  • Loading branch information
JaroslavTulach authored Jul 12, 2024
1 parent 3d967ae commit aaa3495
Show file tree
Hide file tree
Showing 26 changed files with 310 additions and 152 deletions.
74 changes: 55 additions & 19 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ lazy val enso = (project in file("."))
`akka-native`,
`version-output`,
`refactoring-utils`,
`engine-runner-common`,
`engine-runner`,
runtime,
searcher,
Expand Down Expand Up @@ -1508,25 +1509,26 @@ lazy val `language-server` = (project in file("engine/language-server"))
commands += WithDebugCommand.withDebug,
frgaalJavaCompilerSetting,
libraryDependencies ++= akka ++ circe ++ Seq(
"org.slf4j" % "slf4j-api" % slf4jVersion,
"com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingVersion,
"io.circe" %% "circe-generic-extras" % circeGenericExtrasVersion,
"io.circe" %% "circe-literal" % circeVersion,
"dev.zio" %% "zio" % zioVersion,
"com.google.flatbuffers" % "flatbuffers-java" % flatbuffersVersion,
"commons-io" % "commons-io" % commonsIoVersion,
"com.github.pureconfig" %% "pureconfig" % pureconfigVersion,
"org.slf4j" % "slf4j-api" % slf4jVersion,
"com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingVersion,
"io.circe" %% "circe-generic-extras" % circeGenericExtrasVersion,
"io.circe" %% "circe-literal" % circeVersion,
"dev.zio" %% "zio" % zioVersion,
"com.google.flatbuffers" % "flatbuffers-java" % flatbuffersVersion,
"commons-io" % "commons-io" % commonsIoVersion,
"com.github.pureconfig" %% "pureconfig" % pureconfigVersion,
akkaTestkit % Test,
"com.typesafe.akka" %% "akka-http-testkit" % akkaHTTPVersion % Test,
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test,
"org.graalvm.truffle" % "truffle-api" % graalMavenPackagesVersion % "provided",
"org.graalvm.sdk" % "polyglot-tck" % graalMavenPackagesVersion % "provided",
"org.eclipse.jgit" % "org.eclipse.jgit" % jgitVersion,
"org.bouncycastle" % "bcutil-jdk18on" % "1.76" % Test,
"org.bouncycastle" % "bcpkix-jdk18on" % "1.76" % Test,
"org.bouncycastle" % "bcprov-jdk18on" % "1.76" % Test,
"org.apache.tika" % "tika-core" % tikaVersion % Test
"com.typesafe.akka" %% "akka-http-testkit" % akkaHTTPVersion % Test,
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test,
"org.graalvm.truffle" % "truffle-api" % graalMavenPackagesVersion % "provided",
"org.graalvm.sdk" % "polyglot-tck" % graalMavenPackagesVersion % "provided",
"org.netbeans.api" % "org-openide-util-lookup" % netbeansApiVersion % "provided",
"org.eclipse.jgit" % "org.eclipse.jgit" % jgitVersion,
"org.bouncycastle" % "bcutil-jdk18on" % "1.76" % Test,
"org.bouncycastle" % "bcpkix-jdk18on" % "1.76" % Test,
"org.bouncycastle" % "bcprov-jdk18on" % "1.76" % Test,
"org.apache.tika" % "tika-core" % tikaVersion % Test
),
Test / testOptions += Tests
.Argument(TestFrameworks.ScalaCheck, "-minSuccessfulTests", "1000"),
Expand Down Expand Up @@ -1660,6 +1662,7 @@ lazy val `language-server` = (project in file("engine/language-server"))
.dependsOn(`library-manager`)
.dependsOn(`connected-lock-manager-server`)
.dependsOn(`edition-updater`)
.dependsOn(`engine-runner-common`)
.dependsOn(`logging-utils-akka`)
.dependsOn(`logging-service`)
.dependsOn(`polyglot-api`)
Expand Down Expand Up @@ -2459,6 +2462,37 @@ lazy val `runtime-fat-jar` =
* recompilation but still convince the IDE that it is a .jar dependency.
*/

/* The purpose of the `engine-runner-common` project is to contain everything
* that's needed for the `engine-runner` project to invoke `language-server` when
* `--server` option is used.
*
* As such this project contains (primarily) the `LanguageServerApi`
* API & SPI class. `engine-runner` project call the `LanguageServerApi` class static method
* and that method then delegates to an implementation which is supposed to be provided
* by the `language-server` project.
*
* `engine-runner` and `language-server` projects shall be "loosely coupled" - they shouldn't
* have compile time dependency between each other. All that's needed for them to
* communicate belongs into `engine-runner-common` project.
*/
lazy val `engine-runner-common` = project
.in(file("engine/runner-common"))
.settings(
frgaalJavaCompilerSetting,
Test / fork := true,
commands += WithDebugCommand.withDebug,
Test / envVars ++= distributionEnvironmentOverrides,
libraryDependencies ++= Seq(
"org.graalvm.polyglot" % "polyglot" % graalMavenPackagesVersion % "provided",
"commons-io" % "commons-io" % commonsIoVersion,
"commons-cli" % "commons-cli" % commonsCliVersion
)
)
.dependsOn(`polyglot-api`)
.dependsOn(`library-manager`)
.dependsOn(`edition-updater`)
.dependsOn(testkit % Test)

lazy val `engine-runner` = project
.in(file("engine/runner"))
.settings(
Expand Down Expand Up @@ -2684,14 +2718,16 @@ lazy val `engine-runner` = project
.dependsOn(yaml)
.dependsOn(pkg)
.dependsOn(cli)
.dependsOn(`profiling-utils`)
.dependsOn(`library-manager`)
.dependsOn(`language-server`)
.dependsOn(`edition-updater`)
.dependsOn(`runtime-parser`)
.dependsOn(`logging-service`)
.dependsOn(`logging-service-logback` % Runtime)
.dependsOn(`engine-runner-common`)
.dependsOn(`polyglot-api`)
.dependsOn(`enso-test-java-helpers`)
.dependsOn(`language-server` % Runtime)

lazy val buildSmallJdk =
taskKey[File]("Build a minimal JDK used for native image generation")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package org.enso.languageserver.boot;

import java.util.UUID;
import org.apache.commons.cli.CommandLine;
import org.enso.runner.common.LanguageServerApi;
import org.enso.runner.common.ProfilingConfig;
import org.enso.runner.common.WrongOption;
import org.openide.util.lookup.ServiceProvider;
import org.slf4j.event.Level;
import scala.concurrent.ExecutionContext;

@ServiceProvider(service = LanguageServerApi.class)
public final class LanguageServerRunner extends LanguageServerApi {
public LanguageServerRunner() {}

/**
* Handles `--server` CLI option
*
* @param line a CLI line
* @param prof profiling config
* @param logLevel log level to set for the engine runtime
*/
protected final void runLanguageServer(CommandLine line, ProfilingConfig prof, Level logLevel)
throws WrongOption {
var config = parseServerOptions(line, prof);
LanguageServerApp.run(config, logLevel, line.hasOption(LanguageServerApi.DAEMONIZE_OPTION));
}

private static LanguageServerConfig parseServerOptions(
CommandLine line, ProfilingConfig profilingConfig) throws WrongOption {
UUID rootId;
try {
var id = line.getOptionValue(LanguageServerApi.ROOT_ID_OPTION);
if (id == null) {
throw new WrongOption("Root id must be provided");
}
rootId = UUID.fromString(id);
} catch (IllegalArgumentException e) {
throw new WrongOption("Root must be UUID");
}
var rootPath = line.getOptionValue(LanguageServerApi.ROOT_PATH_OPTION);
if (rootPath == null) {
throw new WrongOption("Root path must be provided");
}
var interfac = line.getOptionValue(LanguageServerApi.INTERFACE_OPTION, "127.0.0.1");
int rpcPort;
try {
rpcPort = Integer.parseInt(line.getOptionValue(LanguageServerApi.RPC_PORT_OPTION, "8080"));
} catch (NumberFormatException e) {
throw new WrongOption("Port must be integer");
}
int dataPort;
try {
dataPort = Integer.parseInt(line.getOptionValue(LanguageServerApi.DATA_PORT_OPTION, "8081"));
} catch (NumberFormatException e) {
throw new WrongOption("Port must be integer");
}
Integer secureRpcPort;
try {
var port = line.getOptionValue(LanguageServerApi.SECURE_RPC_PORT_OPTION);
secureRpcPort = port == null ? null : Integer.valueOf(port);
} catch (NumberFormatException e) {
throw new WrongOption("Port must be integer");
}
Integer secureDataPort;
try {
var port = line.getOptionValue(LanguageServerApi.SECURE_DATA_PORT_OPTION);
secureDataPort = port == null ? null : Integer.valueOf(port);
} catch (NumberFormatException e) {
throw new WrongOption("Port must be integer");
}
var graalVMUpdater = line.hasOption(LanguageServerApi.SKIP_GRAALVM_UPDATER);

var config =
new LanguageServerConfig(
interfac,
rpcPort,
scala.Option.apply(secureRpcPort),
dataPort,
scala.Option.apply(secureDataPort),
rootId,
rootPath,
profilingConfig,
new StartupConfig(graalVMUpdater),
"language-server",
ExecutionContext.global());
return config;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.enso.runner
package org.enso.languageserver.boot

import com.typesafe.scalalogging.Logger
import org.enso.languageserver.boot.{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.enso.languageserver.boot

import java.util.UUID

import org.enso.runner.common.ProfilingConfig
import scala.concurrent.{ExecutionContext, ExecutionContextExecutor}

/** The config of the running Language Server instance.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import org.enso.editions.EditionResolver
import org.enso.editions.updater.EditionManager
import org.enso.filewatcher.WatcherAdapterFactory
import org.enso.jsonrpc.{JsonRpcServer, SecureConnectionConfig}
import org.enso.runner.common.CompilerBasedDependencyExtractor
import org.enso.languageserver.capability.CapabilityRouter
import org.enso.languageserver.data._
import org.enso.languageserver.effect
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.enso.languageserver.data

import org.enso.languageserver.boot.{ProfilingConfig, StartupConfig}
import org.enso.runner.common.ProfilingConfig
import org.enso.languageserver.boot.StartupConfig
import org.enso.languageserver.filemanager.ContentRootWithFile
import org.enso.logger.masking.{MaskedPath, ToLogString}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ import org.enso.languageserver.libraries.LocalLibraryManagerProtocol.{
FindLibrary,
FindLibraryResponse
}
import org.enso.languageserver.libraries.{
BlockingOperation,
CompilerBasedDependencyExtractor
}
import org.enso.runner.common.CompilerBasedDependencyExtractor
import org.enso.languageserver.libraries.BlockingOperation
import org.enso.languageserver.requesthandler.RequestTimeout
import org.enso.languageserver.util.UnhandledLogging
import org.enso.libraryupload.{auth, LibraryUploader}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.enso.languageserver;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;

import org.junit.Test;

public class LanguageServerDependenciesTest {

public LanguageServerDependenciesTest() {}

@Test
public void unableToLoadClassFromEngineRunnerProject() {
try {
var c = Class.forName("org.enso.runner.Main");
fail("Shouldn't be able to load class from engine-runner project " + c);
} catch (ClassNotFoundException ex) {
// OK
}
}

@Test
public void ableToLoadClassFromEngineRunnerCommonProject() throws ClassNotFoundException {
var c = Class.forName("org.enso.runner.common.LanguageServerApi");
assertNotNull(
"Should be able to load class from engine-runner-common project (obviously as we have"
+ " compile time dependency)",
c);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package org.enso.languageserver.boot.resource
import akka.actor.ActorSystem
import akka.testkit._
import org.apache.commons.io.FileUtils
import org.enso.languageserver.boot.{ProfilingConfig, StartupConfig}
import org.enso.runner.common.ProfilingConfig
import org.enso.languageserver.boot.StartupConfig
import org.enso.languageserver.data._
import org.enso.languageserver.event.InitializedEvent
import org.enso.languageserver.filemanager.{ContentRoot, ContentRootWithFile}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package org.enso.languageserver.filemanager
import akka.actor.{ActorRef, ActorSystem}
import akka.testkit.{TestDuration, TestKit, TestProbe}
import org.apache.commons.lang3.SystemUtils
import org.enso.languageserver.boot.{ProfilingConfig, StartupConfig}
import org.enso.runner.common.ProfilingConfig
import org.enso.languageserver.boot.StartupConfig
import org.enso.languageserver.data._
import org.enso.languageserver.filemanager.ContentRootManagerProtocol.{
ContentRootsAddedNotification,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package org.enso.languageserver.runtime
import akka.actor.{ActorRef, ActorSystem}
import akka.testkit.{ImplicitSender, TestKit, TestProbe}
import org.apache.commons.io.FileUtils
import org.enso.languageserver.boot.{ProfilingConfig, StartupConfig}
import org.enso.runner.common.ProfilingConfig
import org.enso.languageserver.boot.StartupConfig
import org.enso.languageserver.data._
import org.enso.languageserver.filemanager.{
ContentRoot,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package org.enso.languageserver.search
import akka.actor.{ActorRef, ActorSystem}
import akka.testkit.{ImplicitSender, TestKit, TestProbe}
import org.apache.commons.io.FileUtils
import org.enso.languageserver.boot.{ProfilingConfig, StartupConfig}
import org.enso.runner.common.ProfilingConfig
import org.enso.languageserver.boot.StartupConfig
import org.enso.languageserver.capability.CapabilityProtocol.{
AcquireCapability,
CapabilityAcquired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import akka.actor.{ActorRef, Props}
import akka.http.scaladsl.model.RemoteAddress
import com.google.flatbuffers.FlatBufferBuilder
import org.apache.commons.io.FileUtils
import org.enso.languageserver.boot.{ProfilingConfig, StartupConfig}
import org.enso.runner.common.ProfilingConfig
import org.enso.languageserver.boot.StartupConfig
import org.enso.languageserver.data.{
Config,
ExecutionContextConfig,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@ import org.enso.filewatcher.{NoopWatcherFactory, WatcherAdapterFactory}
import org.enso.jsonrpc.test.JsonRpcServerTestKit
import org.enso.jsonrpc.{ClientControllerFactory, ProtocolFactory}
import org.enso.languageserver.TestClock
import org.enso.languageserver.boot.{
ProfilingConfig,
StartupConfig,
TimingsConfig
}
import org.enso.runner.common.ProfilingConfig
import org.enso.runner.common.CompilerBasedDependencyExtractor
import org.enso.languageserver.boot.{StartupConfig, TimingsConfig}
import org.enso.languageserver.boot.resource.{
DirectoriesInitialization,
InitializationComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import io.circe.literal._
import io.circe.parser.parse
import org.apache.commons.io.FileUtils
import org.bouncycastle.util.encoders.Hex
import org.enso.languageserver.boot.{ProfilingConfig, StartupConfig}
import org.enso.runner.common.ProfilingConfig
import org.enso.languageserver.boot.StartupConfig
import org.enso.languageserver.data._
import org.enso.logger.ReportLogsOnFailure
import org.enso.polyglot.runtime.Runtime.Api
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import org.eclipse.jgit.api.{Git => JGit}
import org.eclipse.jgit.lib.Repository
import org.eclipse.jgit.revwalk.RevCommit
import org.eclipse.jgit.storage.file.FileRepositoryBuilder
import org.enso.languageserver.boot.{ProfilingConfig, StartupConfig}
import org.enso.runner.common.ProfilingConfig
import org.enso.languageserver.boot.StartupConfig
import org.enso.languageserver.data._
import org.enso.languageserver.vcsmanager.VcsApi
import org.enso.logger.ReportLogsOnFailure
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.enso.runner.common;

import java.util.ServiceLoader;
import org.apache.commons.cli.CommandLine;
import org.slf4j.event.Level;

public abstract class LanguageServerApi {
public static final String DAEMONIZE_OPTION = "daemon";
public static final String ROOT_ID_OPTION = "root-id";
public static final String ROOT_PATH_OPTION = "path";
public static final String INTERFACE_OPTION = "interface";
public static final String RPC_PORT_OPTION = "rpc-port";
public static final String DATA_PORT_OPTION = "data-port";
public static final String SECURE_RPC_PORT_OPTION = "secure-rpc-port";
public static final String SECURE_DATA_PORT_OPTION = "secure-data-port";
public static final String SKIP_GRAALVM_UPDATER = "skip-graalvm-updater";

public static void launchLanguageServer(CommandLine line, ProfilingConfig config, Level logLevel)
throws WrongOption {
var it =
ServiceLoader.load(LanguageServerApi.class, LanguageServerApi.class.getClassLoader())
.iterator();
var impl = it.next();
impl.runLanguageServer(line, config, logLevel);
}

protected abstract void runLanguageServer(
CommandLine line, ProfilingConfig config, Level logLevel) throws WrongOption;
}
Loading

0 comments on commit aaa3495

Please sign in to comment.