Skip to content

Fix publish diagnostic #57

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 28, 2021
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Better handling of publishDiagnostics
  • Loading branch information
cmaglie committed Jan 28, 2021
commit 37f3b386b9e9f683bd551b0372baa2378cac3652
116 changes: 49 additions & 67 deletions handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ type InoHandler struct {
sketchMapper *sourcemapper.InoMapper
sketchTrackedFilesCount int
docs map[string]*lsp.TextDocumentItem
inoDocsWithDiagnostics map[string]bool
inoDocsWithDiagnostics map[lsp.DocumentURI]bool

config lsp.BoardConfig
}
Expand Down Expand Up @@ -106,7 +106,7 @@ func (handler *InoHandler) waitClangdStart(msg string) {
func NewInoHandler(stdio io.ReadWriteCloser, board lsp.Board) *InoHandler {
handler := &InoHandler{
docs: map[string]*lsp.TextDocumentItem{},
inoDocsWithDiagnostics: map[string]bool{},
inoDocsWithDiagnostics: map[lsp.DocumentURI]bool{},
config: lsp.BoardConfig{
SelectedBoard: board,
},
Expand Down Expand Up @@ -975,6 +975,10 @@ func (handler *InoHandler) inoDocumentURIFromInoPath(inoPath string) (lsp.Docume
}

func (handler *InoHandler) cpp2inoDocumentURI(cppURI lsp.DocumentURI, cppRange lsp.Range) (lsp.DocumentURI, lsp.Range, error) {
// TODO: Split this function into 2
// - Cpp2inoSketchDocumentURI: converts sketch (cppURI, cppRange) -> (inoURI, inoRange)
// - Cpp2inoDocumentURI : converts non-sketch (cppURI) -> (inoURI) [range is the same]

// Sketchbook/Sketch/Sketch.ino <- build-path/sketch/Sketch.ino.cpp
// Sketchbook/Sketch/AnotherTab.ino <- build-path/sketch/Sketch.ino.cpp (different section from above)
// Sketchbook/Sketch/AnotherFile.cpp <- build-path/sketch/AnotherFile.cpp (1:1)
Expand Down Expand Up @@ -1011,9 +1015,11 @@ func (handler *InoHandler) cpp2inoDocumentURI(cppURI lsp.DocumentURI, cppRange l

rel, err := handler.buildSketchRoot.RelTo(cppPath)
if err == nil {
inoPath := handler.sketchRoot.JoinPath(rel)
inoPath := handler.sketchRoot.JoinPath(rel).String()
log.Printf(" URI: '%s' -> '%s'", cppPath, inoPath)
return lsp.NewDocumentURIFromPath(inoPath), cppRange, nil
inoURI, err := handler.inoDocumentURIFromInoPath(inoPath)
log.Printf(" as URI: '%s'", inoURI)
return inoURI, cppRange, err
}

log.Printf(" could not determine rel-path of '%s' in '%s': %s", cppPath, handler.buildSketchRoot, err)
Expand Down Expand Up @@ -1475,46 +1481,68 @@ func (handler *InoHandler) cpp2inoSymbolInformation(syms []lsp.SymbolInformation
}

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

if len(cppDiags.Diagnostics) == 0 {
// If we receive the empty diagnostic on the preprocessed sketch,
// just return an empty diagnostic array.
if cppDiags.URI.AsPath().EquivalentTo(handler.buildSketchCpp) {
return []*lsp.PublishDiagnosticsParams{}, nil
}

inoURI, _, err := handler.cpp2inoDocumentURI(cppDiags.URI, lsp.NilRange)
return []*lsp.PublishDiagnosticsParams{
{
cppURI := cppDiags.URI
isSketch := cppURI.AsPath().EquivalentTo(handler.buildSketchCpp)
if isSketch {
for inoURI := range handler.inoDocsWithDiagnostics {
inoDiagsParam[inoURI] = &lsp.PublishDiagnosticsParams{
URI: inoURI,
Diagnostics: []lsp.Diagnostic{},
},
}, err
}
}
handler.inoDocsWithDiagnostics = map[lsp.DocumentURI]bool{}
} else {
inoURI, _, err := handler.cpp2inoDocumentURI(cppURI, lsp.NilRange)
if err != nil {
return nil, err
}
inoDiagsParam[inoURI] = &lsp.PublishDiagnosticsParams{
URI: inoURI,
Diagnostics: []lsp.Diagnostic{},
}
}

convertedDiagnostics := map[lsp.DocumentURI]*lsp.PublishDiagnosticsParams{}
for _, cppDiag := range cppDiags.Diagnostics {
inoURI, inoRange, err := handler.cpp2inoDocumentURI(cppDiags.URI, cppDiag.Range)
inoURI, inoRange, err := handler.cpp2inoDocumentURI(cppURI, cppDiag.Range)
if err != nil {
return nil, err
}
if inoURI.String() == sourcemapper.NotInoURI.String() {
continue
}

inoDiagParam, created := convertedDiagnostics[inoURI]
inoDiagParam, created := inoDiagsParam[inoURI]
if !created {
inoDiagParam = &lsp.PublishDiagnosticsParams{
URI: inoURI,
Diagnostics: []lsp.Diagnostic{},
}
convertedDiagnostics[inoURI] = inoDiagParam
inoDiagsParam[inoURI] = inoDiagParam
}

inoDiag := cppDiag
inoDiag.Range = inoRange
inoDiagParam.Diagnostics = append(inoDiagParam.Diagnostics, inoDiag)

if isSketch {
handler.inoDocsWithDiagnostics[inoURI] = true

// If we have an "undefined reference" in the .ino code trigger a
// check for newly created symbols (that in turn may trigger a
// new arduino-preprocessing of the sketch).
if inoDiag.Code == "undeclared_var_use_suggest" ||
inoDiag.Code == "undeclared_var_use" ||
inoDiag.Code == "ovl_no_viable_function_in_call" ||
inoDiag.Code == "pp_file_not_found" {
handler.buildSketchSymbolsCheck = true
}
}
}

inoDiagParams := []*lsp.PublishDiagnosticsParams{}
for _, v := range convertedDiagnostics {
for _, v := range inoDiagsParam {
inoDiagParams = append(inoDiagParams, v)
}
return inoDiagParams, nil
Expand Down Expand Up @@ -1603,34 +1631,9 @@ func (handler *InoHandler) FromClangd(ctx context.Context, connection *jsonrpc2.
if err != nil {
return nil, err
}
cleanUpInoDiagnostics := false
if len(inoDiagnostics) == 0 {
cleanUpInoDiagnostics = true
}

// Push back to IDE the converted diagnostics
inoDocsWithDiagnostics := map[string]bool{}
for _, inoDiag := range inoDiagnostics {
if inoDiag.URI.String() == sourcemapper.NotInoURI.String() {
cleanUpInoDiagnostics = true
continue
}

// If we have an "undefined reference" in the .ino code trigger a
// check for newly created symbols (that in turn may trigger a
// new arduino-preprocessing of the sketch).
if inoDiag.URI.Ext() == ".ino" {
inoDocsWithDiagnostics[inoDiag.URI.Canonical()] = true
cleanUpInoDiagnostics = true
for _, diag := range inoDiag.Diagnostics {
if diag.Code == "undeclared_var_use_suggest" ||
diag.Code == "undeclared_var_use" ||
diag.Code == "ovl_no_viable_function_in_call" ||
diag.Code == "pp_file_not_found" {
handler.buildSketchSymbolsCheck = true
}
}
}

log.Printf(prefix+"to IDE: publishDiagnostics(%s):", inoDiag.URI)
for _, diag := range inoDiag.Diagnostics {
Expand All @@ -1640,27 +1643,6 @@ func (handler *InoHandler) FromClangd(ctx context.Context, connection *jsonrpc2.
return nil, err
}
}

if cleanUpInoDiagnostics {
// Remove diagnostics from all .ino where there are no errors coming from clang
for sourcePath := range handler.inoDocsWithDiagnostics {
if inoDocsWithDiagnostics[sourcePath] {
// skip if we already sent updated diagnostics
continue
}
// otherwise clear previous diagnostics
msg := lsp.PublishDiagnosticsParams{
URI: lsp.NewDocumentURI(sourcePath),
Diagnostics: []lsp.Diagnostic{},
}
log.Printf(prefix+"to IDE: publishDiagnostics(%s):", msg.URI)
if err := handler.StdioConn.Notify(ctx, "textDocument/publishDiagnostics", msg); err != nil {
return nil, err
}
}

handler.inoDocsWithDiagnostics = inoDocsWithDiagnostics
}
return nil, err

case *lsp.ApplyWorkspaceEditParams:
Expand Down