@@ -4,8 +4,8 @@ import * as v from "vscode-languageserver";
44import * as rpc from "vscode-jsonrpc/node" ;
55import * as path from "path" ;
66import fs from "fs" ;
7- // TODO: check DidChangeWatchedFilesNotification.
87import {
8+ DidChangeWatchedFilesNotification ,
99 DidOpenTextDocumentNotification ,
1010 DidChangeTextDocumentNotification ,
1111 DidCloseTextDocumentNotification ,
@@ -14,6 +14,7 @@ import {
1414 InlayHintParams ,
1515 CodeLensParams ,
1616 SignatureHelpParams ,
17+ InitializedNotification ,
1718} from "vscode-languageserver-protocol" ;
1819import * as lookup from "./lookup" ;
1920import * as utils from "./utils" ;
@@ -27,6 +28,10 @@ import * as ic from "./incrementalCompilation";
2728import config , { extensionConfiguration } from "./config" ;
2829import { projectsFiles } from "./projectFiles" ;
2930
31+ // Absolute paths to all the workspace folders
32+ // Configured during the initialize request
33+ const workspaceFolders = new Set < string > ( ) ;
34+
3035// This holds client capabilities specific to our extension, and not necessarily
3136// related to the LS protocol. It's for enabling/disabling features that might
3237// work in one client, like VSCode, but perhaps not in others, like vim.
@@ -208,21 +213,18 @@ let deleteProjectConfigCache = (rootPath: string) => {
208213 }
209214} ;
210215
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" ) ) {
219221 if ( config . extensionConfiguration . cache ?. projectConfig ?. enable === true ) {
220- let projectRoot = utils . findProjectRootOfFile ( changedPath ) ;
222+ let projectRoot = utils . findProjectRootOfFile ( change . uri ) ;
221223 if ( projectRoot != null ) {
222224 syncProjectConfigCache ( projectRoot ) ;
223225 }
224226 }
225- } else {
227+ } else if ( change . uri . includes ( "compiler.log" ) ) {
226228 try {
227229 sendUpdatedDiagnostics ( ) ;
228230 sendCompilationFinishedMessage ( ) ;
@@ -235,13 +237,11 @@ let compilerLogsWatcher = chokidar
235237 } catch {
236238 console . log ( "Error while sending updated diagnostics" ) ;
237239 }
240+ } else {
241+ ic . incrementalCompilationFileChanged ( fileURLToPath ( change . uri ) ) ;
238242 }
239243 } ) ;
240-
241- let stopWatchingCompilerLog = ( ) => {
242- // TODO: cleanup of compilerLogs?
243- compilerLogsWatcher . close ( ) ;
244- } ;
244+ }
245245
246246type clientSentBuildAction = {
247247 title : string ;
@@ -279,15 +279,6 @@ let openedFile = (fileUri: string, fileContent: string) => {
279279 : false ,
280280 } ;
281281 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- }
291282 }
292283 let root = projectsFiles . get ( projectRootPath ) ! ;
293284 root . openFiles . add ( filePath ) ;
@@ -363,12 +354,6 @@ let closedFile = (fileUri: string) => {
363354 root . openFiles . delete ( filePath ) ;
364355 // clear diagnostics too if no open files open in said project
365356 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- ) ;
372357 deleteProjectConfigCache ( projectRootPath ) ;
373358 deleteProjectDiagnostics ( projectRootPath ) ;
374359 if ( root . bsbWatcherByEditor !== null ) {
@@ -1050,7 +1035,7 @@ function onMessage(msg: p.Message) {
10501035 } else {
10511036 process . exit ( 1 ) ;
10521037 }
1053- } else if ( msg . method === "initialized" ) {
1038+ } else if ( msg . method === InitializedNotification . method ) {
10541039 /*
10551040 The initialized notification is sent from the client to the server after the client received the result of the initialize request
10561041 but before the client is sending any other request or notification to the server.
@@ -1059,27 +1044,32 @@ function onMessage(msg: p.Message) {
10591044 We use this to register the file watchers for the project.
10601045 The client can watch files for us and send us events via the `workspace/didChangeWatchedFiles`
10611046 */
1062- const watchers =
1063- Array . from ( projectsFiles . keys ( ) ) . flatMap ( projectRootPath => [
1047+ const watchers = Array . from ( workspaceFolders ) . flatMap (
1048+ ( projectRootPath ) => [
10641049 {
10651050 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 ,
10671052 } ,
10681053 {
10691054 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 ,
10711056 } ,
1072- ] )
1073- const registrationParams : p . RegistrationParams = {
1074- registrations :[
10751057 {
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 ,
10811060 }
10821061 ]
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+ ] ,
10831073 } ;
10841074 const req : p . RequestMessage = {
10851075 jsonrpc : c . jsonrpcVersion ,
@@ -1088,6 +1078,9 @@ function onMessage(msg: p.Message) {
10881078 params : registrationParams ,
10891079 } ;
10901080 send ( req ) ;
1081+ } else if ( msg . method === DidChangeWatchedFilesNotification . method ) {
1082+ const params = msg . params as p . DidChangeWatchedFilesParams ;
1083+ onWorkspaceDidChangeWatchedFiles ( params ) ;
10911084 } else if ( msg . method === DidOpenTextDocumentNotification . method ) {
10921085 let params = msg . params as p . DidOpenTextDocumentParams ;
10931086 openedFile ( params . textDocument . uri , params . textDocument . text ) ;
@@ -1133,6 +1126,10 @@ function onMessage(msg: p.Message) {
11331126 } else if ( msg . method === "initialize" ) {
11341127 // Save initial configuration, if present
11351128 let initParams = msg . params as InitializeParams ;
1129+ for ( const workspaceFolder of initParams . workspaceFolders || [ ] ) {
1130+ const workspaceRootPath = fileURLToPath ( workspaceFolder . uri ) ;
1131+ workspaceFolders . add ( workspaceRootPath ) ;
1132+ }
11361133 let initialConfiguration = initParams . initializationOptions
11371134 ?. extensionConfiguration as extensionConfiguration | undefined ;
11381135
@@ -1244,8 +1241,6 @@ function onMessage(msg: p.Message) {
12441241 } else {
12451242 shutdownRequestAlreadyReceived = true ;
12461243 // TODO: recheck logic around init/shutdown...
1247- stopWatchingCompilerLog ( ) ;
1248- // TODO: delete bsb watchers
12491244
12501245 if ( pullConfigurationPeriodically != null ) {
12511246 clearInterval ( pullConfigurationPeriodically ) ;
0 commit comments