Skip to content

Make the IDE work under Windows #2776

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 19, 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
4 changes: 3 additions & 1 deletion docs/docs/usage/ide-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ Usage
=====
1. Install [Visual Studio Code](https://code.visualstudio.com/).
2. Make sure `code`, the binary for Visual Studio Code, is on your `$PATH`, this
is the case if you can start the IDE by running `code` in a terminal.
is the case if you can start the IDE by running `code` in a terminal. This
is the default on all systems except Mac where you'll need to follow these
instructions: https://code.visualstudio.com/docs/setup/mac#_command-line
3. In your project, run:
```shell
sbt launchIDE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class DottyLanguageServer extends LanguageServer

myDrivers = new mutable.HashMap
for (config <- configs) {
val classpathFlags = List("-classpath", (config.classDirectory +: config.dependencyClasspath).mkString(":"))
val classpathFlags = List("-classpath", (config.classDirectory +: config.dependencyClasspath).mkString(File.pathSeparator))
val settings = defaultFlags ++ config.compilerArguments.toList ++ classpathFlags
myDrivers.put(config, new InteractiveDriver(settings))
}
Expand All @@ -76,7 +76,7 @@ class DottyLanguageServer extends LanguageServer
def driverFor(uri: URI): InteractiveDriver = {
val matchingConfig =
drivers.keys.find(config => config.sourceDirectories.exists(sourceDir =>
uri.getRawPath.startsWith(sourceDir.getAbsolutePath.toString)))
new File(uri.getPath).getCanonicalPath.startsWith(sourceDir.getCanonicalPath)))
matchingConfig match {
case Some(config) =>
drivers(config)
Expand Down
72 changes: 19 additions & 53 deletions project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import sbt.Package.ManifestAttributes
import com.typesafe.sbteclipse.plugin.EclipsePlugin._

import dotty.tools.sbtplugin.DottyPlugin.autoImport._
import dotty.tools.sbtplugin.DottyIDEPlugin.{ prepareCommand, runProcess }
import dotty.tools.sbtplugin.DottyIDEPlugin.autoImport._
import org.scalajs.sbtplugin.ScalaJSPlugin
import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport._
Expand Down Expand Up @@ -766,8 +767,13 @@ object Build {
val mainClass = "dotty.tools.languageserver.Main"
val extensionPath = (baseDirectory in `vscode-dotty`).value.getAbsolutePath

val codeArgs = if (inputArgs.isEmpty) List((baseDirectory.value / "..").getAbsolutePath) else inputArgs
val allArgs = List("-client_command", "code", s"--extensionDevelopmentPath=$extensionPath") ++ codeArgs
val codeArgs =
s"--extensionDevelopmentPath=$extensionPath" +:
(if (inputArgs.isEmpty) List((baseDirectory.value / "..").getAbsolutePath) else inputArgs)

val clientCommand = prepareCommand(codeCommand.value ++ codeArgs)

val allArgs = "-client_command" +: clientCommand

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


sbtPlugin := true,
version := "0.1.2",
version := "0.1.3",
ScriptedPlugin.scriptedSettings,
ScriptedPlugin.sbtTestDirectory := baseDirectory.value / "sbt-test",
ScriptedPlugin.scriptedBufferLog := false,
Expand Down Expand Up @@ -924,76 +930,36 @@ object Build {
compile in Compile := {
val coursier = baseDirectory.value / "out/coursier"
val packageJson = baseDirectory.value / "package.json"
if (!coursier.exists || packageJson.lastModified > coursier.lastModified) {
val exitCode = new java.lang.ProcessBuilder("npm", "run", "update-all")
.directory(baseDirectory.value)
.inheritIO()
.start()
.waitFor()
if (exitCode != 0)
throw new MessageOnlyException("'npm run update-all' in vscode-dotty failed")
}
if (!coursier.exists || packageJson.lastModified > coursier.lastModified)
runProcess(Seq("npm", "run", "update-all"), wait = true, directory = baseDirectory.value)
val tsc = baseDirectory.value / "node_modules" / ".bin" / "tsc"
val exitCodeTsc = new java.lang.ProcessBuilder(tsc.getAbsolutePath, "--pretty", "--project", baseDirectory.value.getAbsolutePath)
.inheritIO()
.start()
.waitFor()
if (exitCodeTsc != 0)
throw new MessageOnlyException("tsc in vscode-dotty failed")
runProcess(Seq(tsc.getAbsolutePath, "--pretty", "--project", baseDirectory.value.getAbsolutePath), wait = true)

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

sbt.inc.Analysis.Empty
},
sbt.Keys.`package`:= {
val exitCode = new java.lang.ProcessBuilder("vsce", "package")
.directory(baseDirectory.value)
.inheritIO()
.start()
.waitFor()
if (exitCode != 0)
throw new MessageOnlyException("vsce package failed")
runProcess(Seq("vsce", "package"), wait = true, directory = baseDirectory.value)

baseDirectory.value / s"dotty-${version.value}.vsix"
},
unpublish := {
val exitCode = new java.lang.ProcessBuilder("vsce", "unpublish")
.directory(baseDirectory.value)
.inheritIO()
.start()
.waitFor()
if (exitCode != 0)
throw new MessageOnlyException("vsce unpublish failed")
runProcess(Seq("vsce", "unpublish"), wait = true, directory = baseDirectory.value)
},
publish := {
val exitCode = new java.lang.ProcessBuilder("vsce", "publish")
.directory(baseDirectory.value)
.inheritIO()
.start()
.waitFor()
if (exitCode != 0)
throw new MessageOnlyException("vsce publish failed")
runProcess(Seq("vsce", "publish"), wait = true, directory = baseDirectory.value)
},
run := Def.inputTask {
val inputArgs = spaceDelimited("<arg>").parsed
val codeArgs = if (inputArgs.isEmpty) List((baseDirectory.value / "..").getAbsolutePath) else inputArgs
val extensionPath = baseDirectory.value.getAbsolutePath
val processArgs = List("code", s"--extensionDevelopmentPath=${extensionPath}") ++ codeArgs

val exitCode = new java.lang.ProcessBuilder(processArgs: _*)
.inheritIO()
.start()
.waitFor()
if (exitCode != 0)
throw new MessageOnlyException("Running Visual Studio Code failed")
val processArgs = List(s"--extensionDevelopmentPath=${extensionPath}") ++ codeArgs

runProcess(codeCommand.value ++ processArgs, wait = true)
}.dependsOn(compile in Compile).evaluated
)

Expand Down
42 changes: 32 additions & 10 deletions sbt-dotty/src/dotty/tools/sbtplugin/DottyIDEPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import sbt.Keys._
import java.io._
import java.lang.ProcessBuilder
import scala.collection.mutable
import scala.util.Properties.{ isWin, isMac }

import dotty.tools.languageserver.config.ProjectConfig

Expand Down Expand Up @@ -123,9 +124,34 @@ object DottyIDEPlugin extends AutoPlugin {
runTask(joinedTask, state)
}

/** Prepare command to be passed to ProcessBuilder */
def prepareCommand(cmd: Seq[String]): Seq[String] =
if (isWin) Seq("cmd.exe", "/C") ++ cmd
else cmd

/** Run `cmd`.
* @param wait If true, wait for `cmd` to return and throw an exception if the exit code is non-zero.
* @param directory If not null, run `cmd` in this directory.
*/
def runProcess(cmd: Seq[String], wait: Boolean = false, directory: File = null): Unit = {
val pb0 = new ProcessBuilder(prepareCommand(cmd): _*).inheritIO()
val pb = if (directory != null) pb0.directory(directory) else pb0
if (wait) {
val exitCode = pb.start().waitFor()
if (exitCode != 0) {
val cmdString = cmd.mkString(" ")
val description = if (directory != null) s""" in directory "$directory"""" else ""
throw new MessageOnlyException(s"""Running command "${cmdString}"${description} failed.""")
}
}
else
pb.start()
}

private val projectConfig = taskKey[Option[ProjectConfig]]("")

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

codeCommand := {
Seq("code", "-n")
},

runCode := {
val exitCode = new ProcessBuilder("code", "--install-extension", "lampepfl.dotty")
.inheritIO()
.start()
.waitFor()
if (exitCode != 0)
throw new MessageOnlyException("Installing the Dotty support for VSCode failed")

new ProcessBuilder("code", baseDirectory.value.getAbsolutePath)
.inheritIO()
.start()
runProcess(codeCommand.value ++ Seq("--install-extension", "lampepfl.dotty"), wait = true)
runProcess(codeCommand.value ++ Seq("."), directory = baseDirectory.value)
}

) ++ addCommandAlias("launchIDE", ";configureIDE;runCode")
Expand Down
1 change: 1 addition & 0 deletions vscode-dotty/.vscodeignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ target/**
.vscode/**
.vscode-test/**
out/test/**
out/.keep
test/**
src/**
**/*.map
Expand Down
5 changes: 4 additions & 1 deletion vscode-dotty/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ Dotty, please follow the instructions at https://github.com/lampepfl/dotty-examp

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


If this is the case and your project succesfully compiles with dotty, you can
simply use the `launchIDE` command provided by the sbt-dotty plugin:
Expand Down
Empty file added vscode-dotty/out/.keep
Empty file.
2 changes: 1 addition & 1 deletion vscode-dotty/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"tsc": "./node_modules/.bin/tsc",
"vscode:prepublish": "npm run update-all && ./node_modules/.bin/tsc -p ./",
"compile": "./node_modules/.bin/tsc -p ./",
"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",
"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",
"test": "node ./node_modules/vscode/bin/test"
},
"extensionDependencies": [
Expand Down