@@ -17,46 +17,67 @@ export function activate(context: ExtensionContext) {
17
17
outputChannel = vscode . window . createOutputChannel ( 'Dotty Language Client' ) ;
18
18
19
19
const sbtArtifact = "org.scala-sbt:sbt-launch:1.1.4"
20
- const languageServerArtifactFile = `${ vscode . workspace . rootPath } /.dotty-ide-artifact`
21
- const languageServerDefaultArtifact = "ch.epfl.lamp:dotty-language-server_0.8:0.8.0-RC1"
22
20
const loadPluginArtifact = "ch.epfl.scala:load-plugin_2.12:0.1.0+2-496ac670"
23
- fs . readFile ( languageServerArtifactFile , ( err , data ) => {
24
- const languageServerArtifact = err ? languageServerDefaultArtifact : data . toString ( ) . trim ( )
25
-
26
- if ( process . env [ 'DLS_DEV_MODE' ] ) {
27
- const portFile = `${ vscode . workspace . rootPath } /.dotty-ide-dev-port`
28
- fs . readFile ( portFile , ( err , port ) => {
29
- if ( err ) {
30
- outputChannel . append ( `Unable to parse ${ portFile } ` )
31
- throw err
21
+ const languageServerArtifactFile = `${ vscode . workspace . rootPath } /.dotty-ide-artifact`
22
+ const languageServerDefaultConfigFile = path . join ( extensionContext . extensionPath , './out/default-dotty-ide-config' )
23
+ const coursierPath = path . join ( extensionContext . extensionPath , './out/coursier' ) ;
24
+
25
+ if ( process . env [ 'DLS_DEV_MODE' ] ) {
26
+ const portFile = `${ vscode . workspace . rootPath } /.dotty-ide-dev-port`
27
+ fs . readFile ( portFile , ( err , port ) => {
28
+ if ( err ) {
29
+ outputChannel . append ( `Unable to parse ${ portFile } ` )
30
+ throw err
31
+ }
32
+
33
+ run ( {
34
+ module : context . asAbsolutePath ( 'out/src/passthrough-server.js' ) ,
35
+ args : [ port . toString ( ) ]
36
+ } )
37
+ } )
38
+
39
+ } else {
40
+
41
+ // Check whether `.dotty-ide-artifact` exists to know whether the IDE has been already
42
+ // configured (via `configureIDE` for instance). If not, start sbt and run `configureIDE`.
43
+ if ( ! fs . existsSync ( languageServerArtifactFile ) ) {
44
+ fs . readFile ( languageServerDefaultConfigFile , ( err , data ) => {
45
+ if ( err ) throw err
46
+ else {
47
+ const [ languageServerScalaVersion , sbtDottyVersion ] = data . toString ( ) . trim ( ) . split ( / \r ? \n / )
48
+ fetchAndConfigure ( coursierPath , sbtArtifact , languageServerScalaVersion , sbtDottyVersion , loadPluginArtifact ) . then ( ( ) => {
49
+ runLanguageServer ( coursierPath , languageServerArtifactFile )
50
+ } )
32
51
}
52
+ } )
53
+ } else {
54
+ runLanguageServer ( coursierPath , languageServerArtifactFile )
55
+ }
56
+ }
57
+ }
33
58
59
+ function runLanguageServer ( coursierPath : string , languageServerArtifactFile : string ) {
60
+ fs . readFile ( languageServerArtifactFile , ( err , data ) => {
61
+ if ( err ) throw err
62
+ else {
63
+ const languageServerArtifact = data . toString ( ) . trim ( )
64
+ fetchWithCoursier ( coursierPath , languageServerArtifact ) . then ( ( languageServerClasspath ) => {
34
65
run ( {
35
- module : context . asAbsolutePath ( 'out/src/passthrough-server.js' ) ,
36
- args : [ port . toString ( ) ]
66
+ command : "java" ,
67
+ args : [ "-classpath" , languageServerClasspath , "dotty.tools.languageserver.Main" , "-stdio" ]
37
68
} )
38
69
} )
39
- } else {
40
- fetchAndRun ( sbtArtifact , languageServerArtifact , loadPluginArtifact )
41
70
}
42
71
} )
43
72
}
44
73
45
- function fetchAndRun ( sbtArtifact : string , languageServerArtifact : string , loadPluginArtifact : string ) {
46
- const coursierPath = path . join ( extensionContext . extensionPath , './out/coursier' ) ;
47
-
74
+ function fetchAndConfigure ( coursierPath : string , sbtArtifact : string , languageServerScalaVersion : string , sbtDottyVersion : string , loadPluginArtifact : string ) {
48
75
const sbtPromise = fetchWithCoursier ( coursierPath , sbtArtifact )
49
- const languageServerPromise = fetchWithCoursier ( coursierPath , languageServerArtifact )
50
76
const loadPluginPromise = fetchWithCoursier ( coursierPath , loadPluginArtifact )
51
77
52
- Promise . all ( [ sbtPromise , languageServerPromise , loadPluginPromise ] ) . then ( ( results ) => {
53
- const [ sbtClasspath , languageServerClasspath , loadPluginJar ] = results
54
- return configureIDE ( sbtClasspath , languageServerClasspath , loadPluginJar )
55
- } ) . then ( ( languageServerClasspath ) => {
56
- run ( {
57
- command : "java" ,
58
- args : [ "-classpath" , languageServerClasspath , "dotty.tools.languageserver.Main" , "-stdio" ]
59
- } )
78
+ return Promise . all ( [ sbtPromise , loadPluginPromise ] ) . then ( ( results ) => {
79
+ const [ sbtClasspath , loadPluginJar ] = results
80
+ return configureIDE ( sbtClasspath , languageServerScalaVersion , sbtDottyVersion , loadPluginJar )
60
81
} )
61
82
62
83
}
@@ -72,7 +93,6 @@ function fetchWithCoursier(coursierPath: string, artifact: string, extra: string
72
93
"-p" ,
73
94
artifact
74
95
] . concat ( extra )
75
-
76
96
const coursierPromise = cpp . spawn ( "java" , args )
77
97
const coursierProc = coursierPromise . childProcess
78
98
@@ -82,7 +102,7 @@ function fetchWithCoursier(coursierPath: string, artifact: string, extra: string
82
102
classPath += data . toString ( ) . trim ( )
83
103
} )
84
104
coursierProc . stderr . on ( 'data' , ( data : Buffer ) => {
85
- let msg = data . toString ( )
105
+ let msg = data . toString ( ) . trim ( )
86
106
outputChannel . append ( msg )
87
107
} )
88
108
@@ -93,24 +113,25 @@ function fetchWithCoursier(coursierPath: string, artifact: string, extra: string
93
113
throw new Error ( msg )
94
114
}
95
115
} )
96
- return coursierPromise . then ( ( ) => {
97
- return classPath ;
98
- } ) ;
116
+ return coursierPromise . then ( ( ) => { return classPath } )
99
117
} )
100
118
}
101
119
102
- function configureIDE ( sbtClasspath : string , languageServerClasspath : string , loadPluginJar : string ) {
120
+ function configureIDE ( sbtClasspath : string , languageServerScalaVersion : string , sbtDottyVersion : string , loadPluginJar : string ) {
103
121
return vscode . window . withProgress ( {
104
122
location : vscode . ProgressLocation . Window ,
105
123
title : 'Configuring IDE...'
106
124
} , ( progress ) => {
107
125
const applyLoadPlugin = `apply -cp ${ loadPluginJar } ch.epfl.scala.loadplugin.LoadPlugin`
108
126
const ifAbsentCommands = [
109
127
"if-absent dotty.tools.sbtplugin.DottyPlugin" ,
110
- "\"set every scalaVersion := \\\"0.8.0-RC1 \\\"\"" ,
111
- "\"load-plugin ch.epfl.lamp:sbt-dotty:0.2.2 dotty.tools.sbtplugin.DottyPlugin\"" ,
112
- "\"load-plugin ch.epfl.lamp:sbt-dotty:0.2.2 dotty.tools.sbtplugin.DottyIDEPlugin\""
128
+ "\"set every scalaVersion := \\\"" + languageServerScalaVersion + " \\\"\"",
129
+ "\"load-plugin ch.epfl.lamp:sbt-dotty:" + sbtDottyVersion + " dotty.tools.sbtplugin.DottyPlugin\"",
130
+ "\"load-plugin ch.epfl.lamp:sbt-dotty:" + sbtDottyVersion + " dotty.tools.sbtplugin.DottyIDEPlugin\""
113
131
] . join ( " " )
132
+
133
+ // Run sbt to configure the IDE. If the `DottyPlugin` is not present, dynamically load it and
134
+ // eventually run `configureIDE`.
114
135
const sbtPromise =
115
136
cpp . spawn ( "java" , [
116
137
"-classpath" , sbtClasspath ,
@@ -129,7 +150,7 @@ function configureIDE(sbtClasspath: string, languageServerClasspath: string, loa
129
150
}
130
151
} )
131
152
132
- return sbtPromise . then ( ( ) => { return languageServerClasspath } ) ;
153
+ return sbtPromise
133
154
} )
134
155
}
135
156
0 commit comments