@@ -126,32 +126,38 @@ func (handler *InoHandler) HandleMessageFromIDE(ctx context.Context, conn *jsonr
126126 params = req .Params
127127 }
128128
129- needsWriteLock := map [string ]bool {
130- "initialize" : true ,
131- "textDocument/didOpen" : true ,
132- "textDocument/didChange" : true ,
133- "textDocument/didClose" : true ,
134- }
135129 log .Printf (prefix + "(queued)" )
136- if needsWriteLock [req .Method ] {
130+ switch req .Method {
131+ case // Write lock
132+ "initialize" ,
133+ "textDocument/didOpen" ,
134+ "textDocument/didChange" ,
135+ "textDocument/didClose" :
137136 handler .dataMux .Lock ()
138137 defer handler .dataMux .Unlock ()
139- } else {
138+ case // Read lock
139+ "textDocument/publishDiagnostics" ,
140+ "workspace/applyEdit" :
141+ handler .dataMux .RLock ()
142+ defer handler .dataMux .RUnlock ()
143+ default : // Default to read lock
140144 handler .dataMux .RLock ()
141145 defer handler .dataMux .RUnlock ()
142146 }
143147
144- // Wait for clangd start-up
145- doNotNeedClangd := map [string ]bool {
146- "initialize" : true ,
147- "initialized" : true ,
148- }
149- if handler .ClangdConn == nil && ! doNotNeedClangd [req .Method ] {
150- log .Printf (prefix + "(throttled: waiting for clangd)" )
151- handler .clangdStarted .Wait ()
148+ switch req .Method {
149+ case // Do not need clangd
150+ "initialize" ,
151+ "initialized" :
152+ default : // Default to clangd required
153+ // Wait for clangd start-up
152154 if handler .ClangdConn == nil {
153- log .Printf ("Clangd startup failed: aborting call" )
154- return nil , errors .New ("could not run clangd, aborted" )
155+ log .Printf (prefix + "(throttled: waiting for clangd)" )
156+ handler .clangdStarted .Wait ()
157+ if handler .ClangdConn == nil {
158+ log .Printf (prefix + "clangd startup failed: aborting call" )
159+ return nil , errors .New ("could not start clangd, aborted" )
160+ }
155161 }
156162 }
157163
@@ -163,7 +169,51 @@ func (handler *InoHandler) HandleMessageFromIDE(ctx context.Context, conn *jsonr
163169 switch p := params .(type ) {
164170 case * lsp.InitializeParams :
165171 // method "initialize"
166- err = handler .initializeWorkbench (p )
172+
173+ go func () {
174+ // Start clangd asynchronously
175+ log .Printf ("LS --- initializing workbench (queued)" )
176+ handler .dataMux .Lock ()
177+ defer handler .dataMux .Unlock ()
178+
179+ log .Printf ("LS --- initializing workbench (running)" )
180+ handler .initializeWorkbench (p )
181+
182+ // clangd should be running now...
183+ handler .clangdStarted .Broadcast ()
184+
185+ log .Printf ("LS --- initializing workbench (done)" )
186+ }()
187+
188+ T := true
189+ F := false
190+ return & lsp.InitializeResult {
191+ Capabilities : lsp.ServerCapabilities {
192+ TextDocumentSync : & lsp.TextDocumentSyncOptionsOrKind {Kind : & lsp .TDSKIncremental },
193+ HoverProvider : true ,
194+ CompletionProvider : & lsp.CompletionOptions {
195+ TriggerCharacters : []string {"." , "\u003e " , ":" },
196+ },
197+ SignatureHelpProvider : & lsp.SignatureHelpOptions {
198+ TriggerCharacters : []string {"(" , "," },
199+ },
200+ DefinitionProvider : true ,
201+ ReferencesProvider : false , // TODO: true
202+ DocumentHighlightProvider : true ,
203+ DocumentSymbolProvider : true ,
204+ WorkspaceSymbolProvider : true ,
205+ CodeActionProvider : & lsp.BoolOrCodeActionOptions {IsProvider : & T },
206+ DocumentFormattingProvider : true ,
207+ DocumentRangeFormattingProvider : true ,
208+ DocumentOnTypeFormattingProvider : & lsp.DocumentOnTypeFormattingOptions {
209+ FirstTriggerCharacter : "\n " ,
210+ },
211+ RenameProvider : & lsp.BoolOrRenameOptions {IsProvider : & F }, // TODO: &T
212+ ExecuteCommandProvider : & lsp.ExecuteCommandOptions {
213+ Commands : []string {"clangd.applyFix" , "clangd.applyTweak" },
214+ },
215+ },
216+ }, nil
167217
168218 case * lsp.InitializedParams :
169219 // method "initialized"
@@ -366,12 +416,12 @@ func (handler *InoHandler) HandleMessageFromIDE(ctx context.Context, conn *jsonr
366416 if err == nil && handler .buildSketchSymbolsLoad {
367417 handler .buildSketchSymbolsLoad = false
368418 log .Println (prefix + "Queued resfreshing document symbols" )
369- err = handler .refreshCppDocumentSymbols ()
419+ go handler .refreshCppDocumentSymbols ()
370420 }
371421 if err == nil && handler .buildSketchSymbolsCheck {
372422 handler .buildSketchSymbolsCheck = false
373423 log .Println (prefix + "Queued check document symbols" )
374- err = handler .checkCppDocumentSymbols ()
424+ go handler .checkCppDocumentSymbols ()
375425 }
376426 if err != nil {
377427 // Exit the process and trigger a restart by the client in case of a severe error
@@ -431,9 +481,6 @@ func (handler *InoHandler) initializeWorkbench(params *lsp.InitializeParams) err
431481
432482 if params == nil {
433483 // If we are restarting re-synchronize clangd
434- ctx , cancel := context .WithTimeout (context .Background (), time .Second )
435- defer cancel ()
436-
437484 cppURI := lsp .NewDocumentURIFromPath (handler .buildSketchCpp )
438485 cppTextDocumentIdentifier := lsp.TextDocumentIdentifier {URI : cppURI }
439486
@@ -447,6 +494,8 @@ func (handler *InoHandler) initializeWorkbench(params *lsp.InitializeParams) err
447494 },
448495 }
449496
497+ ctx , cancel := context .WithTimeout (context .Background (), time .Second )
498+ defer cancel ()
450499 if err := handler .ClangdConn .Notify (ctx , "textDocument/didChange" , syncEvent ); err != nil {
451500 log .Println (" error reinitilizing clangd:" , err )
452501 return err
@@ -465,6 +514,20 @@ func (handler *InoHandler) initializeWorkbench(params *lsp.InitializeParams) err
465514 clangdStream := jsonrpc2 .NewBufferedStream (clangdStdio , jsonrpc2.VSCodeObjectCodec {})
466515 clangdHandler := jsonrpc2 .AsyncHandler (jsonrpc2 .HandlerWithError (handler .FromClangd ))
467516 handler .ClangdConn = jsonrpc2 .NewConn (context .Background (), clangdStream , clangdHandler )
517+
518+ // Send initialization command to clangd
519+ ctx , cancel := context .WithTimeout (context .Background (), time .Second )
520+ defer cancel ()
521+ var resp lsp.InitializeResult
522+ if err := handler .ClangdConn .Call (ctx , "initialize" , handler .lspInitializeParams , & resp ); err != nil {
523+ log .Println (" error initilizing clangd:" , err )
524+ return err
525+ }
526+
527+ if err := handler .ClangdConn .Notify (ctx , "initialized" , lsp.InitializedParams {}); err != nil {
528+ log .Println (" error sending initialize to clangd:" , err )
529+ return err
530+ }
468531 }
469532
470533 return nil
@@ -1373,8 +1436,19 @@ func (handler *InoHandler) FromClangd(ctx context.Context, connection *jsonrpc2.
13731436 defer log .Printf (prefix + "(done)" )
13741437
13751438 log .Printf (prefix + "(queued)" )
1376- handler .synchronizer .DataMux .RLock ()
1377- defer handler .synchronizer .DataMux .RUnlock ()
1439+ switch req .Method {
1440+ case // No locking required
1441+ "$/progress" ,
1442+ "window/workDoneProgress/create" :
1443+ case // Read lock
1444+ "textDocument/publishDiagnostics" ,
1445+ "workspace/applyEdit" :
1446+ handler .dataMux .RLock ()
1447+ defer handler .dataMux .RUnlock ()
1448+ default : // Default to read lock
1449+ handler .dataMux .RLock ()
1450+ defer handler .dataMux .RUnlock ()
1451+ }
13781452 log .Printf (prefix + "(running)" )
13791453
13801454 params , err := lsp .ReadParams (req .Method , req .Params )
0 commit comments