Skip to content

Commit e8b6ccc

Browse files
authored
Merge pull request #63 from bcmi-labs/tmp-folder
Use a different temp folder to preprocess/generate compiler_command.json
2 parents 248f8fd + 397053c commit e8b6ccc

File tree

3 files changed

+68
-27
lines changed

3 files changed

+68
-27
lines changed

Diff for: handler/builder.go

+11-9
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ func (handler *InoHandler) rebuildEnvironmentLoop() {
8585
}
8686
}
8787

88-
func (handler *InoHandler) generateBuildEnvironment() (*paths.Path, error) {
88+
func (handler *InoHandler) generateBuildEnvironment(buildPath *paths.Path) error {
8989
sketchDir := handler.sketchRoot
9090
fqbn := handler.config.SelectedBoard.Fqbn
9191

@@ -97,15 +97,15 @@ func (handler *InoHandler) generateBuildEnvironment() (*paths.Path, error) {
9797
for uri, trackedFile := range handler.docs {
9898
rel, err := paths.New(uri).RelFrom(handler.sketchRoot)
9999
if err != nil {
100-
return nil, errors.WithMessage(err, "dumping tracked files")
100+
return errors.WithMessage(err, "dumping tracked files")
101101
}
102102
data.Overrides[rel.String()] = trackedFile.Text
103103
}
104104
var overridesJSON *paths.Path
105105
if jsonBytes, err := json.MarshalIndent(data, "", " "); err != nil {
106-
return nil, errors.WithMessage(err, "dumping tracked files")
106+
return errors.WithMessage(err, "dumping tracked files")
107107
} else if tmpFile, err := paths.WriteToTempFile(jsonBytes, nil, ""); err != nil {
108-
return nil, errors.WithMessage(err, "dumping tracked files")
108+
return errors.WithMessage(err, "dumping tracked files")
109109
} else {
110110
overridesJSON = tmpFile
111111
defer tmpFile.Remove()
@@ -118,21 +118,23 @@ func (handler *InoHandler) generateBuildEnvironment() (*paths.Path, error) {
118118
"--only-compilation-database",
119119
"--clean",
120120
"--source-override", overridesJSON.String(),
121+
"--build-path", buildPath.String(),
121122
"--format", "json",
122123
sketchDir.String(),
123124
}
124125
cmd, err := executils.NewProcess(args...)
125126
if err != nil {
126-
return nil, errors.Errorf("running %s: %s", strings.Join(args, " "), err)
127+
return errors.Errorf("running %s: %s", strings.Join(args, " "), err)
127128
}
128129
cmdOutput := &bytes.Buffer{}
129130
cmd.RedirectStdoutTo(cmdOutput)
130131
cmd.SetDirFromPath(sketchDir)
131132
log.Println("running: ", strings.Join(args, " "))
132133
if err := cmd.Run(); err != nil {
133-
return nil, errors.Errorf("running %s: %s", strings.Join(args, " "), err)
134+
return errors.Errorf("running %s: %s", strings.Join(args, " "), err)
134135
}
135136

137+
// Currently those values are not used, keeping here for future improvements
136138
type cmdBuilderRes struct {
137139
BuildPath *paths.Path `json:"build_path"`
138140
UsedLibraries []*libraries.Library
@@ -145,9 +147,9 @@ func (handler *InoHandler) generateBuildEnvironment() (*paths.Path, error) {
145147
}
146148
var res cmdRes
147149
if err := json.Unmarshal(cmdOutput.Bytes(), &res); err != nil {
148-
return nil, errors.Errorf("parsing arduino-cli output: %s", err)
150+
return errors.Errorf("parsing arduino-cli output: %s", err)
149151
}
150-
// Return only the build path
151152
log.Println("arduino-cli output:", cmdOutput)
152-
return res.BuilderResult.BuildPath, nil
153+
154+
return nil
153155
}

Diff for: handler/handler.go

+44-16
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ type InoHandler struct {
5151
clangdNotificationCount int64
5252
progressHandler *ProgressProxyHandler
5353

54+
closing chan bool
5455
clangdStarted *sync.Cond
5556
dataMux sync.RWMutex
5657
lspInitializeParams *lsp.InitializeParams
@@ -119,6 +120,7 @@ func NewInoHandler(stdio io.ReadWriteCloser, board lsp.Board) *InoHandler {
119120
handler := &InoHandler{
120121
docs: map[string]*lsp.TextDocumentItem{},
121122
inoDocsWithDiagnostics: map[lsp.DocumentURI]bool{},
123+
closing: make(chan bool),
122124
config: lsp.BoardConfig{
123125
SelectedBoard: board,
124126
},
@@ -131,10 +133,18 @@ func NewInoHandler(stdio io.ReadWriteCloser, board lsp.Board) *InoHandler {
131133
jsonrpc2.OnSend(streams.JSONRPCConnLogOnSend("IDE <-- LS CL:")),
132134
)
133135

136+
if buildPath, err := paths.MkTempDir("", "arduino-language-server"); err != nil {
137+
log.Fatalf("Could not create temp folder: %s", err)
138+
} else {
139+
handler.buildPath = buildPath.Canonical()
140+
handler.buildSketchRoot = buildPath.Join("sketch").Canonical()
141+
}
142+
134143
handler.progressHandler = NewProgressProxy(handler.StdioConn)
135144

136145
if enableLogging {
137146
log.Println("Initial board configuration:", board)
147+
log.Println("Language server build path:", handler.buildPath)
138148
}
139149

140150
go handler.rebuildEnvironmentLoop()
@@ -150,10 +160,30 @@ type FileData struct {
150160
version int
151161
}
152162

153-
// StopClangd closes the connection to the clangd process.
154-
func (handler *InoHandler) StopClangd() {
155-
handler.ClangdConn.Close()
156-
handler.ClangdConn = nil
163+
// Close closes all the json-rpc connections.
164+
func (handler *InoHandler) Close() {
165+
if handler.ClangdConn != nil {
166+
handler.ClangdConn.Close()
167+
handler.ClangdConn = nil
168+
}
169+
if handler.closing != nil {
170+
close(handler.closing)
171+
handler.closing = nil
172+
}
173+
}
174+
175+
// CloseNotify returns a channel that is closed when the InoHandler is closed
176+
func (handler *InoHandler) CloseNotify() <-chan bool {
177+
return handler.closing
178+
}
179+
180+
// CleanUp performs cleanup of the workspace and temp files create by the language server
181+
func (handler *InoHandler) CleanUp() {
182+
if handler.buildPath != nil {
183+
log.Printf("removing buildpath")
184+
handler.buildPath.RemoveAll()
185+
handler.buildPath = nil
186+
}
157187
}
158188

159189
// HandleMessageFromIDE handles a message received from the IDE client (via stdio).
@@ -473,12 +503,14 @@ func (handler *InoHandler) HandleMessageFromIDE(ctx context.Context, conn *jsonr
473503
// Exit the process and trigger a restart by the client in case of a severe error
474504
if err.Error() == "context deadline exceeded" {
475505
log.Println(prefix + "Timeout exceeded while waiting for a reply from clangd.")
476-
handler.exit()
506+
log.Println(prefix + "Please restart the language server.")
507+
handler.Close()
477508
}
478509
if strings.Contains(err.Error(), "non-added document") || strings.Contains(err.Error(), "non-added file") {
479510
log.Printf(prefix + "The clangd process has lost track of the open document.")
480511
log.Printf(prefix+" %s", err)
481-
handler.exit()
512+
log.Println(prefix + "Please restart the language server.")
513+
handler.Close()
482514
}
483515
}
484516

@@ -489,12 +521,6 @@ func (handler *InoHandler) HandleMessageFromIDE(ctx context.Context, conn *jsonr
489521
return result, err
490522
}
491523

492-
func (handler *InoHandler) exit() {
493-
log.Println("Please restart the language server.")
494-
handler.StopClangd()
495-
os.Exit(1)
496-
}
497-
498524
func (handler *InoHandler) initializeWorkbench(ctx context.Context, params *lsp.InitializeParams) error {
499525
currCppTextVersion := 0
500526
if params != nil {
@@ -507,10 +533,7 @@ func (handler *InoHandler) initializeWorkbench(ctx context.Context, params *lsp.
507533
currCppTextVersion = handler.sketchMapper.CppText.Version
508534
}
509535

510-
if buildPath, err := handler.generateBuildEnvironment(); err == nil {
511-
handler.buildPath = buildPath
512-
handler.buildSketchRoot = buildPath.Join("sketch").Canonical()
513-
} else {
536+
if err := handler.generateBuildEnvironment(handler.buildPath); err != nil {
514537
return err
515538
}
516539
handler.buildSketchCpp = handler.buildSketchRoot.Join(handler.sketchName + ".ino.cpp")
@@ -566,6 +589,11 @@ func (handler *InoHandler) initializeWorkbench(ctx context.Context, params *lsp.
566589
handler.ClangdConn = jsonrpc2.NewConn(context.Background(), clangdStream, clangdHandler,
567590
jsonrpc2.OnRecv(streams.JSONRPCConnLogOnRecv("IDE LS <-- CL:")),
568591
jsonrpc2.OnSend(streams.JSONRPCConnLogOnSend("IDE LS --> CL:")))
592+
go func() {
593+
<-handler.ClangdConn.DisconnectNotify()
594+
log.Printf("Lost connection with clangd!")
595+
handler.Close()
596+
}()
569597

570598
// Send initialization command to clangd
571599
ctx, cancel := context.WithTimeout(context.Background(), time.Second)

Diff for: main.go

+13-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"io"
66
"log"
77
"os"
8+
"os/signal"
89

910
"github.com/arduino/go-paths-helper"
1011
"github.com/bcmi-labs/arduino-language-server/handler"
@@ -53,6 +54,16 @@ func main() {
5354
}
5455

5556
inoHandler := handler.NewInoHandler(stdio, initialBoard)
56-
defer inoHandler.StopClangd()
57-
<-inoHandler.StdioConn.DisconnectNotify()
57+
58+
// Intercept kill signal
59+
c := make(chan os.Signal, 2)
60+
signal.Notify(c, os.Interrupt, os.Kill)
61+
62+
select {
63+
case <-inoHandler.CloseNotify():
64+
case <-c:
65+
log.Println("INTERRUPTED")
66+
}
67+
inoHandler.CleanUp()
68+
inoHandler.Close()
5869
}

0 commit comments

Comments
 (0)