@@ -17,46 +17,67 @@ export function activate(context: ExtensionContext) {
1717 outputChannel = vscode . window . createOutputChannel ( 'Dotty Language Client' ) ;
1818
1919 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"
2220 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+ } )
3251 }
52+ } )
53+ } else {
54+ runLanguageServer ( coursierPath , languageServerArtifactFile )
55+ }
56+ }
57+ }
3358
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 ) => {
3465 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" ]
3768 } )
3869 } )
39- } else {
40- fetchAndRun ( sbtArtifact , languageServerArtifact , loadPluginArtifact )
4170 }
4271 } )
4372}
4473
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 ) {
4875 const sbtPromise = fetchWithCoursier ( coursierPath , sbtArtifact )
49- const languageServerPromise = fetchWithCoursier ( coursierPath , languageServerArtifact )
5076 const loadPluginPromise = fetchWithCoursier ( coursierPath , loadPluginArtifact )
5177
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 )
6081 } )
6182
6283}
@@ -72,7 +93,6 @@ function fetchWithCoursier(coursierPath: string, artifact: string, extra: string
7293 "-p" ,
7394 artifact
7495 ] . concat ( extra )
75-
7696 const coursierPromise = cpp . spawn ( "java" , args )
7797 const coursierProc = coursierPromise . childProcess
7898
@@ -82,7 +102,7 @@ function fetchWithCoursier(coursierPath: string, artifact: string, extra: string
82102 classPath += data . toString ( ) . trim ( )
83103 } )
84104 coursierProc . stderr . on ( 'data' , ( data : Buffer ) => {
85- let msg = data . toString ( )
105+ let msg = data . toString ( ) . trim ( )
86106 outputChannel . append ( msg )
87107 } )
88108
@@ -93,24 +113,25 @@ function fetchWithCoursier(coursierPath: string, artifact: string, extra: string
93113 throw new Error ( msg )
94114 }
95115 } )
96- return coursierPromise . then ( ( ) => {
97- return classPath ;
98- } ) ;
116+ return coursierPromise . then ( ( ) => { return classPath } )
99117 } )
100118}
101119
102- function configureIDE ( sbtClasspath : string , languageServerClasspath : string , loadPluginJar : string ) {
120+ function configureIDE ( sbtClasspath : string , languageServerScalaVersion : string , sbtDottyVersion : string , loadPluginJar : string ) {
103121 return vscode . window . withProgress ( {
104122 location : vscode . ProgressLocation . Window ,
105123 title : 'Configuring IDE...'
106124 } , ( progress ) => {
107125 const applyLoadPlugin = `apply -cp ${ loadPluginJar } ch.epfl.scala.loadplugin.LoadPlugin`
108126 const ifAbsentCommands = [
109127 "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\""
113131 ] . join ( " " )
132+
133+ // Run sbt to configure the IDE. If the `DottyPlugin` is not present, dynamically load it and
134+ // eventually run `configureIDE`.
114135 const sbtPromise =
115136 cpp . spawn ( "java" , [
116137 "-classpath" , sbtClasspath ,
@@ -129,7 +150,7 @@ function configureIDE(sbtClasspath: string, languageServerClasspath: string, loa
129150 }
130151 } )
131152
132- return sbtPromise . then ( ( ) => { return languageServerClasspath } ) ;
153+ return sbtPromise
133154 } )
134155}
135156
0 commit comments