Skip to content

Commit 508ca69

Browse files
authored
Merge pull request #57 from bcmi-labs/fix-publish-diagnostic
Fix publish diagnostic
2 parents 0489a1c + 37f3b38 commit 508ca69

File tree

4 files changed

+71
-93
lines changed

4 files changed

+71
-93
lines changed

Diff for: handler/handler.go

+57-74
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ type InoHandler struct {
6969
sketchMapper *sourcemapper.InoMapper
7070
sketchTrackedFilesCount int
7171
docs map[string]*lsp.TextDocumentItem
72-
inoDocsWithDiagnostics map[string]bool
72+
inoDocsWithDiagnostics map[lsp.DocumentURI]bool
7373

7474
config lsp.BoardConfig
7575
}
@@ -106,7 +106,7 @@ func (handler *InoHandler) waitClangdStart(msg string) {
106106
func NewInoHandler(stdio io.ReadWriteCloser, board lsp.Board) *InoHandler {
107107
handler := &InoHandler{
108108
docs: map[string]*lsp.TextDocumentItem{},
109-
inoDocsWithDiagnostics: map[string]bool{},
109+
inoDocsWithDiagnostics: map[lsp.DocumentURI]bool{},
110110
config: lsp.BoardConfig{
111111
SelectedBoard: board,
112112
},
@@ -731,7 +731,7 @@ func startClangd(compileCommandsDir, sketchCpp *paths.Path, compilers map[string
731731
func (handler *InoHandler) didOpen(inoDidOpen *lsp.DidOpenTextDocumentParams) (*lsp.DidOpenTextDocumentParams, error) {
732732
// Add the TextDocumentItem in the tracked files list
733733
inoItem := inoDidOpen.TextDocument
734-
handler.docs[inoItem.URI.Canonical()] = &inoItem
734+
handler.docs[inoItem.URI.AsPath().String()] = &inoItem
735735

736736
// If we are tracking a .ino...
737737
if inoItem.URI.Ext() == ".ino" {
@@ -752,8 +752,8 @@ func (handler *InoHandler) didOpen(inoDidOpen *lsp.DidOpenTextDocumentParams) (*
752752

753753
func (handler *InoHandler) didClose(inoDidClose *lsp.DidCloseTextDocumentParams) (*lsp.DidCloseTextDocumentParams, error) {
754754
inoIdentifier := inoDidClose.TextDocument
755-
if _, exist := handler.docs[inoIdentifier.URI.Canonical()]; exist {
756-
delete(handler.docs, inoIdentifier.URI.Canonical())
755+
if _, exist := handler.docs[inoIdentifier.URI.AsPath().String()]; exist {
756+
delete(handler.docs, inoIdentifier.URI.AsPath().String())
757757
} else {
758758
log.Printf(" didClose of untracked document: %s", inoIdentifier.URI)
759759
return nil, unknownURI(inoIdentifier.URI)
@@ -789,8 +789,9 @@ func (handler *InoHandler) ino2cppTextDocumentItem(inoItem lsp.TextDocumentItem)
789789
cppItem.Version = handler.sketchMapper.CppText.Version
790790
} else {
791791
cppItem.LanguageID = inoItem.LanguageID
792-
cppItem.Text = handler.docs[inoItem.URI.Canonical()].Text
793-
cppItem.Version = handler.docs[inoItem.URI.Canonical()].Version
792+
inoPath := inoItem.URI.AsPath().String()
793+
cppItem.Text = handler.docs[inoPath].Text
794+
cppItem.Version = handler.docs[inoPath].Version
794795
}
795796

796797
return cppItem, nil
@@ -799,7 +800,7 @@ func (handler *InoHandler) ino2cppTextDocumentItem(inoItem lsp.TextDocumentItem)
799800
func (handler *InoHandler) didChange(ctx context.Context, req *lsp.DidChangeTextDocumentParams) (*lsp.DidChangeTextDocumentParams, error) {
800801
doc := req.TextDocument
801802

802-
trackedDoc, ok := handler.docs[doc.URI.Canonical()]
803+
trackedDoc, ok := handler.docs[doc.URI.AsPath().String()]
803804
if !ok {
804805
return nil, unknownURI(doc.URI)
805806
}
@@ -974,6 +975,10 @@ func (handler *InoHandler) inoDocumentURIFromInoPath(inoPath string) (lsp.Docume
974975
}
975976

976977
func (handler *InoHandler) cpp2inoDocumentURI(cppURI lsp.DocumentURI, cppRange lsp.Range) (lsp.DocumentURI, lsp.Range, error) {
978+
// TODO: Split this function into 2
979+
// - Cpp2inoSketchDocumentURI: converts sketch (cppURI, cppRange) -> (inoURI, inoRange)
980+
// - Cpp2inoDocumentURI : converts non-sketch (cppURI) -> (inoURI) [range is the same]
981+
977982
// Sketchbook/Sketch/Sketch.ino <- build-path/sketch/Sketch.ino.cpp
978983
// Sketchbook/Sketch/AnotherTab.ino <- build-path/sketch/Sketch.ino.cpp (different section from above)
979984
// Sketchbook/Sketch/AnotherFile.cpp <- build-path/sketch/AnotherFile.cpp (1:1)
@@ -1010,9 +1015,11 @@ func (handler *InoHandler) cpp2inoDocumentURI(cppURI lsp.DocumentURI, cppRange l
10101015

10111016
rel, err := handler.buildSketchRoot.RelTo(cppPath)
10121017
if err == nil {
1013-
inoPath := handler.sketchRoot.JoinPath(rel)
1018+
inoPath := handler.sketchRoot.JoinPath(rel).String()
10141019
log.Printf(" URI: '%s' -> '%s'", cppPath, inoPath)
1015-
return lsp.NewDocumentURIFromPath(inoPath), cppRange, nil
1020+
inoURI, err := handler.inoDocumentURIFromInoPath(inoPath)
1021+
log.Printf(" as URI: '%s'", inoURI)
1022+
return inoURI, cppRange, err
10161023
}
10171024

10181025
log.Printf(" could not determine rel-path of '%s' in '%s': %s", cppPath, handler.buildSketchRoot, err)
@@ -1405,7 +1412,7 @@ func (handler *InoHandler) cpp2inoTextEdit(cppURI lsp.DocumentURI, cppEdit lsp.T
14051412
}
14061413

14071414
func (handler *InoHandler) cpp2inoDocumentSymbols(cppSymbols []lsp.DocumentSymbol, inoRequestedURI lsp.DocumentURI) []lsp.DocumentSymbol {
1408-
inoRequested := inoRequestedURI.Canonical()
1415+
inoRequested := inoRequestedURI.AsPath().String()
14091416
log.Printf(" filtering for requested ino file: %s", inoRequested)
14101417
if inoRequestedURI.Ext() != ".ino" || len(cppSymbols) == 0 {
14111418
return cppSymbols
@@ -1474,46 +1481,68 @@ func (handler *InoHandler) cpp2inoSymbolInformation(syms []lsp.SymbolInformation
14741481
}
14751482

14761483
func (handler *InoHandler) cpp2inoDiagnostics(cppDiags *lsp.PublishDiagnosticsParams) ([]*lsp.PublishDiagnosticsParams, error) {
1484+
inoDiagsParam := map[lsp.DocumentURI]*lsp.PublishDiagnosticsParams{}
14771485

1478-
if len(cppDiags.Diagnostics) == 0 {
1479-
// If we receive the empty diagnostic on the preprocessed sketch,
1480-
// just return an empty diagnostic array.
1481-
if cppDiags.URI.AsPath().EquivalentTo(handler.buildSketchCpp) {
1482-
return []*lsp.PublishDiagnosticsParams{}, nil
1483-
}
1484-
1485-
inoURI, _, err := handler.cpp2inoDocumentURI(cppDiags.URI, lsp.NilRange)
1486-
return []*lsp.PublishDiagnosticsParams{
1487-
{
1486+
cppURI := cppDiags.URI
1487+
isSketch := cppURI.AsPath().EquivalentTo(handler.buildSketchCpp)
1488+
if isSketch {
1489+
for inoURI := range handler.inoDocsWithDiagnostics {
1490+
inoDiagsParam[inoURI] = &lsp.PublishDiagnosticsParams{
14881491
URI: inoURI,
14891492
Diagnostics: []lsp.Diagnostic{},
1490-
},
1491-
}, err
1493+
}
1494+
}
1495+
handler.inoDocsWithDiagnostics = map[lsp.DocumentURI]bool{}
1496+
} else {
1497+
inoURI, _, err := handler.cpp2inoDocumentURI(cppURI, lsp.NilRange)
1498+
if err != nil {
1499+
return nil, err
1500+
}
1501+
inoDiagsParam[inoURI] = &lsp.PublishDiagnosticsParams{
1502+
URI: inoURI,
1503+
Diagnostics: []lsp.Diagnostic{},
1504+
}
14921505
}
14931506

1494-
convertedDiagnostics := map[lsp.DocumentURI]*lsp.PublishDiagnosticsParams{}
14951507
for _, cppDiag := range cppDiags.Diagnostics {
1496-
inoURI, inoRange, err := handler.cpp2inoDocumentURI(cppDiags.URI, cppDiag.Range)
1508+
inoURI, inoRange, err := handler.cpp2inoDocumentURI(cppURI, cppDiag.Range)
14971509
if err != nil {
14981510
return nil, err
14991511
}
1512+
if inoURI.String() == sourcemapper.NotInoURI.String() {
1513+
continue
1514+
}
15001515

1501-
inoDiagParam, created := convertedDiagnostics[inoURI]
1516+
inoDiagParam, created := inoDiagsParam[inoURI]
15021517
if !created {
15031518
inoDiagParam = &lsp.PublishDiagnosticsParams{
15041519
URI: inoURI,
15051520
Diagnostics: []lsp.Diagnostic{},
15061521
}
1507-
convertedDiagnostics[inoURI] = inoDiagParam
1522+
inoDiagsParam[inoURI] = inoDiagParam
15081523
}
15091524

15101525
inoDiag := cppDiag
15111526
inoDiag.Range = inoRange
15121527
inoDiagParam.Diagnostics = append(inoDiagParam.Diagnostics, inoDiag)
1528+
1529+
if isSketch {
1530+
handler.inoDocsWithDiagnostics[inoURI] = true
1531+
1532+
// If we have an "undefined reference" in the .ino code trigger a
1533+
// check for newly created symbols (that in turn may trigger a
1534+
// new arduino-preprocessing of the sketch).
1535+
if inoDiag.Code == "undeclared_var_use_suggest" ||
1536+
inoDiag.Code == "undeclared_var_use" ||
1537+
inoDiag.Code == "ovl_no_viable_function_in_call" ||
1538+
inoDiag.Code == "pp_file_not_found" {
1539+
handler.buildSketchSymbolsCheck = true
1540+
}
1541+
}
15131542
}
15141543

15151544
inoDiagParams := []*lsp.PublishDiagnosticsParams{}
1516-
for _, v := range convertedDiagnostics {
1545+
for _, v := range inoDiagsParam {
15171546
inoDiagParams = append(inoDiagParams, v)
15181547
}
15191548
return inoDiagParams, nil
@@ -1602,34 +1631,9 @@ func (handler *InoHandler) FromClangd(ctx context.Context, connection *jsonrpc2.
16021631
if err != nil {
16031632
return nil, err
16041633
}
1605-
cleanUpInoDiagnostics := false
1606-
if len(inoDiagnostics) == 0 {
1607-
cleanUpInoDiagnostics = true
1608-
}
16091634

16101635
// Push back to IDE the converted diagnostics
1611-
inoDocsWithDiagnostics := map[string]bool{}
16121636
for _, inoDiag := range inoDiagnostics {
1613-
if inoDiag.URI.String() == sourcemapper.NotInoURI.String() {
1614-
cleanUpInoDiagnostics = true
1615-
continue
1616-
}
1617-
1618-
// If we have an "undefined reference" in the .ino code trigger a
1619-
// check for newly created symbols (that in turn may trigger a
1620-
// new arduino-preprocessing of the sketch).
1621-
if inoDiag.URI.Ext() == ".ino" {
1622-
inoDocsWithDiagnostics[inoDiag.URI.Canonical()] = true
1623-
cleanUpInoDiagnostics = true
1624-
for _, diag := range inoDiag.Diagnostics {
1625-
if diag.Code == "undeclared_var_use_suggest" ||
1626-
diag.Code == "undeclared_var_use" ||
1627-
diag.Code == "ovl_no_viable_function_in_call" ||
1628-
diag.Code == "pp_file_not_found" {
1629-
handler.buildSketchSymbolsCheck = true
1630-
}
1631-
}
1632-
}
16331637

16341638
log.Printf(prefix+"to IDE: publishDiagnostics(%s):", inoDiag.URI)
16351639
for _, diag := range inoDiag.Diagnostics {
@@ -1639,27 +1643,6 @@ func (handler *InoHandler) FromClangd(ctx context.Context, connection *jsonrpc2.
16391643
return nil, err
16401644
}
16411645
}
1642-
1643-
if cleanUpInoDiagnostics {
1644-
// Remove diagnostics from all .ino where there are no errors coming from clang
1645-
for sourcePath := range handler.inoDocsWithDiagnostics {
1646-
if inoDocsWithDiagnostics[sourcePath] {
1647-
// skip if we already sent updated diagnostics
1648-
continue
1649-
}
1650-
// otherwise clear previous diagnostics
1651-
msg := lsp.PublishDiagnosticsParams{
1652-
URI: lsp.NewDocumentURI(sourcePath),
1653-
Diagnostics: []lsp.Diagnostic{},
1654-
}
1655-
log.Printf(prefix+"to IDE: publishDiagnostics(%s):", msg.URI)
1656-
if err := handler.StdioConn.Notify(ctx, "textDocument/publishDiagnostics", msg); err != nil {
1657-
return nil, err
1658-
}
1659-
}
1660-
1661-
handler.inoDocsWithDiagnostics = inoDocsWithDiagnostics
1662-
}
16631646
return nil, err
16641647

16651648
case *lsp.ApplyWorkspaceEditParams:

Diff for: handler/sourcemapper/ino.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ type InoLine struct {
4343

4444
// InoToCppLine converts a source (.ino) line into a target (.cpp) line
4545
func (s *InoMapper) InoToCppLine(sourceURI lsp.DocumentURI, line int) int {
46-
return s.toCpp[InoLine{sourceURI.Canonical(), line}]
46+
return s.toCpp[InoLine{sourceURI.AsPath().String(), line}]
4747
}
4848

4949
// InoToCppLineOk converts a source (.ino) line into a target (.cpp) line
5050
func (s *InoMapper) InoToCppLineOk(sourceURI lsp.DocumentURI, line int) (int, bool) {
51-
res, ok := s.toCpp[InoLine{sourceURI.Canonical(), line}]
51+
res, ok := s.toCpp[InoLine{sourceURI.AsPath().String(), line}]
5252
return res, ok
5353
}
5454

Diff for: lsp/uri.go

+4-9
Original file line numberDiff line numberDiff line change
@@ -21,30 +21,25 @@ var expDriveID = regexp.MustCompile("^/[a-zA-Z]:")
2121

2222
// AsPath convert the DocumentURI to a paths.Path
2323
func (uri DocumentURI) AsPath() *paths.Path {
24-
return paths.New(uri.Unbox())
24+
return paths.New(uri.unbox()).Canonical()
2525
}
2626

27-
// Unbox convert the DocumentURI to a file path string
28-
func (uri DocumentURI) Unbox() string {
27+
// unbox convert the DocumentURI to a file path string
28+
func (uri DocumentURI) unbox() string {
2929
path := uri.url.Path
3030
if expDriveID.MatchString(path) {
3131
return path[1:]
3232
}
3333
return path
3434
}
3535

36-
// Canonical returns the canonical path to the file pointed by the URI
37-
func (uri DocumentURI) Canonical() string {
38-
return uri.AsPath().Canonical().String()
39-
}
40-
4136
func (uri DocumentURI) String() string {
4237
return uri.url.String()
4338
}
4439

4540
// Ext returns the extension of the file pointed by the URI
4641
func (uri DocumentURI) Ext() string {
47-
return filepath.Ext(uri.Unbox())
42+
return filepath.Ext(uri.unbox())
4843
}
4944

5045
// NewDocumentURIFromPath create a DocumentURI from the given Path object

Diff for: lsp/uri_test.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,23 @@ import (
1212
func TestUriToPath(t *testing.T) {
1313
d, err := NewDocumentURIFromURL("file:///C:/Users/test/Sketch.ino")
1414
require.NoError(t, err)
15-
require.Equal(t, "C:/Users/test/Sketch.ino", d.Unbox())
15+
require.Equal(t, "C:/Users/test/Sketch.ino", d.unbox())
1616

1717
d, err = NewDocumentURIFromURL("file:///c%3A/Users/test/Sketch.ino")
1818
require.NoError(t, err)
19-
require.Equal(t, "c:/Users/test/Sketch.ino", d.Unbox())
19+
require.Equal(t, "c:/Users/test/Sketch.ino", d.unbox())
2020

2121
d, err = NewDocumentURIFromURL("file:///Users/test/Sketch.ino")
2222
require.NoError(t, err)
23-
require.Equal(t, "/Users/test/Sketch.ino", d.Unbox())
23+
require.Equal(t, "/Users/test/Sketch.ino", d.unbox())
2424

2525
d, err = NewDocumentURIFromURL("file:///c%3A/Users/USERNA~1/AppData/Local/Temp/.arduinoProIDE-unsaved202108-10416-j28c17.lru6k/sketch_jan8a/sketch_jan8a.ino")
2626
require.NoError(t, err)
27-
require.Equal(t, "c:/Users/USERNA~1/AppData/Local/Temp/.arduinoProIDE-unsaved202108-10416-j28c17.lru6k/sketch_jan8a/sketch_jan8a.ino", d.Unbox())
27+
require.Equal(t, "c:/Users/USERNA~1/AppData/Local/Temp/.arduinoProIDE-unsaved202108-10416-j28c17.lru6k/sketch_jan8a/sketch_jan8a.ino", d.unbox())
2828

2929
d, err = NewDocumentURIFromURL("file:///%F0%9F%98%9B")
3030
require.NoError(t, err)
31-
require.Equal(t, "/\U0001F61B", d.Unbox())
31+
require.Equal(t, "/\U0001F61B", d.unbox())
3232
}
3333

3434
func TestPathToUri(t *testing.T) {
@@ -48,11 +48,11 @@ func TestJSONMarshalUnmarshal(t *testing.T) {
4848
var d DocumentURI
4949
err := json.Unmarshal([]byte(`"file:///Users/test/Sketch.ino"`), &d)
5050
require.NoError(t, err)
51-
require.Equal(t, "/Users/test/Sketch.ino", d.Unbox())
51+
require.Equal(t, "/Users/test/Sketch.ino", d.unbox())
5252

5353
err = json.Unmarshal([]byte(`"file:///%F0%9F%98%9B"`), &d)
5454
require.NoError(t, err)
55-
require.Equal(t, "/\U0001F61B", d.Unbox())
55+
require.Equal(t, "/\U0001F61B", d.unbox())
5656

5757
d = NewDocumentURI("C:\\Users\\test\\Sketch.ino")
5858
data, err := json.Marshal(d)
@@ -79,7 +79,7 @@ func TestNotInoFromSourceMapper(t *testing.T) {
7979
d, err := NewDocumentURIFromURL("file:///not-ino")
8080
require.NoError(t, err)
8181
fmt.Println(d.String())
82-
fmt.Println(d.Unbox())
82+
fmt.Println(d.unbox())
8383
}
8484

8585
func windowsToSlash(path string) string {

0 commit comments

Comments
 (0)