@@ -20,26 +20,83 @@ import { NotificationCenter } from '../notification-center';
20
20
import { SketchContribution , URI } from './contribution' ;
21
21
import { BoardsDataStore } from '../boards/boards-data-store' ;
22
22
23
+ interface DaemonAddress {
24
+ /**
25
+ * The host where the Arduino CLI daemon is available.
26
+ */
27
+ readonly hostname : string ;
28
+ /**
29
+ * The port where the Arduino CLI daemon is listening.
30
+ */
31
+ readonly port : number ;
32
+ /**
33
+ * The [id](https://arduino.github.io/arduino-cli/latest/rpc/commands/#instance) of the initialized core Arduino client instance.
34
+ */
35
+ readonly instance : number ;
36
+ }
37
+
38
+ interface StartLanguageServerParams {
39
+ /**
40
+ * Absolute filesystem path to the Arduino Language Server executable.
41
+ */
42
+ readonly lsPath : string ;
43
+ /**
44
+ * The hostname and the port for the gRPC channel connecting to the Arduino CLI daemon.
45
+ * The `instance` number is for the initialized core Arduino client.
46
+ */
47
+ readonly daemonAddress : DaemonAddress ;
48
+ /**
49
+ * Absolute filesystem path to [`clangd`](https://clangd.llvm.org/).
50
+ */
51
+ readonly clangdPath : string ;
52
+ /**
53
+ * The board is relevant to start a specific "flavor" of the language.
54
+ */
55
+ readonly board : { fqbn : string ; name ?: string } ;
56
+ /**
57
+ * `true` if the LS should generate the log files into the default location. The default location is the `cwd` of the process.
58
+ * It's very often the same as the workspace root of the IDE, aka the sketch folder.
59
+ * When it is a string, it is the absolute filesystem path to the folder to generate the log files.
60
+ * If `string`, but the path is inaccessible, the log files will be generated into the default location.
61
+ */
62
+ readonly log ?: boolean | string ;
63
+ /**
64
+ * Optional `env` for the language server process.
65
+ */
66
+ readonly env ?: NodeJS . ProcessEnv ;
67
+ /**
68
+ * Additional flags for the Arduino Language server process.
69
+ */
70
+ readonly flags ?: readonly string [ ] ;
71
+ /**
72
+ * Set to `true`, to enable `Diagnostics`.
73
+ */
74
+ readonly realTimeDiagnostics ?: boolean ;
75
+ /**
76
+ * If `true`, the logging is not forwarded to the _Output_ view via the language client.
77
+ */
78
+ readonly silentOutput ?: boolean ;
79
+ }
80
+
81
+ /**
82
+ * The FQBN the language server runs with or `undefined` if it could not start.
83
+ */
84
+ type StartLanguageServerResult = string | undefined ;
85
+
23
86
@injectable ( )
24
87
export class InoLanguage extends SketchContribution {
25
88
@inject ( HostedPluginEvents )
26
89
private readonly hostedPluginEvents : HostedPluginEvents ;
27
-
28
90
@inject ( ExecutableService )
29
91
private readonly executableService : ExecutableService ;
30
-
31
92
@inject ( ArduinoDaemon )
32
93
private readonly daemon : ArduinoDaemon ;
33
-
34
94
@inject ( BoardsService )
35
95
private readonly boardsService : BoardsService ;
36
-
37
96
@inject ( BoardsServiceProvider )
38
97
private readonly boardsServiceProvider : BoardsServiceProvider ;
39
-
40
98
@inject ( NotificationCenter )
41
99
private readonly notificationCenter : NotificationCenter ;
42
-
43
100
@inject ( BoardsDataStore )
44
101
private readonly boardDataStore : BoardsDataStore ;
45
102
@@ -129,6 +186,10 @@ export class InoLanguage extends SketchContribution {
129
186
if ( ! port ) {
130
187
return ;
131
188
}
189
+ const portNumber = Number . parseInt ( port , 10 ) ; // TODO: IDE2 APIs should provide a number and not string
190
+ if ( Number . isNaN ( portNumber ) ) {
191
+ return ;
192
+ }
132
193
const release = await this . languageServerStartMutex . acquire ( ) ;
133
194
const toDisposeOnRelease = new DisposableCollection ( ) ;
134
195
try {
@@ -197,22 +258,22 @@ export class InoLanguage extends SketchContribution {
197
258
) ;
198
259
toDisposeOnRelease . push ( Disposable . create ( ( ) => clearTimeout ( timer ) ) ) ;
199
260
} ) ,
200
- this . commandService . executeCommand < string > (
201
- 'arduino.languageserver.start' ,
202
- {
203
- lsPath ,
204
- cliDaemonAddr : `localhost: ${ port } ` ,
205
- clangdPath ,
206
- log : currentSketchPath ? currentSketchPath : log ,
207
- cliDaemonInstance : '1' ,
208
- board : {
209
- fqbn : fqbnWithConfig ,
210
- name : name ? `" ${ name } "` : undefined ,
211
- } ,
212
- realTimeDiagnostics ,
213
- silentOutput : true ,
214
- }
215
- ) ,
261
+ this . start ( {
262
+ lsPath ,
263
+ daemonAddress : {
264
+ hostname : 'localhost' ,
265
+ port : portNumber ,
266
+ instance : 1 , // TODO: get it from the backend
267
+ } ,
268
+ clangdPath ,
269
+ log : currentSketchPath ? currentSketchPath : log ,
270
+ board : {
271
+ fqbn : fqbnWithConfig ,
272
+ name ,
273
+ } ,
274
+ realTimeDiagnostics ,
275
+ silentOutput : true ,
276
+ } ) ,
216
277
] ) ;
217
278
} catch ( e ) {
218
279
console . log ( `Failed to start language server. Original FQBN: ${ fqbn } ` , e ) ;
@@ -222,4 +283,13 @@ export class InoLanguage extends SketchContribution {
222
283
release ( ) ;
223
284
}
224
285
}
286
+
287
+ private async start (
288
+ params : StartLanguageServerParams
289
+ ) : Promise < StartLanguageServerResult | undefined > {
290
+ return this . commandService . executeCommand < StartLanguageServerResult > (
291
+ 'arduino.languageserver.start' ,
292
+ params
293
+ ) ;
294
+ }
225
295
}
0 commit comments