Skip to content

Commit 975d40f

Browse files
committed
Correct handling of textchanges in .cpp/.h
1 parent cf3008d commit 975d40f

File tree

3 files changed

+60
-62
lines changed

3 files changed

+60
-62
lines changed

Diff for: ls/ls.go

+35-51
Original file line numberDiff line numberDiff line change
@@ -984,9 +984,29 @@ func (ls *INOLanguageServer) TextDocumentDidOpenNotifFromIDE(logger jsonrpc.Func
984984
}
985985
}
986986

987-
if clangTextDocItem, err := ls.ino2cppTextDocumentItem(logger, ideTextDocItem); err != nil {
987+
clangURI, _, err := ls.ide2ClangDocumentURI(logger, ideTextDocItem.URI)
988+
if err != nil {
988989
logger.Logf("Error: %s", err)
989-
} else if err := ls.Clangd.conn.TextDocumentDidOpen(&lsp.DidOpenTextDocumentParams{
990+
return
991+
}
992+
clangTextDocItem := lsp.TextDocumentItem{
993+
URI: clangURI,
994+
}
995+
if ls.clangURIRefersToIno(clangURI) {
996+
clangTextDocItem.LanguageID = "cpp"
997+
clangTextDocItem.Text = ls.sketchMapper.CppText.Text
998+
clangTextDocItem.Version = ls.sketchMapper.CppText.Version
999+
} else {
1000+
clangText, err := clangURI.AsPath().ReadFile()
1001+
if err != nil {
1002+
logger.Logf("Error opening sketch file %s: %s", clangURI.AsPath(), err)
1003+
}
1004+
clangTextDocItem.LanguageID = ideTextDocItem.LanguageID
1005+
clangTextDocItem.Version = ideTextDocItem.Version
1006+
clangTextDocItem.Text = string(clangText)
1007+
}
1008+
1009+
if err := ls.Clangd.conn.TextDocumentDidOpen(&lsp.DidOpenTextDocumentParams{
9901010
TextDocument: clangTextDocItem,
9911011
}); err != nil {
9921012
// Exit the process and trigger a restart by the client in case of a severe error
@@ -1092,47 +1112,32 @@ func (ls *INOLanguageServer) TextDocumentDidChangeNotifFromIDE(logger jsonrpc.Fu
10921112
}
10931113
}
10941114

1095-
func (ls *INOLanguageServer) TextDocumentDidSaveNotifFromIDE(logger jsonrpc.FunctionLogger, inoParams *lsp.DidSaveTextDocumentParams) {
1115+
func (ls *INOLanguageServer) TextDocumentDidSaveNotifFromIDE(logger jsonrpc.FunctionLogger, ideParams *lsp.DidSaveTextDocumentParams) {
10961116
ls.writeLock(logger, true)
10971117
defer ls.writeUnlock(logger)
10981118

1099-
ls.triggerRebuild()
1119+
// clangd looks in the build directory (where a copy of the preprocessed sketch resides)
1120+
// so we will not forward notification on saves in the sketch folder.
1121+
logger.Logf("notification is not forwarded to clang")
11001122

1101-
logger.Logf("didSave(%s) hasText=%v", inoParams.TextDocument, inoParams.Text != "")
1102-
if cppTextDocument, err := ls.ide2ClangTextDocumentIdentifier(logger, inoParams.TextDocument); err != nil {
1103-
logger.Logf("--E Error: %s", err)
1104-
} else if cppTextDocument.URI.AsPath().EquivalentTo(ls.buildSketchCpp) {
1105-
logger.Logf(" didSave(%s) equals %s", cppTextDocument, ls.buildSketchCpp)
1106-
logger.Logf(" the notification will be not forwarded to clangd")
1107-
} else {
1108-
logger.Logf("LS --> CL NOTIF didSave(%s)", cppTextDocument)
1109-
if err := ls.Clangd.conn.TextDocumentDidSave(&lsp.DidSaveTextDocumentParams{
1110-
TextDocument: cppTextDocument,
1111-
Text: inoParams.Text,
1112-
}); err != nil {
1113-
// Exit the process and trigger a restart by the client in case of a severe error
1114-
logger.Logf("Connection error with clangd server: %v", err)
1115-
logger.Logf("Please restart the language server.")
1116-
ls.Close()
1117-
}
1118-
}
1123+
ls.triggerRebuild()
11191124
}
11201125

1121-
func (ls *INOLanguageServer) TextDocumentDidCloseNotifFromIDE(logger jsonrpc.FunctionLogger, inoParams *lsp.DidCloseTextDocumentParams) {
1126+
func (ls *INOLanguageServer) TextDocumentDidCloseNotifFromIDE(logger jsonrpc.FunctionLogger, ideParams *lsp.DidCloseTextDocumentParams) {
11221127
ls.writeLock(logger, true)
11231128
defer ls.writeUnlock(logger)
11241129

11251130
ls.triggerRebuild()
11261131

1127-
logger.Logf("didClose(%s)", inoParams.TextDocument)
1132+
logger.Logf("didClose(%s)", ideParams.TextDocument)
11281133

1129-
if cppParams, err := ls.didClose(logger, inoParams); err != nil {
1134+
if clangParams, err := ls.didClose(logger, ideParams); err != nil {
11301135
logger.Logf("--E Error: %s", err)
1131-
} else if cppParams == nil {
1136+
} else if clangParams == nil {
11321137
logger.Logf("--X Notification is not propagated to clangd")
11331138
} else {
1134-
logger.Logf("--> CL NOTIF didClose(%s)", cppParams.TextDocument)
1135-
if err := ls.Clangd.conn.TextDocumentDidClose(cppParams); err != nil {
1139+
logger.Logf("--> CL NOTIF didClose(%s)", clangParams.TextDocument)
1140+
if err := ls.Clangd.conn.TextDocumentDidClose(clangParams); err != nil {
11361141
// Exit the process and trigger a restart by the client in case of a severe error
11371142
logger.Logf("Error sending notification to clangd server: %v", err)
11381143
logger.Logf("Please restart the language server.")
@@ -1314,8 +1319,8 @@ func (ls *INOLanguageServer) extractDataFolderFromArduinoCLI(logger jsonrpc.Func
13141319
}
13151320
}
13161321

1317-
func (ls *INOLanguageServer) didClose(logger jsonrpc.FunctionLogger, inoDidClose *lsp.DidCloseTextDocumentParams) (*lsp.DidCloseTextDocumentParams, error) {
1318-
inoIdentifier := inoDidClose.TextDocument
1322+
func (ls *INOLanguageServer) didClose(logger jsonrpc.FunctionLogger, ideParams *lsp.DidCloseTextDocumentParams) (*lsp.DidCloseTextDocumentParams, error) {
1323+
inoIdentifier := ideParams.TextDocument
13191324
if _, exist := ls.trackedIdeDocs[inoIdentifier.URI.AsPath().String()]; exist {
13201325
delete(ls.trackedIdeDocs, inoIdentifier.URI.AsPath().String())
13211326
} else {
@@ -1340,27 +1345,6 @@ func (ls *INOLanguageServer) didClose(logger jsonrpc.FunctionLogger, inoDidClose
13401345
}, err
13411346
}
13421347

1343-
func (ls *INOLanguageServer) ino2cppTextDocumentItem(logger jsonrpc.FunctionLogger, inoItem lsp.TextDocumentItem) (cppItem lsp.TextDocumentItem, err error) {
1344-
cppURI, err := ls.ide2ClangDocumentURI(logger, inoItem.URI)
1345-
if err != nil {
1346-
return cppItem, err
1347-
}
1348-
cppItem.URI = cppURI
1349-
1350-
if cppURI.AsPath().EquivalentTo(ls.buildSketchCpp) {
1351-
cppItem.LanguageID = "cpp"
1352-
cppItem.Text = ls.sketchMapper.CppText.Text
1353-
cppItem.Version = ls.sketchMapper.CppText.Version
1354-
} else {
1355-
cppItem.LanguageID = inoItem.LanguageID
1356-
inoPath := inoItem.URI.AsPath().String()
1357-
cppItem.Text = ls.trackedIdeDocs[inoPath].Text
1358-
cppItem.Version = ls.trackedIdeDocs[inoPath].Version
1359-
}
1360-
1361-
return cppItem, nil
1362-
}
1363-
13641348
func (ls *INOLanguageServer) clang2IdeCodeAction(logger jsonrpc.FunctionLogger, clangCodeAction lsp.CodeAction, origIdeURI lsp.DocumentURI) *lsp.CodeAction {
13651349
ideCodeAction := &lsp.CodeAction{
13661350
Title: clangCodeAction.Title,

Diff for: ls/ls_clang_to_ide.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,22 @@ func (ls *INOLanguageServer) clang2IdeRangeAndDocumentURI(logger jsonrpc.Functio
4949
return clangURI, clangRange, false, nil
5050
}
5151

52-
// Sketchbook/Sketch/AnotherFile.cpp <-> build-path/sketch/AnotherFile.cpp (same range)
52+
// Sketchbook/Sketch/AnotherFile.cpp <-> build-path/sketch/AnotherFile.cpp (one line offset)
5353
rel, err := ls.buildSketchRoot.RelTo(clangPath)
5454
if err != nil {
5555
logger.Logf("ERROR: could not transform '%s' into a relative path on '%s': %s", clangURI, ls.buildSketchRoot, err)
5656
return lsp.NilURI, lsp.NilRange, false, err
5757
}
5858
idePath := ls.sketchRoot.JoinPath(rel).String()
5959
ideURI, err := ls.idePathToIdeURI(logger, idePath)
60+
if ideRange.End.Line > 0 {
61+
ideRange.End.Line--
62+
}
63+
if ideRange.Start.Line > 0 {
64+
ideRange.Start.Line--
65+
}
6066
logger.Logf("Range: %s:%s -> %s:%s", clangURI, clangRange, ideURI, ideRange)
61-
return ideURI, clangRange, false, err
67+
return ideURI, ideRange, false, err
6268
}
6369

6470
func (ls *INOLanguageServer) clang2IdeDocumentURI(logger jsonrpc.FunctionLogger, clangURI lsp.DocumentURI) (lsp.DocumentURI, error) {

Diff for: ls/ls_ide_to_clang.go

+17-9
Original file line numberDiff line numberDiff line change
@@ -26,43 +26,43 @@ func (ls *INOLanguageServer) idePathToIdeURI(logger jsonrpc.FunctionLogger, inoP
2626
}
2727

2828
func (ls *INOLanguageServer) ide2ClangTextDocumentIdentifier(logger jsonrpc.FunctionLogger, ideTextDocIdentifier lsp.TextDocumentIdentifier) (lsp.TextDocumentIdentifier, error) {
29-
clangURI, err := ls.ide2ClangDocumentURI(logger, ideTextDocIdentifier.URI)
29+
clangURI, _, err := ls.ide2ClangDocumentURI(logger, ideTextDocIdentifier.URI)
3030
return lsp.TextDocumentIdentifier{URI: clangURI}, err
3131
}
3232

33-
func (ls *INOLanguageServer) ide2ClangDocumentURI(logger jsonrpc.FunctionLogger, ideURI lsp.DocumentURI) (lsp.DocumentURI, error) {
33+
func (ls *INOLanguageServer) ide2ClangDocumentURI(logger jsonrpc.FunctionLogger, ideURI lsp.DocumentURI) (lsp.DocumentURI, bool, error) {
3434
// Sketchbook/Sketch/Sketch.ino -> build-path/sketch/Sketch.ino.cpp
3535
// Sketchbook/Sketch/AnotherTab.ino -> build-path/sketch/Sketch.ino.cpp (different section from above)
3636
idePath := ideURI.AsPath()
3737
if idePath.Ext() == ".ino" {
3838
clangURI := lsp.NewDocumentURIFromPath(ls.buildSketchCpp)
3939
logger.Logf("URI: %s -> %s", ideURI, clangURI)
40-
return clangURI, nil
40+
return clangURI, true, nil
4141
}
4242

4343
// another/path/source.cpp -> another/path/source.cpp (unchanged)
4444
inside, err := idePath.IsInsideDir(ls.sketchRoot)
4545
if err != nil {
4646
logger.Logf("ERROR: could not determine if '%s' is inside '%s'", idePath, ls.sketchRoot)
47-
return lsp.NilURI, &UnknownURI{ideURI}
47+
return lsp.NilURI, false, &UnknownURI{ideURI}
4848
}
4949
if !inside {
5050
clangURI := ideURI
5151
logger.Logf("URI: %s -> %s", ideURI, clangURI)
52-
return clangURI, nil
52+
return clangURI, false, nil
5353
}
5454

5555
// Sketchbook/Sketch/AnotherFile.cpp -> build-path/sketch/AnotherFile.cpp
5656
rel, err := ls.sketchRoot.RelTo(idePath)
5757
if err != nil {
5858
logger.Logf("ERROR: could not determine rel-path of '%s' in '%s': %s", idePath, ls.sketchRoot, err)
59-
return lsp.NilURI, err
59+
return lsp.NilURI, false, err
6060
}
6161

6262
clangPath := ls.buildSketchRoot.JoinPath(rel)
6363
clangURI := lsp.NewDocumentURIFromPath(clangPath)
6464
logger.Logf("URI: %s -> %s", ideURI, clangURI)
65-
return clangURI, nil
65+
return clangURI, true, nil
6666
}
6767

6868
func (ls *INOLanguageServer) ide2ClangTextDocumentPositionParams(logger jsonrpc.FunctionLogger, ideParams lsp.TextDocumentPositionParams) (lsp.TextDocumentPositionParams, error) {
@@ -85,23 +85,31 @@ func (ls *INOLanguageServer) ide2ClangPosition(logger jsonrpc.FunctionLogger, id
8585
}
8686

8787
func (ls *INOLanguageServer) ide2ClangRange(logger jsonrpc.FunctionLogger, ideURI lsp.DocumentURI, ideRange lsp.Range) (lsp.DocumentURI, lsp.Range, error) {
88-
clangURI, err := ls.ide2ClangDocumentURI(logger, ideURI)
88+
clangURI, inSketch, err := ls.ide2ClangDocumentURI(logger, ideURI)
8989
if err != nil {
9090
return lsp.DocumentURI{}, lsp.Range{}, err
9191
}
9292
clangRange := ideRange
93+
94+
// Convert .ino ranges using sketchmapper
9395
if ls.clangURIRefersToIno(clangURI) {
9496
if r, ok := ls.sketchMapper.InoToCppLSPRangeOk(ideURI, ideRange); ok {
9597
clangRange = r
9698
} else {
9799
return lsp.DocumentURI{}, lsp.Range{}, fmt.Errorf("invalid range %s:%s: could not be mapped to Arduino-preprocessed sketck.ino.cpp", ideURI, ideRange)
98100
}
99101
}
102+
103+
// Convert other sketch file ranges (.cpp/.h)
104+
if inSketch {
105+
clangRange.Start.Line++
106+
clangRange.End.Line++
107+
}
100108
return clangURI, clangRange, nil
101109
}
102110

103111
func (ls *INOLanguageServer) ide2ClangVersionedTextDocumentIdentifier(logger jsonrpc.FunctionLogger, ideVersionedDoc lsp.VersionedTextDocumentIdentifier) (lsp.VersionedTextDocumentIdentifier, error) {
104-
clangURI, err := ls.ide2ClangDocumentURI(logger, ideVersionedDoc.URI)
112+
clangURI, _, err := ls.ide2ClangDocumentURI(logger, ideVersionedDoc.URI)
105113
return lsp.VersionedTextDocumentIdentifier{
106114
TextDocumentIdentifier: lsp.TextDocumentIdentifier{URI: clangURI},
107115
Version: ideVersionedDoc.Version,

0 commit comments

Comments
 (0)