Skip to content

Commit

Permalink
feat: VSCode support
Browse files Browse the repository at this point in the history
  • Loading branch information
stuartwdouglas committed Sep 17, 2024
1 parent c688607 commit b02bb00
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 15 deletions.
1 change: 1 addition & 0 deletions bin/.dlv-1.23.0.pkg
1 change: 1 addition & 0 deletions bin/delve-1.23.0
4 changes: 2 additions & 2 deletions go-runtime/compile/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,14 +255,14 @@ func Build(ctx context.Context, projectRootDir, moduleDir string, sch *schema.Sc
return fmt.Errorf("failed to compile: %w", err)
}
err = os.WriteFile(filepath.Join(mainDir, "../../launch"), []byte(`#!/bin/bash
if [ -n "$FTL_DEBUG_PORT" ]; then
if [ -n "$FTL_DEBUG_PORT" ] && command -v dlv &> /dev/null ; then
dlv --listen=localhost:$FTL_DEBUG_PORT --headless=true --api-version=2 --accept-multiclient --allow-non-terminal-interactive --log exec --continue ./main
else
exec ./main
fi
`), 0750)
if err != nil {
return err
return fmt.Errorf("failed to write launch script: %w", err)
}
return nil
}
Expand Down
17 changes: 9 additions & 8 deletions internal/buildengine/discover_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func TestDiscoverModules(t *testing.T) {
Language: "go",
Realm: "home",
Module: "alpha",
Deploy: []string{"main"},
Deploy: []string{"main", "launch"},
DeployDir: ".ftl",
Schema: "schema.pb",
Errors: "errors.pb",
Expand All @@ -34,7 +34,7 @@ func TestDiscoverModules(t *testing.T) {
Language: "go",
Realm: "home",
Module: "another",
Deploy: []string{"main"},
Deploy: []string{"main", "launch"},
DeployDir: ".ftl",
Schema: "schema.pb",
Errors: "errors.pb",
Expand All @@ -47,7 +47,7 @@ func TestDiscoverModules(t *testing.T) {
Language: "go",
Realm: "home",
Module: "depcycle1",
Deploy: []string{"main"},
Deploy: []string{"main", "launch"},
DeployDir: ".ftl",
Schema: "schema.pb",
Errors: "errors.pb",
Expand All @@ -60,7 +60,7 @@ func TestDiscoverModules(t *testing.T) {
Language: "go",
Realm: "home",
Module: "depcycle2",
Deploy: []string{"main"},
Deploy: []string{"main", "launch"},
DeployDir: ".ftl",
Schema: "schema.pb",
Errors: "errors.pb",
Expand All @@ -75,8 +75,8 @@ func TestDiscoverModules(t *testing.T) {
Module: "echo",
Build: "mvn -B package",
Deploy: []string{
"main",
"quarkus-app",
"launch",
},
DeployDir: "target",
GeneratedSchemaDir: "src/main/ftl-module-schema",
Expand All @@ -101,6 +101,7 @@ func TestDiscoverModules(t *testing.T) {
Build: "",
Deploy: []string{
"main",
"launch",
},
DeployDir: ".ftl",
Schema: "schema.pb",
Expand All @@ -120,8 +121,8 @@ func TestDiscoverModules(t *testing.T) {
Module: "externalkotlin",
Build: "mvn -B package",
Deploy: []string{
"main",
"quarkus-app",
"launch",
},
DeployDir: "target",
GeneratedSchemaDir: "src/main/ftl-module-schema",
Expand All @@ -143,7 +144,7 @@ func TestDiscoverModules(t *testing.T) {
Language: "go",
Realm: "home",
Module: "integer",
Deploy: []string{"main"},
Deploy: []string{"main", "launch"},
DeployDir: ".ftl",
Schema: "schema.pb",
Errors: "errors.pb",
Expand All @@ -156,7 +157,7 @@ func TestDiscoverModules(t *testing.T) {
Language: "go",
Realm: "home",
Module: "other",
Deploy: []string{"main"},
Deploy: []string{"main", "launch"},
DeployDir: ".ftl",
Schema: "schema.pb",
Errors: "errors.pb",
Expand Down
2 changes: 1 addition & 1 deletion internal/buildengine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func WithListener(listener Listener) Option {
}
}

// WithListener sets the event listener for the Engine.
// WithDevMode sets the engine to dev mode.
func WithDevMode(devMode bool) Option {
return func(o *Engine) {
o.devMode = devMode
Expand Down
126 changes: 123 additions & 3 deletions internal/localdebug/local_ide_debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package localdebug

import (
"context"
"encoding/json"
"fmt"
"os"
"os/signal"
Expand Down Expand Up @@ -56,6 +57,7 @@ func init() {
var lock = sync.Mutex{}
var paths = map[string]bool{}

// SyncIDEDebugIntegrations will sync the local IDE debug configurations for the given project path.
// This is a bit of a hack to prove out the concept of local debugging.
func SyncIDEDebugIntegrations(cxt context.Context, projectPath string, ports map[string]*DebugInfo) {
lock.Lock()
Expand All @@ -64,6 +66,7 @@ func SyncIDEDebugIntegrations(cxt context.Context, projectPath string, ports map
return
}
handleIntellij(cxt, projectPath, ports)
handleVSCode(cxt, projectPath, ports)
}

func handleIntellij(cxt context.Context, path string, ports map[string]*DebugInfo) {
Expand All @@ -86,9 +89,7 @@ func handleIntellij(cxt context.Context, path string, ports map[string]*DebugInf
for _, entry := range entries {
if strings.HasPrefix(entry.Name(), "FTL.") && strings.HasSuffix(entry.Name(), ".xml") {
debugInfo := ports[entry.Name()[4:(len(entry.Name())-4)]]
if debugInfo != nil {
continue
} else {
if debugInfo == nil {
// old FTL entry, remove it
path := filepath.Join(runConfig, entry.Name())
_ = os.Remove(path)
Expand Down Expand Up @@ -137,6 +138,125 @@ func findIdeaFolder(startPath string) string {
return ""
}

func handleVSCode(cxt context.Context, path string, ports map[string]*DebugInfo) {
logger := log.FromContext(cxt)
launchJSON := findLaunchJSON(path)
if launchJSON == "" {
return
}

contents := map[string]interface{}{}
existing := map[string]int{}
var configurations []interface{}
if _, err := os.Stat(launchJSON); err == nil {
file, err := os.ReadFile(launchJSON)
if err != nil {
logger.Errorf(err, "could not read launch.json")
return
}
err = json.Unmarshal(file, &contents)
if err != nil {
logger.Errorf(err, "could not read launch.json")
return
}
configurations = contents["configurations"].([]interface{}) //nolint:forcetypeassert
if configurations == nil {
configurations = []interface{}{}
}
} else {
contents["version"] = "0.2.0"
configurations = []interface{}{}
}
for i, config := range configurations {
existing[config.(map[string]interface{})["name"].(string)] = i //nolint:forcetypeassert
}

for k, v := range ports {
if v.Language == "java" || v.Language == "kotlin" {
name := "FT𝝺 JVM - " + k
pos, ok := existing[name]
if ok {
// Update the port
configurations[pos].(map[string]interface{})["port"] = v.Port //nolint:forcetypeassert
continue
}
entry := map[string]interface{}{
"name": name,
"type": "java",
"request": "attach",
"hostName": "127.0.0.1",
"port": v.Port,
}
configurations = append(configurations, entry)

} else if v.Language == "go" {
name := "FT𝝺 GO - " + k
pos, ok := existing[name]
if ok {
// Update the port
configurations[pos].(map[string]interface{})["port"] = v.Port //nolint:forcetypeassert
continue
}
entry := map[string]interface{}{
"name": name,
"type": "go",
"request": "attach",
"mode": "remote",
"apiVersion": 2,
"host": "127.0.0.1",
"port": v.Port,
}
configurations = append(configurations, entry)
}
}
contents["configurations"] = configurations
data, err := json.Marshal(contents)
if err != nil {
logger.Errorf(err, "could not marshal launch.json")
return
}
err = os.WriteFile(launchJSON, data, 0644)
if err != nil {
logger.Errorf(err, "could not write launch.json")
return
}
}

// findLaunchJSON recurses up the directory tree to find a .vscode folder
// If it can't find one it creates one next to project.toml
// It then returns the path to the launch.json file
func findLaunchJSON(startPath string) string {
currentPath := startPath
projectPath := ""
for {
vscodePath := filepath.Join(currentPath, ".vscode")
if _, err := os.Stat(vscodePath); err == nil {
return filepath.Join(vscodePath, "launch.json")
}
if projectPath == "" {
tmp := filepath.Join(currentPath, "project.toml")
if _, err := os.Stat(tmp); err == nil {
projectPath = currentPath
}
}
parentPath := filepath.Dir(currentPath)
if parentPath == currentPath {
// Reached the root directory
break
}
currentPath = parentPath
}
if projectPath != "" {
vscodePath := filepath.Join(projectPath, ".vscode")
err := os.MkdirAll(vscodePath, 0750)
if err != nil {
return ""
}
return filepath.Join(vscodePath, "launch.json")
}
return ""
}

type DebugInfo struct {
Port int
Language string
Expand Down
2 changes: 1 addition & 1 deletion internal/moduleconfig/moduleconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ func setConfigDefaults(moduleDir string, config *ModuleConfig) error {
config.GeneratedSchemaDir = "src/main/ftl-module-schema"
}
if len(config.Deploy) == 0 {
config.Deploy = []string{"main", "quarkus-app"}
config.Deploy = []string{"quarkus-app", "launch"}
}
case "go":
if config.DeployDir == "" {
Expand Down

0 comments on commit b02bb00

Please sign in to comment.