@@ -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.
@@ -209,21 +214,18 @@ let deleteProjectConfigCache = async (rootPath: string) => {
209214 }
210215} ;
211216
212- let compilerLogsWatcher = chokidar
213- . watch ( [ ] , {
214- awaitWriteFinish : {
215- stabilityThreshold : 1 ,
216- } ,
217- } )
218- . on ( "all" , async ( _e , changedPath ) => {
219- if ( changedPath . includes ( "build.ninja" ) ) {
217+ async function onWorkspaceDidChangeWatchedFiles (
218+ params : p . DidChangeWatchedFilesParams
219+ ) {
220+ await Promise . all ( params . changes . map ( async ( change ) => {
221+ if ( change . uri . includes ( "build.ninja" ) ) {
220222 if ( config . extensionConfiguration . cache ?. projectConfig ?. enable === true ) {
221- let projectRoot = utils . findProjectRootOfFile ( changedPath ) ;
223+ let projectRoot = utils . findProjectRootOfFile ( change . uri ) ;
222224 if ( projectRoot != null ) {
223225 await syncProjectConfigCache ( projectRoot ) ;
224226 }
225227 }
226- } else {
228+ } else if ( change . uri . includes ( "compiler.log" ) ) {
227229 try {
228230 await sendUpdatedDiagnostics ( ) ;
229231 sendCompilationFinishedMessage ( ) ;
@@ -236,13 +238,11 @@ let compilerLogsWatcher = chokidar
236238 } catch {
237239 console . log ( "Error while sending updated diagnostics" ) ;
238240 }
241+ } else {
242+ ic . incrementalCompilationFileChanged ( fileURLToPath ( change . uri ) ) ;
239243 }
240- } ) ;
241-
242- let stopWatchingCompilerLog = ( ) => {
243- // TODO: cleanup of compilerLogs?
244- compilerLogsWatcher . close ( ) ;
245- } ;
244+ } ) ) ;
245+ }
246246
247247type clientSentBuildAction = {
248248 title : string ;
@@ -280,13 +280,7 @@ let openedFile = async (fileUri: string, fileContent: string) => {
280280 : false ,
281281 } ;
282282 projectsFiles . set ( projectRootPath , projectRootState ) ;
283- compilerLogsWatcher . add (
284- path . join ( projectRootPath , c . compilerLogPartialPath )
285- ) ;
286283 if ( config . extensionConfiguration . cache ?. projectConfig ?. enable === true ) {
287- compilerLogsWatcher . add (
288- path . join ( projectRootPath , c . buildNinjaPartialPath )
289- ) ;
290284 await syncProjectConfigCache ( projectRootPath ) ;
291285 }
292286 }
@@ -364,12 +358,6 @@ let closedFile = async (fileUri: string) => {
364358 root . openFiles . delete ( filePath ) ;
365359 // clear diagnostics too if no open files open in said project
366360 if ( root . openFiles . size === 0 ) {
367- compilerLogsWatcher . unwatch (
368- path . join ( projectRootPath , c . compilerLogPartialPath )
369- ) ;
370- compilerLogsWatcher . unwatch (
371- path . join ( projectRootPath , c . buildNinjaPartialPath )
372- ) ;
373361 await deleteProjectConfigCache ( projectRootPath ) ;
374362 deleteProjectDiagnostics ( projectRootPath ) ;
375363 if ( root . bsbWatcherByEditor !== null ) {
@@ -1051,7 +1039,7 @@ async function onMessage(msg: p.Message) {
10511039 } else {
10521040 process . exit ( 1 ) ;
10531041 }
1054- } else if ( msg . method === "initialized" ) {
1042+ } else if ( msg . method === InitializedNotification . method ) {
10551043 /*
10561044 The initialized notification is sent from the client to the server after the client received the result of the initialize request
10571045 but before the client is sending any other request or notification to the server.
@@ -1060,27 +1048,32 @@ async function onMessage(msg: p.Message) {
10601048 We use this to register the file watchers for the project.
10611049 The client can watch files for us and send us events via the `workspace/didChangeWatchedFiles`
10621050 */
1063- const watchers =
1064- Array . from ( projectsFiles . keys ( ) ) . flatMap ( projectRootPath => [
1051+ const watchers = Array . from ( workspaceFolders ) . flatMap (
1052+ ( projectRootPath ) => [
10651053 {
10661054 globPattern : path . join ( projectRootPath , c . compilerLogPartialPath ) ,
1067- kind : p . WatchKind . Change | p . WatchKind . Create ,
1055+ kind : p . WatchKind . Change | p . WatchKind . Create | p . WatchKind . Delete ,
10681056 } ,
10691057 {
10701058 globPattern : path . join ( projectRootPath , c . buildNinjaPartialPath ) ,
1071- kind : p . WatchKind . Change | p . WatchKind . Create ,
1059+ kind : p . WatchKind . Change | p . WatchKind . Create | p . WatchKind . Delete ,
10721060 } ,
1073- ] )
1074- const registrationParams : p . RegistrationParams = {
1075- registrations :[
10761061 {
1077- id : "rescript_file_watcher" ,
1078- method : p . DidChangeWatchedFilesNotification . method ,
1079- registerOptions : {
1080- watchers
1081- }
1062+ globPattern : `${ path . join ( projectRootPath , c . compilerDirPartialPath ) } /**/*.{cmt,cmi}` ,
1063+ kind : p . WatchKind . Change | p . WatchKind . Delete ,
10821064 }
10831065 ]
1066+ ) ;
1067+ const registrationParams : p . RegistrationParams = {
1068+ registrations : [
1069+ {
1070+ id : "rescript_file_watcher" ,
1071+ method : DidChangeWatchedFilesNotification . method ,
1072+ registerOptions : {
1073+ watchers,
1074+ } ,
1075+ } ,
1076+ ] ,
10841077 } ;
10851078 const req : p . RequestMessage = {
10861079 jsonrpc : c . jsonrpcVersion ,
@@ -1089,6 +1082,9 @@ async function onMessage(msg: p.Message) {
10891082 params : registrationParams ,
10901083 } ;
10911084 send ( req ) ;
1085+ } else if ( msg . method === DidChangeWatchedFilesNotification . method ) {
1086+ const params = msg . params as p . DidChangeWatchedFilesParams ;
1087+ await onWorkspaceDidChangeWatchedFiles ( params ) ;
10921088 } else if ( msg . method === DidOpenTextDocumentNotification . method ) {
10931089 let params = msg . params as p . DidOpenTextDocumentParams ;
10941090 await openedFile ( params . textDocument . uri , params . textDocument . text ) ;
@@ -1134,6 +1130,10 @@ async function onMessage(msg: p.Message) {
11341130 } else if ( msg . method === "initialize" ) {
11351131 // Save initial configuration, if present
11361132 let initParams = msg . params as InitializeParams ;
1133+ for ( const workspaceFolder of initParams . workspaceFolders || [ ] ) {
1134+ const workspaceRootPath = fileURLToPath ( workspaceFolder . uri ) ;
1135+ workspaceFolders . add ( workspaceRootPath ) ;
1136+ }
11371137 let initialConfiguration = initParams . initializationOptions
11381138 ?. extensionConfiguration as extensionConfiguration | undefined ;
11391139
@@ -1245,8 +1245,6 @@ async function onMessage(msg: p.Message) {
12451245 } else {
12461246 shutdownRequestAlreadyReceived = true ;
12471247 // TODO: recheck logic around init/shutdown...
1248- stopWatchingCompilerLog ( ) ;
1249- // TODO: delete bsb watchers
12501248
12511249 if ( pullConfigurationPeriodically != null ) {
12521250 clearInterval ( pullConfigurationPeriodically ) ;
0 commit comments