8000 Fix for the lsp crashing upon a textDocument/definition on untracked files by iexavl · Pull Request #208 · arduino/arduino-language-server · GitHub
[go: up one dir, main page]

Skip to content

Fix for the lsp crashing upon a textDocument/definition on untracked files #208

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

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
42 changes: 35 additions & 7 deletions ls/ls.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ type Config struct {
Jobs int
}

var extToFileType = map[string]string{
".h": "cpp",
".hpp": "cpp",
}

type translationOpts struct {
loadRelToIde bool
}

var yellow = color.New(color.FgHiYellow)

func (ls *INOLanguageServer) writeLock(logger jsonrpc.FunctionLogger, requireClangd bool) {
Expand Down Expand Up @@ -603,7 +612,8 @@ func (ls *INOLanguageServer) textDocumentDefinitionReqFromIDE(ctx context.Contex

var ideLocations []lsp.Location
if clangLocations != nil {
ideLocations, err = ls.clang2IdeLocationsArray(logger, clangLocations)
opts := translationOpts{loadRelToIde: true}
ideLocations, err = ls.clang2IdeLocationsArray2(logger, clangLocations, &opts)
if err != nil {
logger.Logf("Error: %v", err)
ls.Close()
Expand Down Expand Up @@ -989,15 +999,13 @@ func (ls *INOLanguageServer) exitNotifFromIDE(logger jsonrpc.FunctionLogger) {
ls.Close()
}

func (ls *INOLanguageServer) textDocumentDidOpenNotifFromIDE(logger jsonrpc.FunctionLogger, ideParam *lsp.DidOpenTextDocumentParams) {
ls.writeLock(logger, true)
defer ls.writeUnlock(logger)
func (ls *INOLanguageServer) implTextDocumentDidOpenNotifFromIDE(logger jsonrpc.FunctionLogger, ideParam lsp.TextDocumentItem) *jsonrpc.ResponseError {

ideTextDocItem := ideParam.TextDocument
ideTextDocItem := ideParam
clangURI, _, err := ls.ide2ClangDocumentURI(logger, ideTextDocItem.URI)
if err != nil {
logger.Logf("Error: %s", err)
return
return &jsonrpc.ResponseError{Code: jsonrpc.ErrorCodesInternalError, Message: err.Error()}
}

if ls.ideURIIsPartOfTheSketch(ideTextDocItem.URI) {
Expand All @@ -1017,7 +1025,7 @@ func (ls *INOLanguageServer) textDocumentDidOpenNotifFromIDE(logger jsonrpc.Func
// Notify clangd that sketchCpp has been opened only once
if ls.sketchTrackedFilesCount != 1 {
logger.Logf("Clang already notified, do not notify it anymore")
return
return nil
}
}

Expand Down Expand Up @@ -1045,7 +1053,17 @@ func (ls *INOLanguageServer) textDocumentDidOpenNotifFromIDE(logger jsonrpc.Func
logger.Logf("Error sending notification to clangd server: %v", err)
logger.Logf("Please restart the language server.")
ls.Close()
return &jsonrpc.ResponseError{Code: jsonrpc.ErrorCodesInternalError, Message: err.Error()}

}
return nil

}
10000
func (ls *INOLanguageServer) textDocumentDidOpenNotifFromIDE(logger jsonrpc.FunctionLogger, ideParam *lsp.DidOpenTextDocumentParams) {
ls.writeLock(logger, true)
defer ls.writeUnlock(logger)
ls.implTextDocumentDidOpenNotifFromIDE(logger, ideParam.TextDocument)
}

func (ls *INOLanguageServer) textDocumentDidChangeNotifFromIDE(logger jsonrpc.FunctionLogger, ideParams *lsp.DidChangeTextDocumentParams) {
Expand Down Expand Up @@ -1619,6 +1637,16 @@ type UnknownURIError struct {
URI lsp.DocumentURI
}

// UnknownFileExtensionError when a file extension isn't recognized
// and a file with it has to be opened.
type UnknownFileExtensionError struct {
extension string
}

func (e *UnknownURIError) Error() string {
return "Document is not available: " + e.URI.String()
}

func (e *UnknownFileExtensionError) Error() string {
return "Unknown file extension " + e.extension
}
36 changes: 32 additions & 4 deletions ls/ls_clang_to_ide.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@ func (ls *INOLanguageServer) clangURIRefersToIno(clangURI lsp.DocumentURI) bool
return clangURI.AsPath().EquivalentTo(ls.buildSketchCpp)
}

func (ls *INOLanguageServer) clang2IdeRangeAndDocumentURI(logger jsonrpc.FunctionLogger, clangURI lsp.DocumentURI, clangRange lsp.Range) (lsp.DocumentURI, lsp.Range, bool, error) {
return ls.clang2IdeRangeAndDocumentURI2(logger, clangURI, clangRange, nil)
}

// Convert Range and DocumentURI from Clang to IDE.
// Returns:
// - The IDE DocumentURI and Range
// - a boolean that is true if the clang range is in the preprocessed area of the sketch
// - an error
func (ls *INOLanguageServer) clang2IdeRangeAndDocumentURI(logger jsonrpc.FunctionLogger, clangURI lsp.DocumentURI, clangRange lsp.Range) (lsp.DocumentURI, lsp.Range, bool, error) {
func (ls *INOLanguageServer) clang2IdeRangeAndDocumentURI2(logger jsonrpc.FunctionLogger, clangURI lsp.DocumentURI, clangRange lsp.Range, opts *translationOpts) (lsp.DocumentURI, lsp.Range, bool, error) {
// Sketchbook/Sketch/Sketch.ino <-> build-path/sketch/Sketch.ino.cpp
// Sketchbook/Sketch/AnotherTab.ino <-> build-path/sketch/Sketch.ino.cpp (different section from above)
if ls.clangURIRefersToIno(clangURI) {
Expand Down Expand Up @@ -80,7 +84,25 @@ func (ls *INOLanguageServer) clang2IdeRangeAndDocumentURI(logger jsonrpc.Functio
return lsp.NilURI, lsp.NilRange, false, err
}
idePath := ls.sketchRoot.JoinPath(rel).String()
ideURI, err := ls.idePathToIdeURI(logger, idePath)

var ideURI lsp.DocumentURI
if opts == nil || !opts.loadRelToIde {
ideURI, err = ls.idePathToIdeURI(logger, idePath)
} else {
doc, ok := ls.trackedIdeDocs[idePath]
if !ok {
var shouldOpen bool
doc, shouldOpen, err = makeTextDocumentItem(logger, idePath)
if err != nil {
logger.Logf("ERROR: could not open '%s': %s", idePath, err)
}
if shouldOpen {
ls.implTextDocumentDidOpenNotifFromIDE(logger, doc)
}

}
ideURI = doc.URI
}
if ideRange.End.Line > 0 {
ideRange.End.Line--
}
Expand Down Expand Up @@ -296,9 +318,12 @@ func (ls *INOLanguageServer) cland2IdeTextEdits(logger jsonrpc.FunctionLogger, c
}

func (ls *INOLanguageServer) clang2IdeLocationsArray(logger jsonrpc.FunctionLogger, clangLocations []lsp.Location) ([]lsp.Location, error) {
return ls.clang2IdeLocationsArray2(logger, clangLocations, nil)
}
func (ls *INOLanguageServer) clang2IdeLocationsArray2(logger jsonrpc.FunctionLogger, clangLocations []lsp.Location, opts *translationOpts) ([]lsp.Location, error) {
ideLocations := []lsp.Location{}
for _, clangLocation := range clangLocations {
ideLocation, inPreprocessed, err := ls.clang2IdeLocation(logger, clangLocation)
ideLocation, inPreprocessed, err := ls.clang2IdeLocation2(logger, clangLocation, opts)
if err != nil {
logger.Logf("ERROR converting location %s: %s", clangLocation, err)
return nil, err
Expand All @@ -313,7 +338,10 @@ func (ls *INOLanguageServer) clang2IdeLocationsArray(logger jsonrpc.FunctionLogg
}

func (ls *INOLanguageServer) clang2IdeLocation(logger jsonrpc.FunctionLogger, clangLocation lsp.Location) (lsp.Location, bool, error) {
ideURI, ideRange, inPreprocessed, err := ls.clang2IdeRangeAndDocumentURI(logger, clangLocation.URI, clangLocation.Range)
return ls.clang2IdeLocation2(logger, clangLocation, nil)
}
func (ls *INOLanguageServer) clang2IdeLocation2(logger jsonrpc.FunctionLogger, clangLocation lsp.Location, opts *translationOpts) (lsp.Location, bool, error) {
ideURI, ideRange, inPreprocessed, err := ls.clang2IdeRangeAndDocumentURI2(logger, clangLocation.URI, clangLocation.Range, opts)
return lsp.Location{
URI: ideURI,
Range: ideRange,
Expand Down
30 changes: 30 additions & 0 deletions ls/ls_ide_to_clang.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,43 @@

import (
"fmt"
"os"
"path/filepath"

"github.com/arduino/arduino-language-server/sourcemapper"
"go.bug.st/lsp"
"go.bug.st/lsp/jsonrpc"
)

func getFileType(ext string) string {
if fileType, ok := extToFileType[ext]; ok {
return fileType
}
return "unknown"
}
func (ls *INOLanguageServer) idePathToIdeURI(logger jsonrpc.FunctionLogger, inoPath string) (lsp.DocumentURI, error) {
return ls.idePathToIdeURI2(logger, inoPath, nil)

Check failure on line 35 in ls/ls_ide_to_clang.go

View workflow job for this annotation

GitHub Actions / build (Linux_64bit, ubuntu-latest)

too many arguments in call to ls.idePathToIdeURI2

Check failure on line 35 in ls/ls_ide_to_clang.go

View workflow job for this annotation

GitHub Actions / check-errors (./)

too many arguments in call to ls.idePathToIdeURI2
}

func makeTextDocumentItem(logger jsonrpc.FunctionLogger, path string) (lsp.TextDocumentItem, bool, error) {
ext := filepath.Ext(path)
filetype := getFileType(path)
uri := lsp.NewDocumentURI(path)
if filetype == "unknown" {
return lsp.TextDocumentItem{URI: uri, LanguageID: filetype}, false, &UnknownFileExtensionError{ext}
}
languageID := filetype
version := 0

text, err := os.ReadFile(path)
if err != nil {
logger.Logf("Could not read file: %v", err)
return lsp.TextDocumentItem{}, false, err
}
return lsp.TextDocumentItem{URI: uri, LanguageID: languageID, Version: version, Text: string(text)}, true, nil

}
func (ls *INOLanguageServer) idePathToIdeURI2(logger jsonrpc.FunctionLogger, inoPath string) (lsp.DocumentURI, error) {
if inoPath == sourcemapper.NotIno.File {
return sourcemapper.NotInoURI, nil
}
Expand Down
Loading
0