Skip to content

Commit 2d7539c

Browse files
committed
Language server now skips libraries detection while editing
A full build is made only at language server startup. Other full builds must be performed by the IDE and build_path should be passed to the LS with a custom command.
1 parent 047d50e commit 2d7539c

File tree

3 files changed

+59
-11
lines changed

3 files changed

+59
-11
lines changed

ls/builder.go

+17-10
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func (r *SketchRebuilder) rebuilderLoop() {
9292
r.cancel = cancel
9393
r.mutex.Unlock()
9494

95-
if err := r.doRebuild(ctx, logger); err != nil {
95+
if err := r.doRebuild(ctx, false, logger); err != nil {
9696
logger.Logf("Error: %s", err)
9797
}
9898

@@ -104,10 +104,16 @@ func (r *SketchRebuilder) rebuilderLoop() {
104104
}
105105
}
106106

107-
func (r *SketchRebuilder) doRebuild(ctx context.Context, logger jsonrpc.FunctionLogger) error {
107+
func (r *SketchRebuilder) doRebuild(ctx context.Context, fullRebuild bool, logger jsonrpc.FunctionLogger) error {
108108
ls := r.ls
109+
var buildPath *paths.Path
110+
if fullRebuild {
111+
buildPath = ls.fullBuildPath
112+
} else {
113+
buildPath = ls.buildPath
114+
}
109115

110-
if success, err := ls.generateBuildEnvironment(ctx, logger); err != nil {
116+
if success, err := ls.generateBuildEnvironment(ctx, fullRebuild, buildPath, logger); err != nil {
111117
return err
112118
} else if !success {
113119
return fmt.Errorf("build failed")
@@ -123,9 +129,7 @@ func (r *SketchRebuilder) doRebuild(ctx context.Context, logger jsonrpc.Function
123129
default:
124130
}
125131

126-
if err := ls.buildPath.Join("compile_commands.json").CopyTo(ls.compileCommandsDir.Join("compile_commands.json")); err != nil {
127-
logger.Logf("ERROR: updating compile_commands: %s", err)
128-
}
132+
ls.CopyBuildResults(logger, buildPath, fullRebuild)
129133

130134
if cppContent, err := ls.buildSketchCpp.ReadFile(); err == nil {
131135
oldVesrion := ls.sketchMapper.CppText.Version
@@ -166,11 +170,10 @@ func (r *SketchRebuilder) doRebuild(ctx context.Context, logger jsonrpc.Function
166170
return nil
167171
}
168172

169-
func (ls *INOLanguageServer) generateBuildEnvironment(ctx context.Context, logger jsonrpc.FunctionLogger) (bool, error) {
173+
func (ls *INOLanguageServer) generateBuildEnvironment(ctx context.Context, fullBuild bool, buildPath *paths.Path, logger jsonrpc.FunctionLogger) (bool, error) {
170174
// Extract all build information from language server status
171175
ls.readLock(logger, false)
172176
sketchRoot := ls.sketchRoot
173-
buildPath := ls.buildPath
174177
config := ls.config
175178
type overridesFile struct {
176179
Overrides map[string]string `json:"overrides"`
@@ -204,6 +207,7 @@ func (ls *INOLanguageServer) generateBuildEnvironment(ctx context.Context, logge
204207
BuildPath: buildPath.String(),
205208
CreateCompilationDatabaseOnly: true,
206209
Verbose: true,
210+
SkipLibrariesDiscovery: !fullBuild,
207211
}
208212
compileReqJson, _ := json.MarshalIndent(compileReq, "", " ")
209213
logger.Logf("Running build with: %s", string(compileReqJson))
@@ -264,9 +268,12 @@ func (ls *INOLanguageServer) generateBuildEnvironment(ctx context.Context, logge
264268
"--source-override", overridesJSON.String(),
265269
"--build-path", buildPath.String(),
266270
"--format", "json",
267-
//"--clean",
268-
sketchRoot.String(),
269271
}
272+
if !fullBuild {
273+
args = append(args, "--skip-libraries-discovery")
274+
}
275+
args = append(args, sketchRoot.String())
276+
270277
cmd, err := executils.NewProcess(nil, args...)
271278
if err != nil {
272279
return false, errors.Errorf("running %s: %s", strings.Join(args, " "), err)

ls/ls.go

+26-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ type INOLanguageServer struct {
4040
buildPath *paths.Path
4141
buildSketchRoot *paths.Path
4242
buildSketchCpp *paths.Path
43+
fullBuildPath *paths.Path
4344
sketchRoot *paths.Path
4445
sketchName string
4546
sketchMapper *sourcemapper.SketchMapper
@@ -136,9 +137,16 @@ func NewINOLanguageServer(stdin io.Reader, stdout io.Writer, config *Config) *IN
136137
ls.buildSketchRoot = ls.buildPath.Join("sketch")
137138
}
138139

140+
if tmp, err := paths.MkTempDir("", "arduino-language-server"); err != nil {
141+
log.Fatalf("Could not create temp folder: %s", err)
142+
} else {
143+
ls.fullBuildPath = tmp.Canonical()
144+
}
145+
139146
logger.Logf("Initial board configuration: %s", ls.config.Fqbn)
140147
logger.Logf("Language server build path: %s", ls.buildPath)
141148
logger.Logf("Language server build sketch root: %s", ls.buildSketchRoot)
149+
logger.Logf("Language server FULL build path: %s", ls.fullBuildPath)
142150
logger.Logf("Language server compile-commands: %s", ls.compileCommandsDir.Join("compile_commands.json"))
143151

144152
ls.IDE = NewIDELSPServer(logger, stdin, stdout, ls)
@@ -166,7 +174,7 @@ func (ls *INOLanguageServer) InitializeReqFromIDE(ctx context.Context, logger js
166174
ls.sketchName = ls.sketchRoot.Base()
167175
ls.buildSketchCpp = ls.buildSketchRoot.Join(ls.sketchName + ".ino.cpp")
168176

169-
if success, err := ls.generateBuildEnvironment(context.Background(), logger); err != nil {
177+
if success, err := ls.generateBuildEnvironment(context.Background(), true, ls.buildPath, logger); err != nil {
170178
logger.Logf("error starting clang: %s", err)
171179
return
172180
} else if !success {
@@ -1172,6 +1180,23 @@ func (ls *INOLanguageServer) TextDocumentDidCloseNotifFromIDE(logger jsonrpc.Fun
11721180
}
11731181
}
11741182

1183+
func (ls *INOLanguageServer) FullBuildCompletedFromIDE(logger jsonrpc.FunctionLogger, params *FullBuildResult) {
1184+
ls.writeLock(logger, true)
1185+
defer ls.writeUnlock(logger)
1186+
ls.CopyBuildResults(logger, params.BuildPath, true)
1187+
}
1188+
1189+
func (ls *INOLanguageServer) CopyBuildResults(logger jsonrpc.FunctionLogger, buildPath *paths.Path, fullRebuild bool) {
1190+
if err := buildPath.Join("compile_commands.json").CopyTo(ls.compileCommandsDir.Join("compile_commands.json")); err != nil {
1191+
logger.Logf("ERROR: updating compile_commands: %s", err)
1192+
}
1193+
if fullRebuild {
1194+
if err := buildPath.Join("libraries.cache").CopyTo(ls.compileCommandsDir.Join("libraries.cache")); err != nil {
1195+
logger.Logf("ERROR: updating libraires.cache: %s", err)
1196+
}
1197+
}
1198+
}
1199+
11751200
func (ls *INOLanguageServer) PublishDiagnosticsNotifFromClangd(logger jsonrpc.FunctionLogger, clangParams *lsp.PublishDiagnosticsParams) {
11761201
ls.readLock(logger, false)
11771202
defer ls.readUnlock(logger)

ls/lsp_server_ide.go

+16
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"io"
66

7+
"github.com/arduino/go-paths-helper"
78
"github.com/fatih/color"
89
"go.bug.st/json"
910
"go.bug.st/lsp"
@@ -20,6 +21,7 @@ func NewIDELSPServer(logger jsonrpc.FunctionLogger, in io.Reader, out io.Writer,
2021
ls: ls,
2122
}
2223
server.conn = lsp.NewServer(in, out, server)
24+
server.conn.RegisterCustomNotification("arduino/buildCompleted", server.ArduinoBuildCompleted)
2325
server.conn.SetLogger(&LSPLogger{
2426
IncomingPrefix: "IDE --> LS",
2527
OutgoingPrefix: "IDE <-- LS",
@@ -267,3 +269,17 @@ func (server *IDELSPServer) TextDocumentDidSave(logger jsonrpc.FunctionLogger, p
267269
func (server *IDELSPServer) TextDocumentDidClose(logger jsonrpc.FunctionLogger, params *lsp.DidCloseTextDocumentParams) {
268270
server.ls.TextDocumentDidCloseNotifFromIDE(logger, params)
269271
}
272+
273+
// FullBuildResult is a custom notification from the Arduino IDE, sent
274+
type FullBuildResult struct {
275+
BuildPath *paths.Path `json:"build_path"`
276+
}
277+
278+
func (server *IDELSPServer) ArduinoBuildCompleted(logger jsonrpc.FunctionLogger, raw json.RawMessage) {
279+
var params FullBuildResult
280+
if err := json.Unmarshal(raw, &params); err != nil {
281+
logger.Logf("ERROR decoding FullBuildResult: %s", err)
282+
} else {
283+
server.ls.FullBuildCompletedFromIDE(logger, &params)
284+
}
285+
}

0 commit comments

Comments
 (0)