Skip to content

Commit dec44e9

Browse files
committed
Introduced lsp.Client/Server and big improvement in logging
1 parent 63c7ad1 commit dec44e9

File tree

7 files changed

+1456
-1165
lines changed

7 files changed

+1456
-1165
lines changed

Diff for: handler/builder.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/pkg/errors"
1414
"go.bug.st/json"
1515
"go.bug.st/lsp"
16+
"go.bug.st/lsp/jsonrpc"
1617
)
1718

1819
func (handler *INOLanguageServer) scheduleRebuildEnvironment() {
@@ -23,8 +24,7 @@ func (handler *INOLanguageServer) scheduleRebuildEnvironment() {
2324
}
2425

2526
func (handler *INOLanguageServer) rebuildEnvironmentLoop() {
26-
defer streams.CatchAndLogPanic()
27-
logger := streams.NewPrefixLogger(color.New(color.FgHiMagenta), "RBLD---")
27+
logger := NewLSPFunctionLogger(color.HiMagentaString, "RBLD---")
2828

2929
grabDeadline := func() *time.Time {
3030
handler.rebuildSketchDeadlineMutex.Lock()
@@ -85,7 +85,7 @@ func (handler *INOLanguageServer) rebuildEnvironmentLoop() {
8585
}
8686
}
8787

88-
func (handler *INOLanguageServer) generateBuildEnvironment(logger streams.PrefixLogger, buildPath *paths.Path) error {
88+
func (handler *INOLanguageServer) generateBuildEnvironment(logger jsonrpc.FunctionLogger, buildPath *paths.Path) error {
8989
sketchDir := handler.sketchRoot
9090
fqbn := handler.config.SelectedBoard.Fqbn
9191

@@ -130,7 +130,7 @@ func (handler *INOLanguageServer) generateBuildEnvironment(logger streams.Prefix
130130
cmdOutput := &bytes.Buffer{}
131131
cmd.RedirectStdoutTo(cmdOutput)
132132
cmd.SetDirFromPath(sketchDir)
133-
logger("running: %s", strings.Join(args, " "))
133+
logger.Logf("running: %s", strings.Join(args, " "))
134134
if err := cmd.Run(); err != nil {
135135
return errors.Errorf("running %s: %s", strings.Join(args, " "), err)
136136
}
@@ -150,7 +150,7 @@ func (handler *INOLanguageServer) generateBuildEnvironment(logger streams.Prefix
150150
if err := json.Unmarshal(cmdOutput.Bytes(), &res); err != nil {
151151
return errors.Errorf("parsing arduino-cli output: %s", err)
152152
}
153-
logger("arduino-cli output: %s", cmdOutput)
153+
logger.Logf("arduino-cli output: %s", cmdOutput)
154154

155155
return nil
156156
}

Diff for: handler/clangd_client.go

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package handler
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"io"
7+
"os"
8+
"strings"
9+
10+
"github.com/arduino/arduino-cli/executils"
11+
"github.com/arduino/arduino-language-server/streams"
12+
"github.com/arduino/go-paths-helper"
13+
"go.bug.st/json"
14+
"go.bug.st/lsp"
15+
"go.bug.st/lsp/jsonrpc"
16+
)
17+
18+
type ClangdClient struct {
19+
conn *lsp.Client
20+
handler *INOLanguageServer
21+
}
22+
23+
func NewClangdClient(logger jsonrpc.FunctionLogger,
24+
buildPath, buildSketchCpp, dataFolder *paths.Path,
25+
connectionClosedCB func(),
26+
inoLanguageServer *INOLanguageServer,
27+
) *ClangdClient {
28+
clangdStdout, clangdStdin, clangdStderr := startClangd(logger, buildPath, buildSketchCpp, dataFolder)
29+
clangdStdio := streams.NewReadWriteCloser(clangdStdin, clangdStdout)
30+
if enableLogging {
31+
clangdStdio = streams.LogReadWriteCloserAs(clangdStdio, "inols-clangd.log")
32+
go io.Copy(streams.OpenLogFileAs("inols-clangd-err.log"), clangdStderr)
33+
} else {
34+
go io.Copy(os.Stderr, clangdStderr)
35+
}
36+
37+
client := &ClangdClient{
38+
handler: inoLanguageServer,
39+
}
40+
client.conn = lsp.NewClient(clangdStdio, clangdStdio, client)
41+
client.conn.SetLogger(&LSPLogger{IncomingPrefix: "IDE LS <-- Clangd", OutgoingPrefix: "IDE LS --> Clangd"})
42+
go func() {
43+
defer streams.CatchAndLogPanic()
44+
client.conn.Run()
45+
connectionClosedCB()
46+
}()
47+
48+
return client
49+
}
50+
51+
func startClangd(logger jsonrpc.FunctionLogger, compileCommandsDir, sketchCpp, dataFolder *paths.Path) (io.WriteCloser, io.ReadCloser, io.ReadCloser) {
52+
// Start clangd
53+
args := []string{
54+
globalClangdPath,
55+
"-log=verbose",
56+
fmt.Sprintf(`--compile-commands-dir=%s`, compileCommandsDir),
57+
}
58+
if dataFolder != nil {
59+
args = append(args, fmt.Sprintf("-query-driver=%s", dataFolder.Join("packages", "**")))
60+
}
61+
logger.Logf(" Starting clangd: %s", strings.Join(args, " "))
62+
if clangdCmd, err := executils.NewProcess(args...); err != nil {
63+
panic("starting clangd: " + err.Error())
64+
} else if clangdIn, err := clangdCmd.StdinPipe(); err != nil {
65+
panic("getting clangd stdin: " + err.Error())
66+
} else if clangdOut, err := clangdCmd.StdoutPipe(); err != nil {
67+
panic("getting clangd stdout: " + err.Error())
68+
} else if clangdErr, err := clangdCmd.StderrPipe(); err != nil {
69+
panic("getting clangd stderr: " + err.Error())
70+
} else if err := clangdCmd.Start(); err != nil {
71+
panic("running clangd: " + err.Error())
72+
} else {
73+
return clangdIn, clangdOut, clangdErr
74+
}
75+
}
76+
77+
func (client *ClangdClient) Close() {
78+
panic("unimplemented")
79+
}
80+
81+
// The following are events incoming from Clangd
82+
83+
func (client *ClangdClient) WindowShowMessageRequest(context.Context, jsonrpc.FunctionLogger, *lsp.ShowMessageRequestParams) (*lsp.MessageActionItem, *jsonrpc.ResponseError) {
84+
panic("unimplemented")
85+
}
86+
87+
func (client *ClangdClient) WindowShowDocument(context.Context, jsonrpc.FunctionLogger, *lsp.ShowDocumentParams) (*lsp.ShowDocumentResult, *jsonrpc.ResponseError) {
88+
panic("unimplemented")
89+
}
90+
91+
func (client *ClangdClient) WindowWorkDoneProgressCreate(ctx context.Context, logger jsonrpc.FunctionLogger, params *lsp.WorkDoneProgressCreateParams) *jsonrpc.ResponseError {
92+
return client.handler.WindowWorkDoneProgressCreateFromClangd(ctx, logger, params)
93+
}
94+
95+
func (client *ClangdClient) ClientRegisterCapability(context.Context, jsonrpc.FunctionLogger, *lsp.RegistrationParams) *jsonrpc.ResponseError {
96+
panic("unimplemented")
97+
}
98+
99+
func (client *ClangdClient) ClientUnregisterCapability(context.Context, jsonrpc.FunctionLogger, *lsp.UnregistrationParams) *jsonrpc.ResponseError {
100+
panic("unimplemented")
101+
}
102+
103+
func (client *ClangdClient) WorkspaceWorkspaceFolders(context.Context, jsonrpc.FunctionLogger) ([]lsp.WorkspaceFolder, *jsonrpc.ResponseError) {
104+
panic("unimplemented")
105+
}
106+
107+
func (client *ClangdClient) WorkspaceConfiguration(context.Context, jsonrpc.FunctionLogger, *lsp.ConfigurationParams) ([]json.RawMessage, *jsonrpc.ResponseError) {
108+
panic("unimplemented")
109+
}
110+
111+
func (client *ClangdClient) WorkspaceApplyEdit(context.Context, jsonrpc.FunctionLogger, *lsp.ApplyWorkspaceEditParams) (*lsp.ApplyWorkspaceEditResult, *jsonrpc.ResponseError) {
112+
panic("unimplemented")
113+
}
114+
115+
func (client *ClangdClient) WorkspaceCodeLensRefresh(context.Context, jsonrpc.FunctionLogger) *jsonrpc.ResponseError {
116+
panic("unimplemented")
117+
}
118+
119+
func (client *ClangdClient) Progress(logger jsonrpc.FunctionLogger, progress *lsp.ProgressParams) {
120+
client.handler.ProgressFromClangd(logger, progress)
121+
}
122+
123+
func (client *ClangdClient) LogTrace(jsonrpc.FunctionLogger, *lsp.LogTraceParams) {
124+
panic("unimplemented")
125+
}
126+
127+
func (client *ClangdClient) WindowShowMessage(jsonrpc.FunctionLogger, *lsp.ShowMessageParams) {
128+
panic("unimplemented")
129+
}
130+
131+
func (client *ClangdClient) WindowLogMessage(jsonrpc.FunctionLogger, *lsp.LogMessageParams) {
132+
panic("unimplemented")
133+
}
134+
135+
func (client *ClangdClient) TelemetryEvent(jsonrpc.FunctionLogger, json.RawMessage) {
136+
panic("unimplemented")
137+
}
138+
139+
func (client *ClangdClient) TextDocumentPublishDiagnostics(logger jsonrpc.FunctionLogger, params *lsp.PublishDiagnosticsParams) {
140+
client.handler.PublishDiagnosticsFromClangd(logger, params)
141+
}

0 commit comments

Comments
 (0)