Skip to content

Commit 90a4284

Browse files
committed
IDE: Initialize sbt project when there's none
1 parent 999d1cb commit 90a4284

File tree

2 files changed

+46
-31
lines changed

2 files changed

+46
-31
lines changed

project/Build.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -977,11 +977,12 @@ object Build {
977977
includeFilter in unmanagedSources := NothingFilter | "*.ts" | "**.json",
978978
watchSources in Global ++= (unmanagedSources in Compile).value,
979979
resourceGenerators in Compile += Def.task {
980-
val defaultIDEConfig = baseDirectory.value / "out" / "default-dotty-ide-config"
981-
IO.write(defaultIDEConfig, dottyVersion)
980+
// Resources that will be copied when bootstrapping a new project
981+
val buildSbtFile = baseDirectory.value / "out" / "build.sbt"
982+
IO.write(buildSbtFile, s"""scalaVersion := "$dottyVersion"""")
982983
val dottyPluginSbtFile = baseDirectory.value / "out" / "dotty-plugin.sbt"
983984
IO.write(dottyPluginSbtFile, s"""addSbtPlugin("$dottyOrganization" % "$sbtDottyName" % "$sbtDottyVersion")""")
984-
Seq(defaultIDEConfig, dottyPluginSbtFile)
985+
Seq(buildSbtFile, dottyPluginSbtFile)
985986
},
986987
compile in Compile := Def.task {
987988
val workingDir = baseDirectory.value

vscode-dotty/src/extension.ts

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,42 @@ import { LanguageClient, LanguageClientOptions, RevealOutputChannelOn,
1313
let extensionContext: ExtensionContext
1414
let outputChannel: vscode.OutputChannel
1515

16+
const sbtVersion = "1.2.3"
17+
const sbtArtifact = `org.scala-sbt:sbt-launch:${sbtVersion}`
18+
const workspaceRoot = `${vscode.workspace.rootPath}`
19+
const disableDottyIDEFile = path.join(workspaceRoot, ".dotty-ide-disabled")
20+
const sbtProjectDir = path.join(workspaceRoot, "project")
21+
const sbtPluginFile = path.join(sbtProjectDir, "dotty-plugin.sbt")
22+
const sbtBuildPropertiesFile = path.join(sbtProjectDir, "build.properties")
23+
const sbtBuildSbtFile = path.join(workspaceRoot, "build.sbt")
24+
const languageServerArtifactFile = path.join(workspaceRoot, ".dotty-ide-artifact")
25+
26+
function isUnconfiguredProject() {
27+
return !( fs.existsSync(disableDottyIDEFile)
28+
|| fs.existsSync(sbtPluginFile)
29+
|| fs.existsSync(sbtBuildPropertiesFile)
30+
|| fs.existsSync(sbtBuildSbtFile)
31+
)
32+
}
33+
1634
export function activate(context: ExtensionContext) {
1735
extensionContext = context
1836
outputChannel = vscode.window.createOutputChannel('Dotty Language Client');
1937

20-
const sbtArtifact = "org.scala-sbt:sbt-launch:1.2.3"
21-
const buildSbtFile = `${vscode.workspace.rootPath}/build.sbt`
22-
const dottyPluginSbtFile = path.join(extensionContext.extensionPath, './out/dotty-plugin.sbt')
23-
const disableDottyIDEFile = `${vscode.workspace.rootPath}/.dotty-ide-disabled`
24-
const languageServerArtifactFile = `${vscode.workspace.rootPath}/.dotty-ide-artifact`
25-
const languageServerDefaultConfigFile = path.join(extensionContext.extensionPath, './out/default-dotty-ide-config')
26-
const coursierPath = path.join(extensionContext.extensionPath, './out/coursier');
38+
const coursierPath = path.join(extensionContext.extensionPath, "out", "coursier");
39+
const dottyPluginSbtFileSource = path.join(extensionContext.extensionPath, "out", "dotty-plugin.sbt")
40+
const buildSbtFileSource = path.join(extensionContext.extensionPath, "out", "build.sbt")
2741

2842
if (process.env['DLS_DEV_MODE']) {
29-
const portFile = `${vscode.workspace.rootPath}/.dotty-ide-dev-port`
43+
const portFile = path.join(workspaceRoot, ".dotty-ide-dev-port")
3044
fs.readFile(portFile, (err, port) => {
3145
if (err) {
3246
outputChannel.append(`Unable to parse ${portFile}`)
3347
throw err
3448
}
3549

3650
run({
37-
module: context.asAbsolutePath('out/src/passthrough-server.js'),
51+
module: context.asAbsolutePath(path.join("out", "src", "passthrough-server.js")),
3852
args: [ port.toString() ]
3953
})
4054
})
@@ -44,20 +58,14 @@ export function activate(context: ExtensionContext) {
4458
// otherwise, try propose to start it if there's no build.sbt
4559
if (fs.existsSync(languageServerArtifactFile)) {
4660
runLanguageServer(coursierPath, languageServerArtifactFile)
47-
} else if (!fs.existsSync(disableDottyIDEFile) && !fs.existsSync(buildSbtFile)) {
61+
} else if (isUnconfiguredProject()) {
4862
vscode.window.showInformationMessage(
4963
"This looks like an unconfigured Scala project. Would you like to start the Dotty IDE?",
5064
"Yes", "No"
5165
).then(choice => {
5266
if (choice == "Yes") {
53-
fs.readFile(languageServerDefaultConfigFile, (err, data) => {
54-
if (err) throw err
55-
else {
56-
const languageServerScalaVersion = data.toString().trim()
57-
fetchAndConfigure(coursierPath, sbtArtifact, languageServerScalaVersion, dottyPluginSbtFile).then(() => {
58-
runLanguageServer(coursierPath, languageServerArtifactFile)
59-
})
60-
}
67+
fetchAndConfigure(coursierPath, sbtArtifact, buildSbtFileSource, dottyPluginSbtFileSource).then(() => {
68+
runLanguageServer(coursierPath, languageServerArtifactFile)
6169
})
6270
} else {
6371
fs.appendFile(disableDottyIDEFile, "", _ => {})
@@ -82,17 +90,17 @@ function runLanguageServer(coursierPath: string, languageServerArtifactFile: str
8290
})
8391
}
8492

85-
function fetchAndConfigure(coursierPath: string, sbtArtifact: string, languageServerScalaVersion: string, dottyPluginSbtFile: string) {
93+
function fetchAndConfigure(coursierPath: string, sbtArtifact: string, buildSbtFileSource: string, dottyPluginSbtFileSource: string) {
8694
return fetchWithCoursier(coursierPath, sbtArtifact).then((sbtClasspath) => {
87-
return configureIDE(sbtClasspath, languageServerScalaVersion, dottyPluginSbtFile)
95+
return configureIDE(sbtClasspath, buildSbtFileSource, dottyPluginSbtFileSource)
8896
})
8997
}
9098

9199
function fetchWithCoursier(coursierPath: string, artifact: string, extra: string[] = []) {
92100
return vscode.window.withProgress({
93101
location: vscode.ProgressLocation.Window,
94102
title: `Fetching ${ artifact }`
95-
}, (progress) => {
103+
}, _ => {
96104
const args = [
97105
"-jar", coursierPath,
98106
"fetch",
@@ -119,20 +127,26 @@ function fetchWithCoursier(coursierPath: string, artifact: string, extra: string
119127
})
120128
}
121129

122-
function configureIDE(sbtClasspath: string, languageServerScalaVersion: string, dottyPluginSbtFile: string) {
130+
function configureIDE(sbtClasspath: string,
131+
buildSbtFileSource: string,
132+
dottyPluginSbtFileSource: string) {
133+
123134
return vscode.window.withProgress({
124135
location: vscode.ProgressLocation.Window,
125136
title: 'Configuring the IDE for Dotty...'
126-
}, (progress) => {
137+
}, _ => {
138+
139+
// Bootstrap an sbt build
140+
fs.mkdirSync(sbtProjectDir)
141+
fs.appendFileSync(sbtBuildPropertiesFile, `sbt.version=${sbtVersion}`)
142+
fs.copyFileSync(buildSbtFileSource, sbtBuildSbtFile)
143+
fs.copyFileSync(dottyPluginSbtFileSource, path.join(sbtProjectDir, "plugins.sbt"))
127144

128-
// Run sbt to configure the IDE. If the `DottyPlugin` is not present, dynamically load it and
129-
// eventually run `configureIDE`.
145+
// Run sbt to configure the IDE.
130146
const sbtPromise =
131147
cpp.spawn("java", [
132148
"-classpath", sbtClasspath,
133149
"xsbt.boot.Boot",
134-
`--addPluginSbtFile=${dottyPluginSbtFile}`,
135-
`set every scalaVersion := "${languageServerScalaVersion}"`,
136150
"configureIDE"
137151
])
138152

@@ -145,7 +159,7 @@ function configureIDE(sbtClasspath: string, languageServerScalaVersion: string,
145159
}
146160
})
147161

148-
return sbtPromise
162+
return sbtPromise
149163
})
150164
}
151165

0 commit comments

Comments
 (0)