@@ -44,7 +44,7 @@ type INOLanguageServer struct {
44
44
sketchName string
45
45
sketchMapper * sourcemapper.SketchMapper
46
46
sketchTrackedFilesCount int
47
- trackedIDEDocs map [string ]lsp.TextDocumentItem
47
+ trackedIdeDocs map [string ]lsp.TextDocumentItem
48
48
ideInoDocsWithDiagnostics map [lsp.DocumentURI ]bool
49
49
sketchRebuilder * SketchRebuilder
50
50
}
@@ -115,7 +115,7 @@ func (ls *INOLanguageServer) readUnlock(logger jsonrpc.FunctionLogger) {
115
115
func NewINOLanguageServer (stdin io.Reader , stdout io.Writer , config * Config ) * INOLanguageServer {
116
116
logger := NewLSPFunctionLogger (color .HiWhiteString , "LS: " )
117
117
ls := & INOLanguageServer {
118
- trackedIDEDocs : map [string ]lsp.TextDocumentItem {},
118
+ trackedIdeDocs : map [string ]lsp.TextDocumentItem {},
119
119
ideInoDocsWithDiagnostics : map [lsp.DocumentURI ]bool {},
120
120
closing : make (chan bool ),
121
121
config : config ,
@@ -952,7 +952,7 @@ func (ls *INOLanguageServer) TextDocumentRangeFormattingReqFromIDE(ctx context.C
952
952
}
953
953
}
954
954
955
- func (ls * INOLanguageServer ) InitializedNotifFromIDE (logger jsonrpc.FunctionLogger , params * lsp.InitializedParams ) {
955
+ func (ls * INOLanguageServer ) InitializedNotifFromIDE (logger jsonrpc.FunctionLogger , ideParams * lsp.InitializedParams ) {
956
956
logger .Logf ("Notification is not propagated to clangd" )
957
957
}
958
958
@@ -962,18 +962,18 @@ func (ls *INOLanguageServer) ExitNotifFromIDE(logger jsonrpc.FunctionLogger) {
962
962
os .Exit (0 )
963
963
}
964
964
965
- func (ls * INOLanguageServer ) TextDocumentDidOpenNotifFromIDE (logger jsonrpc.FunctionLogger , inoParam * lsp.DidOpenTextDocumentParams ) {
965
+ func (ls * INOLanguageServer ) TextDocumentDidOpenNotifFromIDE (logger jsonrpc.FunctionLogger , ideParam * lsp.DidOpenTextDocumentParams ) {
966
966
ls .writeLock (logger , true )
967
967
defer ls .writeUnlock (logger )
968
968
969
969
ls .triggerRebuild ()
970
970
971
971
// Add the TextDocumentItem in the tracked files list
972
- inoTextDocItem := inoParam .TextDocument
973
- ls .trackedIDEDocs [ inoTextDocItem .URI .AsPath ().String ()] = inoTextDocItem
972
+ ideTextDocItem := ideParam .TextDocument
973
+ ls .trackedIdeDocs [ ideTextDocItem .URI .AsPath ().String ()] = ideTextDocItem
974
974
975
975
// If we are tracking a .ino...
976
- if inoTextDocItem .URI .Ext () == ".ino" {
976
+ if ideTextDocItem .URI .Ext () == ".ino" {
977
977
ls .sketchTrackedFilesCount ++
978
978
logger .Logf ("Increasing .ino tracked files count to %d" , ls .sketchTrackedFilesCount )
979
979
@@ -984,10 +984,10 @@ func (ls *INOLanguageServer) TextDocumentDidOpenNotifFromIDE(logger jsonrpc.Func
984
984
}
985
985
}
986
986
987
- if cppItem , err := ls .ino2cppTextDocumentItem (logger , inoTextDocItem ); err != nil {
987
+ if clangTextDocItem , err := ls .ino2cppTextDocumentItem (logger , ideTextDocItem ); err != nil {
988
988
logger .Logf ("Error: %s" , err )
989
989
} else if err := ls .Clangd .conn .TextDocumentDidOpen (& lsp.DidOpenTextDocumentParams {
990
- TextDocument : cppItem ,
990
+ TextDocument : clangTextDocItem ,
991
991
}); err != nil {
992
992
// Exit the process and trigger a restart by the client in case of a severe error
993
993
logger .Logf ("Error sending notification to clangd server: %v" , err )
@@ -996,33 +996,109 @@ func (ls *INOLanguageServer) TextDocumentDidOpenNotifFromIDE(logger jsonrpc.Func
996
996
}
997
997
}
998
998
999
- func (ls * INOLanguageServer ) TextDocumentDidChangeNotifFromIDE (logger jsonrpc.FunctionLogger , inoParams * lsp.DidChangeTextDocumentParams ) {
999
+ func (ls * INOLanguageServer ) TextDocumentDidChangeNotifFromIDE (logger jsonrpc.FunctionLogger , ideParams * lsp.DidChangeTextDocumentParams ) {
1000
1000
ls .writeLock (logger , true )
1001
1001
defer ls .writeUnlock (logger )
1002
1002
1003
1003
ls .triggerRebuild ()
1004
1004
1005
- logger .Logf ("didChange(%s)" , inoParams .TextDocument )
1006
- for _ , change := range inoParams .ContentChanges {
1005
+ logger .Logf ("didChange(%s)" , ideParams .TextDocument )
1006
+ for _ , change := range ideParams .ContentChanges {
1007
1007
logger .Logf (" > %s" , change )
1008
1008
}
1009
1009
1010
- if cppParams , err := ls .didChange (logger , inoParams ); err != nil {
1010
+ // Clear all RangeLengths: it's a deprecated field and if the byte count is wrong the
1011
+ // source text file will be unloaded from clangd without notice, leading to a "non-added
1012
+ // document" error for all subsequent requests.
1013
+ // https://github.com/clangd/clangd/issues/717#issuecomment-793220007
1014
+ for i := range ideParams .ContentChanges {
1015
+ ideParams .ContentChanges [i ].RangeLength = nil
1016
+ }
1017
+
1018
+ ideTextDocIdentifier := ideParams .TextDocument
1019
+
1020
+ // Apply the change to the tracked sketch file.
1021
+ trackedIdeDocID := ideTextDocIdentifier .URI .AsPath ().String ()
1022
+ if doc , ok := ls .trackedIdeDocs [trackedIdeDocID ]; ! ok {
1023
+ logger .Logf ("Error: %s" , & UnknownURI {ideTextDocIdentifier .URI })
1024
+ return
1025
+ } else if updatedDoc , err := textedits .ApplyLSPTextDocumentContentChangeEvent (doc , ideParams ); err != nil {
1011
1026
logger .Logf ("Error: %s" , err )
1012
- } else if cppParams == nil {
1013
- logger .Logf ("Notification is not propagated to clangd" )
1027
+ return
1014
1028
} else {
1015
- logger .Logf ("to Clang: didChange(%s@%d)" , cppParams .TextDocument )
1016
- for _ , change := range cppParams .ContentChanges {
1017
- logger .Logf (" > %s" , change )
1029
+ ls .trackedIdeDocs [trackedIdeDocID ] = updatedDoc
1030
+ logger .Logf ("Tracked SKETCH file:----------+\n " + updatedDoc .Text + "\n ----------------------" )
1031
+ }
1032
+
1033
+ // If the file is not part of a .ino flie forward the change as-is to clangd
1034
+ var clangParams * lsp.DidChangeTextDocumentParams
1035
+
1036
+ if ideTextDocIdentifier .URI .Ext () != ".ino" {
1037
+
1038
+ clangTextDocIdentifier , err := ls .ide2ClangVersionedTextDocumentIdentifier (logger , ideTextDocIdentifier )
1039
+ if err != nil {
1040
+ logger .Logf ("Error: %s" , err )
1041
+ return
1018
1042
}
1019
- if err := ls .Clangd .conn .TextDocumentDidChange (cppParams ); err != nil {
1020
- // Exit the process and trigger a restart by the client in case of a severe error
1021
- logger .Logf ("Connection error with clangd server: %v" , err )
1022
- logger .Logf ("Please restart the language server." )
1023
- ls .Close ()
1043
+ clangParams = & lsp.DidChangeTextDocumentParams {
1044
+ TextDocument : clangTextDocIdentifier ,
1045
+ ContentChanges : ideParams .ContentChanges ,
1046
+ }
1047
+
1048
+ } else {
1049
+
1050
+ // If changes are applied to a .ino file we increment the global .ino.cpp versioning
1051
+ // for each increment of the single .ino file.
1052
+
1053
+ clangChanges := []lsp.TextDocumentContentChangeEvent {}
1054
+ for _ , ideChange := range ideParams .ContentChanges {
1055
+ var clangChangeRange * lsp.Range
1056
+ if ideChange .Range != nil {
1057
+ clangURI , clangRange , err := ls .ide2ClangRange (logger , ideTextDocIdentifier .URI , * ideChange .Range )
1058
+ if err != nil {
1059
+ logger .Logf ("Error: %s" , err )
1060
+ return
1061
+ }
1062
+ if ! ls .clangURIRefersToIno (clangURI ) {
1063
+ logger .Logf ("Error: change to .ino does not maps to a change in sketch.ino.cpp" )
1064
+ return
1065
+ }
1066
+ clangChangeRange = & clangRange
1067
+
1068
+ _ = ls .sketchMapper .ApplyTextChange (ideTextDocIdentifier .URI , ideChange )
1069
+ ls .sketchMapper .DebugLogAll ()
1070
+ } else {
1071
+ panic ("full-text change in .ino not implemented" )
1072
+ }
1073
+ clangChanges = append (clangChanges , lsp.TextDocumentContentChangeEvent {
1074
+ Range : clangChangeRange ,
1075
+ RangeLength : ideChange .RangeLength ,
1076
+ Text : ideChange .Text ,
1077
+ })
1078
+ }
1079
+
1080
+ // build a cpp equivalent didChange request
1081
+ clangParams = & lsp.DidChangeTextDocumentParams {
1082
+ ContentChanges : clangChanges ,
1083
+ TextDocument : lsp.VersionedTextDocumentIdentifier {
1084
+ TextDocumentIdentifier : lsp.TextDocumentIdentifier {
1085
+ URI : lsp .NewDocumentURIFromPath (ls .buildSketchCpp ),
1086
+ },
1087
+ Version : ls .sketchMapper .CppText .Version ,
1088
+ },
1024
1089
}
1025
1090
}
1091
+
1092
+ logger .Logf ("to Clang: didChange(%s@%d)" , clangParams .TextDocument )
1093
+ for _ , change := range clangParams .ContentChanges {
1094
+ logger .Logf (" > %s" , change )
1095
+ }
1096
+ if err := ls .Clangd .conn .TextDocumentDidChange (clangParams ); err != nil {
1097
+ // Exit the process and trigger a restart by the client in case of a severe error
1098
+ logger .Logf ("Connection error with clangd server: %v" , err )
1099
+ logger .Logf ("Please restart the language server." )
1100
+ ls .Close ()
1101
+ }
1026
1102
}
1027
1103
1028
1104
func (ls * INOLanguageServer ) TextDocumentDidSaveNotifFromIDE (logger jsonrpc.FunctionLogger , inoParams * lsp.DidSaveTextDocumentParams ) {
@@ -1244,8 +1320,8 @@ func (ls *INOLanguageServer) extractDataFolderFromArduinoCLI(logger jsonrpc.Func
1244
1320
1245
1321
func (ls * INOLanguageServer ) didClose (logger jsonrpc.FunctionLogger , inoDidClose * lsp.DidCloseTextDocumentParams ) (* lsp.DidCloseTextDocumentParams , error ) {
1246
1322
inoIdentifier := inoDidClose .TextDocument
1247
- if _ , exist := ls .trackedIDEDocs [inoIdentifier .URI .AsPath ().String ()]; exist {
1248
- delete (ls .trackedIDEDocs , inoIdentifier .URI .AsPath ().String ())
1323
+ if _ , exist := ls .trackedIdeDocs [inoIdentifier .URI .AsPath ().String ()]; exist {
1324
+ delete (ls .trackedIdeDocs , inoIdentifier .URI .AsPath ().String ())
1249
1325
} else {
1250
1326
logger .Logf (" didClose of untracked document: %s" , inoIdentifier .URI )
1251
1327
return nil , & UnknownURI {inoIdentifier .URI }
@@ -1282,87 +1358,13 @@ func (ls *INOLanguageServer) ino2cppTextDocumentItem(logger jsonrpc.FunctionLogg
1282
1358
} else {
1283
1359
cppItem .LanguageID = inoItem .LanguageID
1284
1360
inoPath := inoItem .URI .AsPath ().String ()
1285
- cppItem .Text = ls .trackedIDEDocs [inoPath ].Text
1286
- cppItem .Version = ls .trackedIDEDocs [inoPath ].Version
1361
+ cppItem .Text = ls .trackedIdeDocs [inoPath ].Text
1362
+ cppItem .Version = ls .trackedIdeDocs [inoPath ].Version
1287
1363
}
1288
1364
1289
1365
return cppItem , nil
1290
1366
}
1291
1367
1292
- func (ls * INOLanguageServer ) didChange (logger jsonrpc.FunctionLogger , inoDidChangeParams * lsp.DidChangeTextDocumentParams ) (* lsp.DidChangeTextDocumentParams , error ) {
1293
- // Clear all RangeLengths: it's a deprecated field and if the byte count is wrong the
1294
- // source text file will be unloaded from clangd without notice, leading to a "non-added
1295
- // document" error for all subsequent requests.
1296
- // https://github.com/clangd/clangd/issues/717#issuecomment-793220007
1297
- for i := range inoDidChangeParams .ContentChanges {
1298
- inoDidChangeParams .ContentChanges [i ].RangeLength = nil
1299
- }
1300
-
1301
- inoDoc := inoDidChangeParams .TextDocument
1302
-
1303
- // Apply the change to the tracked sketch file.
1304
- trackedInoID := inoDoc .URI .AsPath ().String ()
1305
- if doc , ok := ls .trackedIDEDocs [trackedInoID ]; ! ok {
1306
- return nil , & UnknownURI {inoDoc .URI }
1307
- } else if updatedDoc , err := textedits .ApplyLSPTextDocumentContentChangeEvent (doc , inoDidChangeParams ); err != nil {
1308
- return nil , err
1309
- } else {
1310
- ls .trackedIDEDocs [trackedInoID ] = updatedDoc
1311
- }
1312
-
1313
- logger .Logf ("Tracked SKETCH file:----------+\n " + ls .trackedIDEDocs [trackedInoID ].Text + "\n ----------------------" )
1314
-
1315
- // If the file is not part of a .ino flie forward the change as-is to clangd
1316
- if inoDoc .URI .Ext () != ".ino" {
1317
- if cppDoc , err := ls .ino2cppVersionedTextDocumentIdentifier (logger , inoDidChangeParams .TextDocument ); err != nil {
1318
- return nil , err
1319
- } else {
1320
- cppDidChangeParams := * inoDidChangeParams
1321
- cppDidChangeParams .TextDocument = cppDoc
1322
- return & cppDidChangeParams , nil
1323
- }
1324
- }
1325
-
1326
- // If changes are applied to a .ino file we increment the global .ino.cpp versioning
1327
- // for each increment of the single .ino file.
1328
-
1329
- cppChanges := []lsp.TextDocumentContentChangeEvent {}
1330
- for _ , inoChange := range inoDidChangeParams .ContentChanges {
1331
- cppChangeRange , ok := ls .sketchMapper .InoToCppLSPRangeOk (inoDoc .URI , * inoChange .Range )
1332
- if ! ok {
1333
- return nil , errors .Errorf ("invalid change range %s:%s" , inoDoc .URI , inoChange .Range )
1334
- }
1335
-
1336
- _ = ls .sketchMapper .ApplyTextChange (inoDoc .URI , inoChange )
1337
-
1338
- ls .sketchMapper .DebugLogAll ()
1339
-
1340
- cppChanges = append (cppChanges , lsp.TextDocumentContentChangeEvent {
1341
- Range : & cppChangeRange ,
1342
- RangeLength : inoChange .RangeLength ,
1343
- Text : inoChange .Text ,
1344
- })
1345
- }
1346
-
1347
- // build a cpp equivalent didChange request
1348
- return & lsp.DidChangeTextDocumentParams {
1349
- ContentChanges : cppChanges ,
1350
- TextDocument : lsp.VersionedTextDocumentIdentifier {
1351
- TextDocumentIdentifier : lsp.TextDocumentIdentifier {
1352
- URI : lsp .NewDocumentURIFromPath (ls .buildSketchCpp ),
1353
- },
1354
- Version : ls .sketchMapper .CppText .Version ,
1355
- },
1356
- }, nil
1357
- }
1358
-
1359
- func (ls * INOLanguageServer ) ino2cppVersionedTextDocumentIdentifier (logger jsonrpc.FunctionLogger , doc lsp.VersionedTextDocumentIdentifier ) (lsp.VersionedTextDocumentIdentifier , error ) {
1360
- cppURI , err := ls .ide2ClangDocumentURI (logger , doc .URI )
1361
- res := doc
1362
- res .URI = cppURI
1363
- return res , err
1364
- }
1365
-
1366
1368
func (ls * INOLanguageServer ) clang2IdeCodeAction (logger jsonrpc.FunctionLogger , clangCodeAction lsp.CodeAction , origIdeURI lsp.DocumentURI ) * lsp.CodeAction {
1367
1369
ideCodeAction := & lsp.CodeAction {
1368
1370
Title : clangCodeAction .Title ,
0 commit comments