Skip to content

Commit

Permalink
feat: add LSP for FTL
Browse files Browse the repository at this point in the history
Add an LSP that produces document highlights when FTL outputs build errors

this is a work in progress
  • Loading branch information
worstell committed Mar 28, 2024
1 parent afb6a53 commit 5ec9856
Show file tree
Hide file tree
Showing 8 changed files with 281 additions and 20 deletions.
10 changes: 7 additions & 3 deletions buildengine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/TBD54566975/ftl/backend/schema"
"github.com/TBD54566975/ftl/internal/log"
"github.com/TBD54566975/ftl/internal/rpc"
"github.com/TBD54566975/ftl/lsp"
)

type schemaChange struct {
Expand Down Expand Up @@ -190,22 +191,23 @@ func (e *Engine) Deploy(ctx context.Context, replicas int32, waitForDeployOnline
}

// Dev builds and deploys all local modules and watches for changes, redeploying as necessary.
func (e *Engine) Dev(ctx context.Context, period time.Duration) error {
func (e *Engine) Dev(ctx context.Context, period time.Duration, languageServer *lsp.Server) error {
logger := log.FromContext(ctx)

// Build and deploy all modules first.
err := e.buildAndDeploy(ctx, 1, true)
if err != nil {
logger.Errorf(err, "initial deploy failed")
languageServer.Post(err)
}

logger.Infof("All modules deployed, watching for changes...")

// Then watch for changes and redeploy.
return e.watchForModuleChanges(ctx, period)
return e.watchForModuleChanges(ctx, period, languageServer)
}

func (e *Engine) watchForModuleChanges(ctx context.Context, period time.Duration) error {
func (e *Engine) watchForModuleChanges(ctx context.Context, period time.Duration, languageServer *lsp.Server) error {
logger := log.FromContext(ctx)

moduleHashes := map[string][]byte{}
Expand Down Expand Up @@ -243,6 +245,7 @@ func (e *Engine) watchForModuleChanges(ctx context.Context, period time.Duration
err := e.buildAndDeploy(ctx, 1, true, config.Key)
if err != nil {
logger.Errorf(err, "deploy %s failed", config.Key)
languageServer.Post(err)
}
}
case WatchEventProjectRemoved:
Expand All @@ -258,6 +261,7 @@ func (e *Engine) watchForModuleChanges(ctx context.Context, period time.Duration
config := event.Project.Config()
err := e.buildAndDeploy(ctx, 1, true, config.Key)
if err != nil {
languageServer.Post(err)
switch project := event.Project.(type) {
case Module:
logger.Errorf(err, "build and deploy failed for module %q: %v", project.Config().Key, err)
Expand Down
8 changes: 7 additions & 1 deletion cmd/ftl/cmd_dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/TBD54566975/ftl/buildengine"
"github.com/TBD54566975/ftl/common/projectconfig"
"github.com/TBD54566975/ftl/internal/rpc"
"github.com/TBD54566975/ftl/lsp"
)

type devCmd struct {
Expand Down Expand Up @@ -52,6 +53,11 @@ func (d *devCmd) Run(ctx context.Context, projConfig projectconfig.Config) error
})
}

languageServer := lsp.NewServer(ctx)
g.Go(func() error {
return languageServer.Run()
})

err := d.ServeCmd.pollControllerOnine(ctx, client)
if err != nil {
return err
Expand All @@ -62,7 +68,7 @@ func (d *devCmd) Run(ctx context.Context, projConfig projectconfig.Config) error
if err != nil {
return err
}
return engine.Dev(ctx, d.Watch)
return engine.Dev(ctx, d.Watch, languageServer)
})

return g.Wait()
Expand Down
13 changes: 0 additions & 13 deletions examples/go/echo/echo.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,3 @@ func Echo(ctx context.Context, req EchoRequest) (EchoResponse, error) {

return EchoResponse{Message: fmt.Sprintf("Hello, %s!!! It is %s!", req.Name.Default(defaultName.Get(ctx)), tresp.Time)}, nil
}

/*
verb cronJob(Unit) Unit
+cron "0 0 * * *"
*/

//ftl:cron <schedule>
func CronJob(ctx context.Context) error {
_, err := ftl.Call(ctx, Echo, EchoRequest{})
return err
}
15 changes: 15 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,15 @@ require (
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/mattn/go-isatty v0.0.20
github.com/otiai10/copy v1.14.0
github.com/pkg/errors v0.9.1
github.com/radovskyb/watcher v1.0.7
github.com/rs/cors v1.10.1
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
github.com/swaggest/jsonschema-go v0.3.69
github.com/titanous/json5 v1.0.0
github.com/tliron/commonlog v0.2.16
github.com/tliron/glsp v0.2.2
github.com/tliron/kutil v0.3.24
github.com/tmc/langchaingo v0.1.5
github.com/zalando/go-keyring v0.2.3
go.opentelemetry.io/otel v1.24.0
Expand All @@ -56,10 +60,21 @@ require (
)

require (
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/iancoleman/strcase v0.3.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
github.com/pkoukk/tiktoken-go v0.1.2 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/sasha-s/go-deadlock v0.3.1 // indirect
github.com/segmentio/ksuid v1.0.4 // indirect
github.com/sourcegraph/jsonrpc2 v0.2.0 // indirect
go.opentelemetry.io/proto/otlp v1.1.0 // indirect
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
)
Expand Down
31 changes: 31 additions & 0 deletions go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions kotlin-runtime/scaffolding/{{ .Name | lower }}/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>{{ .GroupID }}</groupId>
Expand Down
67 changes: 67 additions & 0 deletions lsp/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package lsp

import (
"fmt"

"github.com/tliron/commonlog"

"github.com/TBD54566975/ftl/internal/log"
)

// GLSPLogger is a custom logger for the language server.
type GLSPLogger struct {
commonlog.Logger
}

func (l *GLSPLogger) Log(entry log.Entry) {
l.Logger.Log(toGLSPLevel(entry.Level), 10, entry.Message, entry.Attributes)
}

func (l *GLSPLogger) Logf(level log.Level, format string, args ...interface{}) {
l.Log(log.Entry{Level: level, Message: fmt.Sprintf(format, args...)})
}
func (l *GLSPLogger) Tracef(format string, args ...interface{}) {
l.Log(log.Entry{Level: log.Trace, Message: fmt.Sprintf(format, args...)})
}

func (l *GLSPLogger) Debugf(format string, args ...interface{}) {
l.Log(log.Entry{Level: log.Debug, Message: fmt.Sprintf(format, args...)})
}

func (l *GLSPLogger) Infof(format string, args ...interface{}) {
l.Log(log.Entry{Level: log.Info, Message: fmt.Sprintf(format, args...)})
}

func (l *GLSPLogger) Warnf(format string, args ...interface{}) {
l.Log(log.Entry{Level: log.Warn, Message: fmt.Sprintf(format, args...)})
}

func (l *GLSPLogger) Errorf(err error, format string, args ...interface{}) {
if err == nil {
return
}
l.Log(log.Entry{Level: log.Error, Message: fmt.Sprintf(format, args...) + ": " + err.Error(), Error: err})
}

var _ log.Interface = (*GLSPLogger)(nil)

func NewGLSPLogger(log commonlog.Logger) *GLSPLogger {
return &GLSPLogger{log}
}

func toGLSPLevel(l log.Level) commonlog.Level {
switch l {
case log.Trace:
return commonlog.Debug
case log.Debug:
return commonlog.Debug
case log.Info:
return commonlog.Info
case log.Warn:
return commonlog.Warning
case log.Error:
return commonlog.Error
default:
return commonlog.Debug
}
}
Loading

0 comments on commit 5ec9856

Please sign in to comment.