Skip to content

Commit 5c34a3a

Browse files
committed
IDE: Initialize sbt project when there's none
1 parent 9d12693 commit 5c34a3a

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
@@ -985,11 +985,12 @@ object Build {
985985
includeFilter in unmanagedSources := NothingFilter | "*.ts" | "**.json",
986986
watchSources in Global ++= (unmanagedSources in Compile).value,
987987
resourceGenerators in Compile += Def.task {
988-
val defaultIDEConfig = baseDirectory.value / "out" / "default-dotty-ide-config"
989-
IO.write(defaultIDEConfig, dottyVersion)
988+
// Resources that will be copied when bootstrapping a new project
989+
val buildSbtFile = baseDirectory.value / "out" / "build.sbt"
990+
IO.write(buildSbtFile, s"""scalaVersion := "$dottyVersion"""")
990991
val dottyPluginSbtFile = baseDirectory.value / "out" / "dotty-plugin.sbt"
991992
IO.write(dottyPluginSbtFile, s"""addSbtPlugin("$dottyOrganization" % "$sbtDottyName" % "$sbtDottyVersion")""")
992-
Seq(defaultIDEConfig, dottyPluginSbtFile)
993+
Seq(buildSbtFile, dottyPluginSbtFile)
993994
},
994995
compile in Compile := Def.task {
995996
val workingDir = baseDirectory.value

vscode-dotty/src/extension.ts

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,31 @@ let extensionContext: ExtensionContext
1818
let outputChannel: vscode.OutputChannel
1919
export let client: LanguageClient
2020

21+
const sbtVersion = "1.2.3"
22+
const sbtArtifact = `org.scala-sbt:sbt-launch:${sbtVersion}`
23+
const workspaceRoot = `${vscode.workspace.rootPath}`
24+
const disableDottyIDEFile = path.join(workspaceRoot, ".dotty-ide-disabled")
25+
const sbtProjectDir = path.join(workspaceRoot, "project")
26+
const sbtPluginFile = path.join(sbtProjectDir, "dotty-plugin.sbt")
27+
const sbtBuildPropertiesFile = path.join(sbtProjectDir, "build.properties")
28+
const sbtBuildSbtFile = path.join(workspaceRoot, "build.sbt")
29+
const languageServerArtifactFile = path.join(workspaceRoot, ".dotty-ide-artifact")
30+
31+
function isUnconfiguredProject() {
32+
return !( fs.existsSync(disableDottyIDEFile)
33+
|| fs.existsSync(sbtPluginFile)
34+
|| fs.existsSync(sbtBuildPropertiesFile)
35+
|| fs.existsSync(sbtBuildSbtFile)
36+
)
37+
}
38+
2139
export function activate(context: ExtensionContext) {
2240
extensionContext = context
2341
outputChannel = vscode.window.createOutputChannel("Dotty");
2442

25-
const sbtArtifact = "org.scala-sbt:sbt-launch:1.2.3"
26-
const buildSbtFile = `${vscode.workspace.rootPath}/build.sbt`
27-
const dottyPluginSbtFile = path.join(extensionContext.extensionPath, './out/dotty-plugin.sbt')
28-
const disableDottyIDEFile = `${vscode.workspace.rootPath}/.dotty-ide-disabled`
29-
const languageServerArtifactFile = `${vscode.workspace.rootPath}/.dotty-ide-artifact`
30-
const languageServerDefaultConfigFile = path.join(extensionContext.extensionPath, './out/default-dotty-ide-config')
31-
const coursierPath = path.join(extensionContext.extensionPath, './out/coursier');
43+
const coursierPath = path.join(extensionContext.extensionPath, "out", "coursier");
44+
const dottyPluginSbtFileSource = path.join(extensionContext.extensionPath, "out", "dotty-plugin.sbt")
45+
const buildSbtFileSource = path.join(extensionContext.extensionPath, "out", "build.sbt")
3246

3347
vscode.workspace.onWillSaveTextDocument(worksheet.prepareWorksheet)
3448
vscode.workspace.onDidSaveTextDocument(document => {
@@ -43,15 +57,15 @@ export function activate(context: ExtensionContext) {
4357
})
4458

4559
if (process.env['DLS_DEV_MODE']) {
46-
const portFile = `${vscode.workspace.rootPath}/.dotty-ide-dev-port`
60+
const portFile = path.join(workspaceRoot, ".dotty-ide-dev-port")
4761
fs.readFile(portFile, (err, port) => {
4862
if (err) {
4963
outputChannel.appendLine(`Unable to parse ${portFile}`)
5064
throw err
5165
}
5266

5367
run({
54-
module: context.asAbsolutePath('out/src/passthrough-server.js'),
68+
module: context.asAbsolutePath(path.join("out", "src", "passthrough-server.js")),
5569
args: [ port.toString() ]
5670
}, false)
5771
})
@@ -61,20 +75,14 @@ export function activate(context: ExtensionContext) {
6175
// otherwise, try propose to start it if there's no build.sbt
6276
if (fs.existsSync(languageServerArtifactFile)) {
6377
runLanguageServer(coursierPath, languageServerArtifactFile)
64-
} else if (!fs.existsSync(disableDottyIDEFile) && !fs.existsSync(buildSbtFile)) {
78+
} else if (isUnconfiguredProject()) {
6579
vscode.window.showInformationMessage(
6680
"This looks like an unconfigured Scala project. Would you like to start the Dotty IDE?",
6781
"Yes", "No"
6882
).then(choice => {
6983
if (choice == "Yes") {
70-
fs.readFile(languageServerDefaultConfigFile, (err, data) => {
71-
if (err) throw err
72-
else {
73-
const languageServerScalaVersion = data.toString().trim()
74-
fetchAndConfigure(coursierPath, sbtArtifact, languageServerScalaVersion, dottyPluginSbtFile).then(() => {
75-
runLanguageServer(coursierPath, languageServerArtifactFile)
76-
})
77-
}
84+
fetchAndConfigure(coursierPath, sbtArtifact, buildSbtFileSource, dottyPluginSbtFileSource).then(() => {
85+
runLanguageServer(coursierPath, languageServerArtifactFile)
7886
})
7987
} else {
8088
fs.appendFile(disableDottyIDEFile, "", _ => {})
@@ -101,17 +109,17 @@ function runLanguageServer(coursierPath: string, languageServerArtifactFile: str
101109
})
102110
}
103111

104-
function fetchAndConfigure(coursierPath: string, sbtArtifact: string, languageServerScalaVersion: string, dottyPluginSbtFile: string) {
112+
function fetchAndConfigure(coursierPath: string, sbtArtifact: string, buildSbtFileSource: string, dottyPluginSbtFileSource: string) {
105113
return fetchWithCoursier(coursierPath, sbtArtifact).then((sbtClasspath) => {
106-
return configureIDE(sbtClasspath, languageServerScalaVersion, dottyPluginSbtFile)
114+
return configureIDE(sbtClasspath, buildSbtFileSource, dottyPluginSbtFileSource)
107115
})
108116
}
109117

110118
function fetchWithCoursier(coursierPath: string, artifact: string, extra: string[] = []) {
111119
return vscode.window.withProgress({
112120
location: vscode.ProgressLocation.Window,
113121
title: `Fetching ${ artifact }`
114-
}, (progress) => {
122+
}, _ => {
115123
const args = [
116124
"-jar", coursierPath,
117125
"fetch",
@@ -142,21 +150,27 @@ function fetchWithCoursier(coursierPath: string, artifact: string, extra: string
142150
})
143151
}
144152

145-
function configureIDE(sbtClasspath: string, languageServerScalaVersion: string, dottyPluginSbtFile: string) {
153+
function configureIDE(sbtClasspath: string,
154+
buildSbtFileSource: string,
155+
dottyPluginSbtFileSource: string) {
156+
146157
return vscode.window.withProgress({
147158
location: vscode.ProgressLocation.Window,
148159
title: 'Configuring the IDE for Dotty...'
149-
}, (progress) => {
160+
}, _ => {
161+
162+
// Bootstrap an sbt build
163+
fs.mkdirSync(sbtProjectDir)
164+
fs.appendFileSync(sbtBuildPropertiesFile, `sbt.version=${sbtVersion}`)
165+
fs.copyFileSync(buildSbtFileSource, sbtBuildSbtFile)
166+
fs.copyFileSync(dottyPluginSbtFileSource, path.join(sbtProjectDir, "plugins.sbt"))
150167

151-
// Run sbt to configure the IDE. If the `DottyPlugin` is not present, dynamically load it and
152-
// eventually run `configureIDE`.
168+
// Run sbt to configure the IDE.
153169
const sbtPromise =
154170
cpp.spawn("java", [
155171
"-Dsbt.log.noformat=true",
156172
"-classpath", sbtClasspath,
157173
"xsbt.boot.Boot",
158-
`--addPluginSbtFile=${dottyPluginSbtFile}`,
159-
`set every scalaVersion := "${languageServerScalaVersion}"`,
160174
"configureIDE"
161175
])
162176

@@ -182,7 +196,7 @@ function configureIDE(sbtClasspath: string, languageServerScalaVersion: string,
182196
}
183197
})
184198

185-
return sbtPromise
199+
return sbtPromise
186200
})
187201
}
188202

0 commit comments

Comments
 (0)