Skip to content
This repository has been archived by the owner on Jul 25, 2022. It is now read-only.

Try to launch ENSIME server #3

Merged
merged 5 commits into from
Nov 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,14 @@ workingDir/
.idea/
.idea_modules/
src/main/main.iml
lib/
*.pem

.tags*
.ensime*
.classpath*
.atom*
.imdone*

# APM
lib/
package.json
17 changes: 17 additions & 0 deletions apm.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,23 @@ apmPackage := {
"outline-view" -> Json.obj(
"versions" -> Json.obj("0.1.0" -> "provideOutlines")
)
),
"configSchema" -> Json.obj(
"server" -> Json.obj(
"type" -> "string",
"title" -> "Language server",
"default" -> "scalameta",
"enum" -> Json.arr(
Json.obj(
"value" -> "scalameta",
"description" -> "Scalameta"
),
Json.obj(
"value" -> "ensime",
"description" -> "ENSIME"
)
)
)
)
)

Expand Down
35 changes: 15 additions & 20 deletions src/main/scala/ScalaLanguageClient.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,33 @@ import facade.atom_ide.busy_signal._

class ScalaLanguageClient extends AutoLanguageClient { client =>

private lazy val server: ServerType = ServerType.fromConfig

override def getGrammarScopes(): js.Array[String] = js.Array("source.scala")
override def getLanguageName(): String = "Scala"
override def getServerName(): String = "Scalameta"
override def getServerName(): String = server.name

override def startServerProcess(projectPath: String): ChildProcess = {
global.console.log(s"startServerProcess(${projectPath})")

// FIXME: use more civilized way of detecting JAVA_HOME
val javaHome = ChildProcess.asInstanceOf[js.Dynamic].execSync("/usr/libexec/java_home").toString.trim
val toolsJar = Path.join(javaHome, "lib", "tools.jar")

// TODO: try to use coursier directly
// TODO: try to use coursier directly or download it on the first run
val coursierJar = Path.join(OS.homedir, "bin", "coursier")
val coursierArgs = js.Array(
"launch", "--quiet",
"--repository", "bintray:dhpcs/maven",
"--repository", "sonatype:releases",
"--extra-jars", toolsJar,
"org.scalameta:metaserver_2.12:0.1-SNAPSHOT",
"--main", "scala.meta.languageserver.Main"
)

val javaBin = Path.join(javaHome, "bin", "java")
val javaArgs = js.Array(
s"-Dvscode.workspace=${projectPath}",
"-jar", coursierJar
).concat(coursierArgs)
val javaArgs =
server.javaArgs(projectPath) ++
Seq(
"-jar", coursierJar,
"launch", "--quiet",
"--extra-jars", toolsJar
) ++
server.coursierArgs

global.console.log(javaArgs.mkString(javaBin, "\n", ""))
println((javaBin +: javaArgs).mkString("\n"))

val serverProcess = ChildProcess.spawn(javaBin, javaArgs)
val serverProcess = ChildProcess.spawn(javaBin, js.Array(javaArgs: _*))
client.captureServerErrors(serverProcess)
serverProcess.on("exit", { err: js.Any =>
busySignal.clear()
Expand All @@ -49,8 +45,7 @@ class ScalaLanguageClient extends AutoLanguageClient { client =>
}

override def filterChangeWatchedFiles(filePath: String): Boolean = {
filePath.endsWith(".semanticdb") ||
filePath.endsWith(".compilerconfig")
server.watchFilter(filePath)
}

override def preInitialization(connection: js.Any): Unit = {
Expand Down
69 changes: 69 additions & 0 deletions src/main/scala/ServerType.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package laughedelic.atom.ide.scala

import scala.scalajs.js, js.annotation._, js.Dynamic.global

sealed trait ServerType {

val name: String

def javaArgs(projectPath: String): Seq[String]
val coursierArgs: Seq[String]

def watchFilter(filePath: String): Boolean
}

case object ServerType {

case object Scalameta extends ServerType {
val name: String = "Scalameta"

def javaArgs(projectPath: String): Seq[String] = Seq(
s"-Dvscode.workspace=${projectPath}"
)

val coursierArgs: Seq[String] = Seq(
"--repository", "bintray:dhpcs/maven",
"--repository", "sonatype:releases",
"org.scalameta:metaserver_2.12:0.1-SNAPSHOT",
"--main", "scala.meta.languageserver.Main"
)

def watchFilter(filePath: String): Boolean = {
filePath.endsWith(".semanticdb") ||
filePath.endsWith(".compilerconfig")
}
}

case object Ensime extends ServerType {
val name: String = "ENSIME"

def javaArgs(projectPath: String): Seq[String] = Seq(
"-Xmx4G", // heap size
// FIXME: how to setup classpath properly without parsing .ensime config?
// "-classpath", classpath,
s"-Dlsp.workspace=${projectPath}",
// TODO: add log level to the plugin settings
s"-Dlsp.logLevel=DEBUG",
)

val coursierArgs: Seq[String] = Seq(
"--repository", "bintray:dhpcs/maven",
"--repository", "sonatype:snapshots",
"org.ensime:server_2.12:3.0.0-SNAPSHOT",
"--main", "org.ensime.server.Server",
"--", "--lsp"
)

def watchFilter(filePath: String): Boolean = {
// TODO: should be more precise:
filePath.contains(".ensime")
}
}

def fromConfig: ServerType = {
global.atom.config.get("ide-scala.server").toString match {
case "scalameta" => Scalameta
case "ensime" => Ensime
}
}
}