From d03920dd466f5d29491ca48afc06f9dce70dbb6c Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 5 Jan 2021 13:44:10 +0100 Subject: [PATCH] Leverage clangd to detect function prototypes changes --- handler/handler.go | 28 +++++++++++++++++++--------- lsp/structures.go | 20 ++++++++++++++++++++ 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/handler/handler.go b/handler/handler.go index e07153a..be81c37 100644 --- a/handler/handler.go +++ b/handler/handler.go @@ -624,12 +624,26 @@ func (handler *InoHandler) didChange(ctx context.Context, req *lsp.DidChangeText cppChanges := []lsp.TextDocumentContentChangeEvent{} for _, inoChange := range req.ContentChanges { - dirty := handler.sketchMapper.ApplyTextChange(doc.URI, inoChange) - if dirty { - // TODO: Detect changes in critical lines (for example function definitions) - // and trigger arduino-preprocessing + clangd restart. + cppRange, ok := handler.sketchMapper.InoToCppLSPRangeOk(doc.URI, *inoChange.Range) + if !ok { + return nil, errors.Errorf("invalid change range %s:%s", doc.URI, *inoChange.Range) + } - log.Println("--! DIRTY CHANGE, force sketch rebuild!") + // Detect changes in critical lines (for example function definitions) + // and trigger arduino-preprocessing + clangd restart. + dirty := false + for _, sym := range handler.buildSketchSymbols { + if sym.Range.Overlaps(cppRange) { + dirty = true + log.Println("--! DIRTY CHANGE detected using symbol tables, force sketch rebuild!") + break + } + } + if handler.sketchMapper.ApplyTextChange(doc.URI, inoChange) { + dirty = true + log.Println("--! DIRTY CHANGE detected with sketch mapper, force sketch rebuild!") + } + if dirty { handler.scheduleRebuildEnvironment() } @@ -637,10 +651,6 @@ func (handler *InoHandler) didChange(ctx context.Context, req *lsp.DidChangeText // log.Println(handler.sketchMapper.CppText.Text) // log.Println("----------------------") - cppRange, ok := handler.sketchMapper.InoToCppLSPRangeOk(doc.URI, *inoChange.Range) - if !ok { - return nil, errors.Errorf("invalid change range %s:%s", doc.URI, *inoChange.Range) - } cppChange := lsp.TextDocumentContentChangeEvent{ Range: &cppRange, RangeLength: inoChange.RangeLength, diff --git a/lsp/structures.go b/lsp/structures.go index e7a93b6..9b5cb73 100644 --- a/lsp/structures.go +++ b/lsp/structures.go @@ -21,6 +21,21 @@ func (p Position) String() string { return fmt.Sprintf("%d:%d", p.Line, p.Character) } +// In returns true if the Position is within the Range r +func (p Position) In(r Range) bool { + return p.AfterOrEq(r.Start) && p.BeforeOrEq(r.End) +} + +// BeforeOrEq returns true if the Position is before or equal the give Position +func (p Position) BeforeOrEq(q Position) bool { + return p.Line < q.Line || (p.Line == q.Line && p.Character <= q.Character) +} + +// AfterOrEq returns true if the Position is after or equal the give Position +func (p Position) AfterOrEq(q Position) bool { + return p.Line > q.Line || (p.Line == q.Line && p.Character >= q.Character) +} + type Range struct { /** * The range's start position. @@ -37,6 +52,11 @@ func (r Range) String() string { return fmt.Sprintf("%s-%s", r.Start, r.End) } +// Overlaps returns true if the Range overlaps with the given Range p +func (r Range) Overlaps(p Range) bool { + return r.Start.In(p) || r.End.In(p) || p.Start.In(r) || p.End.In(r) +} + type Location struct { URI DocumentURI `json:"uri"` Range Range `json:"range"`