Skip to content

Commit bdb0c9c

Browse files
committed
Visual Studio Code extension for Dotty
This extension uses the Dotty Language Server to provide IDE features in Visual Studio Code.
1 parent 5d552a9 commit bdb0c9c

File tree

10 files changed

+525
-1
lines changed

10 files changed

+525
-1
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ project/local-plugins.sbt
1717
.ensime
1818
.ensime_cache/
1919

20+
# npm
21+
node_modules
22+
2023
# Scala-IDE specific
2124
.scala_dependencies
2225
.cache

build.sbt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@ val scalap = Build.scalap
2222
val dist = Build.dist
2323

2424
val `sbt-dotty` = Build.`sbt-dotty`
25+
val `vscode-dotty` = Build.`vscode-dotty`
2526

2627
inThisBuild(Build.thisBuildSettings)

project/Build.scala

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ object Build {
8585
bootstrapFromPublishedJars := false
8686
)
8787

88+
// Only available in vscode-dotty
89+
lazy val unpublish = taskKey[Unit]("Unpublish a package")
90+
91+
8892

8993
lazy val commonSettings = publishSettings ++ Seq(
9094
organization := dottyOrganization,
@@ -775,7 +779,20 @@ object DottyInjectedPlugin extends AutoPlugin {
775779
libraryDependencies ++= Seq(
776780
"org.eclipse.lsp4j" % "org.eclipse.lsp4j" % "0.2.0",
777781
Dependencies.`jackson-databind`
778-
)
782+
),
783+
javaOptions := (javaOptions in `dotty-compiler-bootstrapped`).value,
784+
785+
run := Def.inputTaskDyn {
786+
val inputArgs = spaceDelimited("<arg>").parsed
787+
788+
val mainClass = "dotty.tools.languageserver.Main"
789+
val extensionPath = (baseDirectory in `vscode-dotty`).value.getAbsolutePath
790+
791+
val codeArgs = if (inputArgs.isEmpty) List((baseDirectory.value / "..").getAbsolutePath) else inputArgs
792+
val allArgs = List("-client_command", "code", s"--extensionDevelopmentPath=$extensionPath") ++ codeArgs
793+
794+
runTask(Runtime, mainClass, allArgs: _*)
795+
}.dependsOn(compile in (`vscode-dotty`, Compile)).evaluated
779796
)
780797

781798
/** A sandbox to play with the Scala.js back-end of dotty.
@@ -909,6 +926,108 @@ object DottyInjectedPlugin extends AutoPlugin {
909926
}).evaluated
910927
)
911928

929+
lazy val `vscode-dotty` = project.in(file("vscode-dotty")).
930+
settings(commonSettings).
931+
settings(
932+
EclipseKeys.skipProject := true,
933+
934+
version := "0.0.1", // Keep in sync with package.json
935+
936+
autoScalaLibrary := false,
937+
publishArtifact := false,
938+
includeFilter in unmanagedSources := NothingFilter | "*.ts" | "**.json",
939+
watchSources in Global ++= (unmanagedSources in Compile).value,
940+
compile in Compile := {
941+
val coursier = baseDirectory.value / "out/coursier"
942+
val packageJson = baseDirectory.value / "package.json"
943+
if (!coursier.exists || packageJson.lastModified > coursier.lastModified) {
944+
val exitCode = new java.lang.ProcessBuilder("npm", "run", "update-all")
945+
.directory(baseDirectory.value)
946+
.inheritIO()
947+
.start()
948+
.waitFor()
949+
if (exitCode != 0)
950+
throw new FeedbackProvidedException {
951+
override def toString = "'npm run update-all' in vscode-dotty failed"
952+
}
953+
}
954+
val tsc = baseDirectory.value / "node_modules" / ".bin" / "tsc"
955+
val exitCodeTsc = new java.lang.ProcessBuilder(tsc.getAbsolutePath, "--pretty", "--project", baseDirectory.value.getAbsolutePath)
956+
.inheritIO()
957+
.start()
958+
.waitFor()
959+
if (exitCodeTsc != 0)
960+
throw new FeedbackProvidedException {
961+
override def toString = "tsc in vscode-dotty failed"
962+
}
963+
964+
// Currently, vscode-dotty depends on daltonjorge.scala for syntax highlighting,
965+
// this is not automatically installed when starting the extension in development mode
966+
// (--extensionDevelopmentPath=...)
967+
val exitCodeInstall = new java.lang.ProcessBuilder("code", "--install-extension", "daltonjorge.scala")
968+
.inheritIO()
969+
.start()
970+
.waitFor()
971+
if (exitCodeInstall != 0)
972+
throw new FeedbackProvidedException {
973+
override def toString = "Installing dependency daltonjorge.scala failed"
974+
}
975+
976+
sbt.inc.Analysis.Empty
977+
},
978+
sbt.Keys.`package`:= {
979+
val exitCode = new java.lang.ProcessBuilder("vsce", "package")
980+
.directory(baseDirectory.value)
981+
.inheritIO()
982+
.start()
983+
.waitFor()
984+
if (exitCode != 0)
985+
throw new FeedbackProvidedException {
986+
override def toString = "vsce package failed"
987+
}
988+
989+
baseDirectory.value / s"dotty-${version.value}.vsix"
990+
},
991+
unpublish := {
992+
val exitCode = new java.lang.ProcessBuilder("vsce", "unpublish")
993+
.directory(baseDirectory.value)
994+
.inheritIO()
995+
.start()
996+
.waitFor()
997+
if (exitCode != 0)
998+
throw new FeedbackProvidedException {
999+
override def toString = "vsce unpublish failed"
1000+
}
1001+
},
1002+
publish := {
1003+
val exitCode = new java.lang.ProcessBuilder("vsce", "publish")
1004+
.directory(baseDirectory.value)
1005+
.inheritIO()
1006+
.start()
1007+
.waitFor()
1008+
if (exitCode != 0)
1009+
throw new FeedbackProvidedException {
1010+
override def toString = "vsce publish failed"
1011+
}
1012+
},
1013+
run := Def.inputTask {
1014+
val inputArgs = spaceDelimited("<arg>").parsed
1015+
val codeArgs = if (inputArgs.isEmpty) List((baseDirectory.value / "..").getAbsolutePath) else inputArgs
1016+
val extensionPath = baseDirectory.value.getAbsolutePath
1017+
val processArgs = List("code", s"--extensionDevelopmentPath=${extensionPath}") ++ codeArgs
1018+
1019+
val exitCode = new java.lang.ProcessBuilder(processArgs: _*)
1020+
.inheritIO()
1021+
.start()
1022+
.waitFor()
1023+
if (exitCode != 0)
1024+
throw new FeedbackProvidedException {
1025+
override def toString = "Running Visual Studio Code failed"
1026+
}
1027+
}.dependsOn(compile in Compile).evaluated
1028+
)
1029+
1030+
9121031
lazy val publishSettings = Seq(
9131032
publishMavenStyle := true,
9141033
isSnapshot := version.value.contains("SNAPSHOT"),

vscode-dotty/.vscodeignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
## This is used to exclude files from "vsce publish"
2+
target/**
3+
.vscode/**
4+
.vscode-test/**
5+
out/test/**
6+
test/**
7+
src/**
8+
**/*.map
9+
.gitignore
10+
tsconfig.json

vscode-dotty/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# IDE support for Dotty, the experimental Scala compiler
2+
3+
## Prerequisites
4+
To use this in your own Scala project, you must first get it to compile with
5+
Dotty, please follow the instructions at https://github.com/lampepfl/dotty-example-project
6+
7+
## Starting Visual Studio Code from sbt
8+
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.
10+
11+
If this is the case and your project succesfully compiles with dotty, you can
12+
simply use the `launchIDE` command provided by the sbt-dotty plugin:
13+
14+
```shell
15+
sbt launchIDE
16+
```
17+
18+
## More information
19+
20+
See http://dotty.epfl.ch/docs/usage/ide-support.html

0 commit comments

Comments
 (0)