@@ -4,8 +4,8 @@ import * as v from "vscode-languageserver";
4
4
import * as rpc from "vscode-jsonrpc/node" ;
5
5
import * as path from "path" ;
6
6
import fs from "fs" ;
7
- // TODO: check DidChangeWatchedFilesNotification.
8
7
import {
8
+ DidChangeWatchedFilesNotification ,
9
9
DidOpenTextDocumentNotification ,
10
10
DidChangeTextDocumentNotification ,
11
11
DidCloseTextDocumentNotification ,
@@ -14,6 +14,7 @@ import {
14
14
InlayHintParams ,
15
15
CodeLensParams ,
16
16
SignatureHelpParams ,
17
+ InitializedNotification ,
17
18
} from "vscode-languageserver-protocol" ;
18
19
import * as lookup from "./lookup" ;
19
20
import * as utils from "./utils" ;
@@ -27,6 +28,10 @@ import * as ic from "./incrementalCompilation";
27
28
import config , { extensionConfiguration } from "./config" ;
28
29
import { projectsFiles } from "./projectFiles" ;
29
30
31
+ // Absolute paths to all the workspace folders
32
+ // Configured during the initialize request
33
+ const workspaceFolders = new Set < string > ( ) ;
34
+
30
35
// This holds client capabilities specific to our extension, and not necessarily
31
36
// related to the LS protocol. It's for enabling/disabling features that might
32
37
// work in one client, like VSCode, but perhaps not in others, like vim.
@@ -208,21 +213,18 @@ let deleteProjectConfigCache = (rootPath: string) => {
208
213
}
209
214
} ;
210
215
211
- let compilerLogsWatcher = chokidar
212
- . watch ( [ ] , {
213
- awaitWriteFinish : {
214
- stabilityThreshold : 1 ,
215
- } ,
216
- } )
217
- . on ( "all" , ( _e , changedPath ) => {
218
- if ( changedPath . includes ( "build.ninja" ) ) {
216
+ function onWorkspaceDidChangeWatchedFiles (
217
+ params : p . DidChangeWatchedFilesParams
218
+ ) {
219
+ params . changes . forEach ( ( change ) => {
220
+ if ( change . uri . includes ( "build.ninja" ) ) {
219
221
if ( config . extensionConfiguration . cache ?. projectConfig ?. enable === true ) {
220
- let projectRoot = utils . findProjectRootOfFile ( changedPath ) ;
222
+ let projectRoot = utils . findProjectRootOfFile ( change . uri ) ;
221
223
if ( projectRoot != null ) {
222
224
syncProjectConfigCache ( projectRoot ) ;
223
225
}
224
226
}
225
- } else {
227
+ } else if ( change . uri . includes ( "compiler.log" ) ) {
226
228
try {
227
229
sendUpdatedDiagnostics ( ) ;
228
230
sendCompilationFinishedMessage ( ) ;
@@ -235,13 +237,11 @@ let compilerLogsWatcher = chokidar
235
237
} catch {
236
238
console . log ( "Error while sending updated diagnostics" ) ;
237
239
}
240
+ } else {
241
+ ic . incrementalCompilationFileChanged ( fileURLToPath ( change . uri ) ) ;
238
242
}
239
243
} ) ;
240
-
241
- let stopWatchingCompilerLog = ( ) => {
242
- // TODO: cleanup of compilerLogs?
243
- compilerLogsWatcher . close ( ) ;
244
- } ;
244
+ }
245
245
246
246
type clientSentBuildAction = {
247
247
title : string ;
@@ -279,15 +279,6 @@ let openedFile = (fileUri: string, fileContent: string) => {
279
279
: false ,
280
280
} ;
281
281
projectsFiles . set ( projectRootPath , projectRootState ) ;
282
- compilerLogsWatcher . add (
283
- path . join ( projectRootPath , c . compilerLogPartialPath )
284
- ) ;
285
- if ( config . extensionConfiguration . cache ?. projectConfig ?. enable === true ) {
286
- compilerLogsWatcher . add (
287
- path . join ( projectRootPath , c . buildNinjaPartialPath )
288
- ) ;
289
- syncProjectConfigCache ( projectRootPath ) ;
290
- }
291
282
}
292
283
let root = projectsFiles . get ( projectRootPath ) ! ;
293
284
root . openFiles . add ( filePath ) ;
@@ -363,12 +354,6 @@ let closedFile = (fileUri: string) => {
363
354
root . openFiles . delete ( filePath ) ;
364
355
// clear diagnostics too if no open files open in said project
365
356
if ( root . openFiles . size === 0 ) {
366
- compilerLogsWatcher . unwatch (
367
- path . join ( projectRootPath , c . compilerLogPartialPath )
368
- ) ;
369
- compilerLogsWatcher . unwatch (
370
- path . join ( projectRootPath , c . buildNinjaPartialPath )
371
- ) ;
372
357
deleteProjectConfigCache ( projectRootPath ) ;
373
358
deleteProjectDiagnostics ( projectRootPath ) ;
374
359
if ( root . bsbWatcherByEditor !== null ) {
@@ -1050,7 +1035,7 @@ function onMessage(msg: p.Message) {
1050
1035
} else {
1051
1036
process . exit ( 1 ) ;
1052
1037
}
1053
- } else if ( msg . method === "initialized" ) {
1038
+ } else if ( msg . method === InitializedNotification . method ) {
1054
1039
/*
1055
1040
The initialized notification is sent from the client to the server after the client received the result of the initialize request
1056
1041
but before the client is sending any other request or notification to the server.
@@ -1059,27 +1044,32 @@ function onMessage(msg: p.Message) {
1059
1044
We use this to register the file watchers for the project.
1060
1045
The client can watch files for us and send us events via the `workspace/didChangeWatchedFiles`
1061
1046
*/
1062
- const watchers =
1063
- Array . from ( projectsFiles . keys ( ) ) . flatMap ( projectRootPath => [
1047
+ const watchers = Array . from ( workspaceFolders ) . flatMap (
1048
+ ( projectRootPath ) => [
1064
1049
{
1065
1050
globPattern : path . join ( projectRootPath , c . compilerLogPartialPath ) ,
1066
- kind : p . WatchKind . Change | p . WatchKind . Create ,
1051
+ kind : p . WatchKind . Change | p . WatchKind . Create | p . WatchKind . Delete ,
1067
1052
} ,
1068
1053
{
1069
1054
globPattern : path . join ( projectRootPath , c . buildNinjaPartialPath ) ,
1070
- kind : p . WatchKind . Change | p . WatchKind . Create ,
1055
+ kind : p . WatchKind . Change | p . WatchKind . Create | p . WatchKind . Delete ,
1071
1056
} ,
1072
- ] )
1073
- const registrationParams : p . RegistrationParams = {
1074
- registrations :[
1075
1057
{
1076
- id : "rescript_file_watcher" ,
1077
- method : p . DidChangeWatchedFilesNotification . method ,
1078
- registerOptions : {
1079
- watchers
1080
- }
1058
+ globPattern : `${ path . join ( projectRootPath , c . compilerDirPartialPath ) } /**/*.{cmt,cmi}` ,
1059
+ kind : p . WatchKind . Change | p . WatchKind . Delete ,
1081
1060
}
1082
1061
]
1062
+ ) ;
1063
+ const registrationParams : p . RegistrationParams = {
1064
+ registrations : [
1065
+ {
1066
+ id : "rescript_file_watcher" ,
1067
+ method : DidChangeWatchedFilesNotification . method ,
1068
+ registerOptions : {
1069
+ watchers,
1070
+ } ,
1071
+ } ,
1072
+ ] ,
1083
1073
} ;
1084
1074
const req : p . RequestMessage = {
1085
1075
jsonrpc : c . jsonrpcVersion ,
@@ -1088,6 +1078,9 @@ function onMessage(msg: p.Message) {
1088
1078
params : registrationParams ,
1089
1079
} ;
1090
1080
send ( req ) ;
1081
+ } else if ( msg . method === DidChangeWatchedFilesNotification . method ) {
1082
+ const params = msg . params as p . DidChangeWatchedFilesParams ;
1083
+ onWorkspaceDidChangeWatchedFiles ( params ) ;
1091
1084
} else if ( msg . method === DidOpenTextDocumentNotification . method ) {
1092
1085
let params = msg . params as p . DidOpenTextDocumentParams ;
1093
1086
openedFile ( params . textDocument . uri , params . textDocument . text ) ;
@@ -1133,6 +1126,10 @@ function onMessage(msg: p.Message) {
1133
1126
} else if ( msg . method === "initialize" ) {
1134
1127
// Save initial configuration, if present
1135
1128
let initParams = msg . params as InitializeParams ;
1129
+ for ( const workspaceFolder of initParams . workspaceFolders || [ ] ) {
1130
+ const workspaceRootPath = fileURLToPath ( workspaceFolder . uri ) ;
1131
+ workspaceFolders . add ( workspaceRootPath ) ;
1132
+ }
1136
1133
let initialConfiguration = initParams . initializationOptions
1137
1134
?. extensionConfiguration as extensionConfiguration | undefined ;
1138
1135
@@ -1244,8 +1241,6 @@ function onMessage(msg: p.Message) {
1244
1241
} else {
1245
1242
shutdownRequestAlreadyReceived = true ;
1246
1243
// TODO: recheck logic around init/shutdown...
1247
- stopWatchingCompilerLog ( ) ;
1248
- // TODO: delete bsb watchers
1249
1244
1250
1245
if ( pullConfigurationPeriodically != null ) {
1251
1246
clearInterval ( pullConfigurationPeriodically ) ;
0 commit comments