Skip to content

Commit 6ade705

Browse files
authored
Merge pull request #2776 from dotty-staging/ide-path
Make the IDE work under Windows
2 parents 3242e86 + d74757f commit 6ade705

File tree

8 files changed

+62
-68
lines changed

8 files changed

+62
-68
lines changed

docs/docs/usage/ide-support.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ Usage
1818
=====
1919
1. Install [Visual Studio Code](https://code.visualstudio.com/).
2020
2. Make sure `code`, the binary for Visual Studio Code, is on your `$PATH`, this
21-
is the case if you can start the IDE by running `code` in a terminal.
21+
is the case if you can start the IDE by running `code` in a terminal. This
22+
is the default on all systems except Mac where you'll need to follow these
23+
instructions: https://code.visualstudio.com/docs/setup/mac#_command-line
2224
3. In your project, run:
2325
```shell
2426
sbt launchIDE

language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class DottyLanguageServer extends LanguageServer
6464

6565
myDrivers = new mutable.HashMap
6666
for (config <- configs) {
67-
val classpathFlags = List("-classpath", (config.classDirectory +: config.dependencyClasspath).mkString(":"))
67+
val classpathFlags = List("-classpath", (config.classDirectory +: config.dependencyClasspath).mkString(File.pathSeparator))
6868
val settings = defaultFlags ++ config.compilerArguments.toList ++ classpathFlags
6969
myDrivers.put(config, new InteractiveDriver(settings))
7070
}
@@ -76,7 +76,7 @@ class DottyLanguageServer extends LanguageServer
7676
def driverFor(uri: URI): InteractiveDriver = {
7777
val matchingConfig =
7878
drivers.keys.find(config => config.sourceDirectories.exists(sourceDir =>
79-
uri.getRawPath.startsWith(sourceDir.getAbsolutePath.toString)))
79+
new File(uri.getPath).getCanonicalPath.startsWith(sourceDir.getCanonicalPath)))
8080
matchingConfig match {
8181
case Some(config) =>
8282
drivers(config)

project/Build.scala

+19-53
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import sbt.Package.ManifestAttributes
1515
import com.typesafe.sbteclipse.plugin.EclipsePlugin._
1616

1717
import dotty.tools.sbtplugin.DottyPlugin.autoImport._
18+
import dotty.tools.sbtplugin.DottyIDEPlugin.{ prepareCommand, runProcess }
1819
import dotty.tools.sbtplugin.DottyIDEPlugin.autoImport._
1920
import org.scalajs.sbtplugin.ScalaJSPlugin
2021
import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport._
@@ -766,8 +767,13 @@ object Build {
766767
val mainClass = "dotty.tools.languageserver.Main"
767768
val extensionPath = (baseDirectory in `vscode-dotty`).value.getAbsolutePath
768769

769-
val codeArgs = if (inputArgs.isEmpty) List((baseDirectory.value / "..").getAbsolutePath) else inputArgs
770-
val allArgs = List("-client_command", "code", s"--extensionDevelopmentPath=$extensionPath") ++ codeArgs
770+
val codeArgs =
771+
s"--extensionDevelopmentPath=$extensionPath" +:
772+
(if (inputArgs.isEmpty) List((baseDirectory.value / "..").getAbsolutePath) else inputArgs)
773+
774+
val clientCommand = prepareCommand(codeCommand.value ++ codeArgs)
775+
776+
val allArgs = "-client_command" +: clientCommand
771777

772778
runTask(Runtime, mainClass, allArgs: _*)
773779
}.dependsOn(compile in (`vscode-dotty`, Compile)).evaluated
@@ -893,7 +899,7 @@ object Build {
893899

894900

895901
sbtPlugin := true,
896-
version := "0.1.2",
902+
version := "0.1.3",
897903
ScriptedPlugin.scriptedSettings,
898904
ScriptedPlugin.sbtTestDirectory := baseDirectory.value / "sbt-test",
899905
ScriptedPlugin.scriptedBufferLog := false,
@@ -924,76 +930,36 @@ object Build {
924930
compile in Compile := {
925931
val coursier = baseDirectory.value / "out/coursier"
926932
val packageJson = baseDirectory.value / "package.json"
927-
if (!coursier.exists || packageJson.lastModified > coursier.lastModified) {
928-
val exitCode = new java.lang.ProcessBuilder("npm", "run", "update-all")
929-
.directory(baseDirectory.value)
930-
.inheritIO()
931-
.start()
932-
.waitFor()
933-
if (exitCode != 0)
934-
throw new MessageOnlyException("'npm run update-all' in vscode-dotty failed")
935-
}
933+
if (!coursier.exists || packageJson.lastModified > coursier.lastModified)
934+
runProcess(Seq("npm", "run", "update-all"), wait = true, directory = baseDirectory.value)
936935
val tsc = baseDirectory.value / "node_modules" / ".bin" / "tsc"
937-
val exitCodeTsc = new java.lang.ProcessBuilder(tsc.getAbsolutePath, "--pretty", "--project", baseDirectory.value.getAbsolutePath)
938-
.inheritIO()
939-
.start()
940-
.waitFor()
941-
if (exitCodeTsc != 0)
942-
throw new MessageOnlyException("tsc in vscode-dotty failed")
936+
runProcess(Seq(tsc.getAbsolutePath, "--pretty", "--project", baseDirectory.value.getAbsolutePath), wait = true)
943937

944938
// Currently, vscode-dotty depends on daltonjorge.scala for syntax highlighting,
945939
// this is not automatically installed when starting the extension in development mode
946940
// (--extensionDevelopmentPath=...)
947-
val exitCodeInstall = new java.lang.ProcessBuilder("code", "--install-extension", "daltonjorge.scala")
948-
.inheritIO()
949-
.start()
950-
.waitFor()
951-
if (exitCodeInstall != 0)
952-
throw new MessageOnlyException("Installing dependency daltonjorge.scala failed")
941+
runProcess(codeCommand.value ++ Seq("--install-extension", "daltonjorge.scala"), wait = true)
953942

954943
sbt.inc.Analysis.Empty
955944
},
956945
sbt.Keys.`package`:= {
957-
val exitCode = new java.lang.ProcessBuilder("vsce", "package")
958-
.directory(baseDirectory.value)
959-
.inheritIO()
960-
.start()
961-
.waitFor()
962-
if (exitCode != 0)
963-
throw new MessageOnlyException("vsce package failed")
946+
runProcess(Seq("vsce", "package"), wait = true, directory = baseDirectory.value)
964947

965948
baseDirectory.value / s"dotty-${version.value}.vsix"
966949
},
967950
unpublish := {
968-
val exitCode = new java.lang.ProcessBuilder("vsce", "unpublish")
969-
.directory(baseDirectory.value)
970-
.inheritIO()
971-
.start()
972-
.waitFor()
973-
if (exitCode != 0)
974-
throw new MessageOnlyException("vsce unpublish failed")
951+
runProcess(Seq("vsce", "unpublish"), wait = true, directory = baseDirectory.value)
975952
},
976953
publish := {
977-
val exitCode = new java.lang.ProcessBuilder("vsce", "publish")
978-
.directory(baseDirectory.value)
979-
.inheritIO()
980-
.start()
981-
.waitFor()
982-
if (exitCode != 0)
983-
throw new MessageOnlyException("vsce publish failed")
954+
runProcess(Seq("vsce", "publish"), wait = true, directory = baseDirectory.value)
984955
},
985956
run := Def.inputTask {
986957
val inputArgs = spaceDelimited("<arg>").parsed
987958
val codeArgs = if (inputArgs.isEmpty) List((baseDirectory.value / "..").getAbsolutePath) else inputArgs
988959
val extensionPath = baseDirectory.value.getAbsolutePath
989-
val processArgs = List("code", s"--extensionDevelopmentPath=${extensionPath}") ++ codeArgs
990-
991-
val exitCode = new java.lang.ProcessBuilder(processArgs: _*)
992-
.inheritIO()
993-
.start()
994-
.waitFor()
995-
if (exitCode != 0)
996-
throw new MessageOnlyException("Running Visual Studio Code failed")
960+
val processArgs = List(s"--extensionDevelopmentPath=${extensionPath}") ++ codeArgs
961+
962+
runProcess(codeCommand.value ++ processArgs, wait = true)
997963
}.dependsOn(compile in Compile).evaluated
998964
)
999965

sbt-dotty/src/dotty/tools/sbtplugin/DottyIDEPlugin.scala

+32-10
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import sbt.Keys._
55
import java.io._
66
import java.lang.ProcessBuilder
77
import scala.collection.mutable
8+
import scala.util.Properties.{ isWin, isMac }
89

910
import dotty.tools.languageserver.config.ProjectConfig
1011

@@ -123,9 +124,34 @@ object DottyIDEPlugin extends AutoPlugin {
123124
runTask(joinedTask, state)
124125
}
125126

127+
/** Prepare command to be passed to ProcessBuilder */
128+
def prepareCommand(cmd: Seq[String]): Seq[String] =
129+
if (isWin) Seq("cmd.exe", "/C") ++ cmd
130+
else cmd
131+
132+
/** Run `cmd`.
133+
* @param wait If true, wait for `cmd` to return and throw an exception if the exit code is non-zero.
134+
* @param directory If not null, run `cmd` in this directory.
135+
*/
136+
def runProcess(cmd: Seq[String], wait: Boolean = false, directory: File = null): Unit = {
137+
val pb0 = new ProcessBuilder(prepareCommand(cmd): _*).inheritIO()
138+
val pb = if (directory != null) pb0.directory(directory) else pb0
139+
if (wait) {
140+
val exitCode = pb.start().waitFor()
141+
if (exitCode != 0) {
142+
val cmdString = cmd.mkString(" ")
143+
val description = if (directory != null) s""" in directory "$directory"""" else ""
144+
throw new MessageOnlyException(s"""Running command "${cmdString}"${description} failed.""")
145+
}
146+
}
147+
else
148+
pb.start()
149+
}
150+
126151
private val projectConfig = taskKey[Option[ProjectConfig]]("")
127152

128153
object autoImport {
154+
val codeCommand = taskKey[Seq[String]]("Command to start VSCode")
129155
val runCode = taskKey[Unit]("Start VSCode, usually called from launchIDE")
130156
val launchIDE = taskKey[Unit]("Configure and run VSCode on this project")
131157
}
@@ -203,17 +229,13 @@ object DottyIDEPlugin extends AutoPlugin {
203229
override def buildSettings: Seq[Setting[_]] = Seq(
204230
commands ++= Seq(configureIDE, compileForIDE),
205231

232+
codeCommand := {
233+
Seq("code", "-n")
234+
},
235+
206236
runCode := {
207-
val exitCode = new ProcessBuilder("code", "--install-extension", "lampepfl.dotty")
208-
.inheritIO()
209-
.start()
210-
.waitFor()
211-
if (exitCode != 0)
212-
throw new MessageOnlyException("Installing the Dotty support for VSCode failed")
213-
214-
new ProcessBuilder("code", baseDirectory.value.getAbsolutePath)
215-
.inheritIO()
216-
.start()
237+
runProcess(codeCommand.value ++ Seq("--install-extension", "lampepfl.dotty"), wait = true)
238+
runProcess(codeCommand.value ++ Seq("."), directory = baseDirectory.value)
217239
}
218240

219241
) ++ addCommandAlias("launchIDE", ";configureIDE;runCode")

vscode-dotty/.vscodeignore

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ target/**
33
.vscode/**
44
.vscode-test/**
55
out/test/**
6+
out/.keep
67
test/**
78
src/**
89
**/*.map

vscode-dotty/README.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ Dotty, please follow the instructions at https://github.com/lampepfl/dotty-examp
66

77
## Starting Visual Studio Code from sbt
88
First, make sure `code`, the binary for Visual Studio Code, is on your `$PATH`,
9-
this is the case if you can start the IDE by running `code` in a terminal.
9+
this is the case if you can start the IDE by running `code` in a terminal. This
10+
is the default on all systems except Mac where you'll need to follow these
11+
instructions: https://code.visualstudio.com/docs/setup/mac#_command-line
12+
1013

1114
If this is the case and your project succesfully compiles with dotty, you can
1215
simply use the `launchIDE` command provided by the sbt-dotty plugin:

vscode-dotty/out/.keep

Whitespace-only changes.

vscode-dotty/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"tsc": "./node_modules/.bin/tsc",
3636
"vscode:prepublish": "npm run update-all && ./node_modules/.bin/tsc -p ./",
3737
"compile": "./node_modules/.bin/tsc -p ./",
38-
"update-all": "npm install && node ./node_modules/vscode/bin/install && mkdir -p out && curl -L -o out/coursier https://github.com/coursier/coursier/raw/v1.0.0-RC3/coursier",
38+
"update-all": "npm install && node ./node_modules/vscode/bin/install && curl -L -o out/coursier https://github.com/coursier/coursier/raw/v1.0.0-RC3/coursier",
3939
"test": "node ./node_modules/vscode/bin/test"
4040
},
4141
"extensionDependencies": [

0 commit comments

Comments
 (0)