Skip to content

Commit 9170400

Browse files
committed
pkg/lsp: refactor diagnostics
1 parent 490f965 commit 9170400

4 files changed

Lines changed: 628 additions & 558 deletions

File tree

cmd/run.go

Lines changed: 151 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -1,170 +1,170 @@
11
package cmd
22

33
import (
4-
"context"
5-
"errors"
6-
"fmt"
7-
"net/http"
8-
"os"
9-
"os/signal"
10-
"path/filepath"
11-
"syscall"
12-
"time"
13-
14-
"github.com/docker/docker/client"
15-
"github.com/go-playground/validator/v10"
16-
"github.com/hide-org/hide/pkg/devcontainer"
17-
"github.com/hide-org/hide/pkg/files"
18-
"github.com/hide-org/hide/pkg/git"
19-
"github.com/hide-org/hide/pkg/gitignore"
20-
"github.com/hide-org/hide/pkg/handlers"
21-
"github.com/hide-org/hide/pkg/lsp"
22-
"github.com/hide-org/hide/pkg/middleware"
23-
"github.com/hide-org/hide/pkg/model"
24-
"github.com/hide-org/hide/pkg/project"
25-
"github.com/hide-org/hide/pkg/random"
26-
"github.com/hide-org/hide/pkg/util"
27-
"github.com/rs/zerolog"
28-
"github.com/rs/zerolog/log"
29-
"github.com/spf13/cobra"
4+
"context"
5+
"errors"
6+
"fmt"
7+
"net/http"
8+
"os"
9+
"os/signal"
10+
"path/filepath"
11+
"syscall"
12+
"time"
13+
14+
"github.com/docker/docker/client"
15+
"github.com/go-playground/validator/v10"
16+
"github.com/hide-org/hide/pkg/devcontainer"
17+
"github.com/hide-org/hide/pkg/files"
18+
"github.com/hide-org/hide/pkg/git"
19+
"github.com/hide-org/hide/pkg/gitignore"
20+
"github.com/hide-org/hide/pkg/handlers"
21+
"github.com/hide-org/hide/pkg/lsp"
22+
"github.com/hide-org/hide/pkg/middleware"
23+
"github.com/hide-org/hide/pkg/model"
24+
"github.com/hide-org/hide/pkg/project"
25+
"github.com/hide-org/hide/pkg/random"
26+
"github.com/hide-org/hide/pkg/util"
27+
"github.com/rs/zerolog"
28+
"github.com/rs/zerolog/log"
29+
"github.com/spf13/cobra"
3030
)
3131

3232
const (
33-
HidePath = ".hide"
34-
ProjectsDir = "projects"
35-
DefaultDotEnvPath = ".env"
33+
HidePath = ".hide"
34+
ProjectsDir = "projects"
35+
DefaultDotEnvPath = ".env"
3636
)
3737

3838
var (
39-
envPath string
40-
debug bool
41-
port int
39+
envPath string
40+
debug bool
41+
port int
4242
)
4343

4444
func init() {
45-
pf := runCmd.PersistentFlags()
46-
pf.StringVar(&envPath, "env", DefaultDotEnvPath, "path to the .env file")
47-
pf.BoolVar(&debug, "debug", false, "run service in a debug mode")
48-
pf.IntVar(&port, "port", 8080, "service port")
45+
pf := runCmd.PersistentFlags()
46+
pf.StringVar(&envPath, "env", DefaultDotEnvPath, "path to the .env file")
47+
pf.BoolVar(&debug, "debug", false, "run service in a debug mode")
48+
pf.IntVar(&port, "port", 8080, "service port")
4949
}
5050

5151
var runCmd = &cobra.Command{
52-
Use: "run",
53-
Short: "Runs Hide service",
54-
PreRun: func(cmd *cobra.Command, args []string) {
55-
setupLogger(debug)
56-
},
57-
Run: func(cmd *cobra.Command, args []string) {
58-
fmt.Print(splash)
59-
60-
_, err := os.Stat(envPath)
61-
62-
if os.IsNotExist(err) {
63-
log.Debug().Msgf("Environment file %s does not exist.", envPath)
64-
}
65-
66-
if err == nil {
67-
dir, file := filepath.Split(envPath)
68-
69-
if dir == "" {
70-
dir = "."
71-
}
72-
73-
err := util.LoadEnv(os.DirFS(dir), file)
74-
if err != nil {
75-
log.Error().Err(err).Msgf("Cannot load environment variables from %s", envPath)
76-
}
77-
}
78-
79-
dockerUser := os.Getenv("DOCKER_USER")
80-
dockerToken := os.Getenv("DOCKER_TOKEN")
81-
82-
if dockerUser == "" || dockerToken == "" {
83-
log.Warn().Msg("DOCKER_USER or DOCKER_TOKEN environment variables are empty. This might cause problems when pulling images from Docker Hub.")
84-
}
85-
86-
dockerClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
87-
if err != nil {
88-
log.Fatal().Err(err).Msg("Cannot initialize docker client")
89-
}
90-
91-
containerRunner := devcontainer.NewDockerRunner(devcontainer.NewExecutorImpl(), devcontainer.NewImageManager(dockerClient, random.String, devcontainer.NewDockerHubRegistryCredentials(dockerUser, dockerToken)), devcontainer.NewDockerContainerManager(dockerClient))
92-
projectStore := project.NewInMemoryStore(make(map[string]*model.Project))
93-
home, err := os.UserHomeDir()
94-
if err != nil {
95-
log.Fatal().Err(err).Msg("User's home directory is not set")
96-
}
97-
98-
projectsDir := filepath.Join(home, HidePath, ProjectsDir)
99-
100-
fileManager := files.NewFileManager(gitignore.NewMatcherFactory())
101-
languageDetector := lsp.NewLanguageDetector()
102-
diagnosticsStore := lsp.NewDiagnosticsStore()
103-
clientPool := lsp.NewClientPool()
104-
lspService := lsp.NewService(languageDetector, lsp.LspServerExecutables, diagnosticsStore, clientPool)
105-
projectManager := project.NewProjectManager(containerRunner, projectStore, projectsDir, fileManager, lspService, languageDetector, random.String, git.NewClient())
106-
validator := validator.New(validator.WithRequiredStructEnabled())
107-
108-
router := handlers.
109-
NewRouter().
110-
WithCreateProjectHandler(handlers.CreateProjectHandler{Manager: projectManager, Validator: validator}).
111-
WithDeleteProjectHandler(handlers.DeleteProjectHandler{Manager: projectManager}).
112-
WithCreateTaskHandler(handlers.CreateTaskHandler{Manager: projectManager}).
113-
WithGetProjectHandler(handlers.GetProjectHandler{Manager: projectManager}).
114-
WithGetProjectsHandler(handlers.GetProjectsHandler{Manager: projectManager}).
115-
WithListTasksHandler(handlers.ListTasksHandler{Manager: projectManager}).
116-
WithCreateFileHandler(handlers.CreateFileHandler{ProjectManager: projectManager}).
117-
WithListFilesHandler(handlers.ListFilesHandler{ProjectManager: projectManager}).
118-
WithReadFileHandler(middleware.PathValidator(handlers.ReadFileHandler{ProjectManager: projectManager})).
119-
WithUpdateFileHandler(middleware.PathValidator(handlers.UpdateFileHandler{ProjectManager: projectManager})).
120-
WithDeleteFileHandler(middleware.PathValidator(handlers.DeleteFileHandler{ProjectManager: projectManager})).
121-
WithSearchFileHandler(handlers.SearchFilesHandler{ProjectManager: projectManager}).
122-
WithSearchSymbolsHandler(handlers.NewSearchSymbolsHandler(projectManager)).
123-
WithDocumentOutlineHandler(handlers.DocumentOutline{ProjectManager: projectManager}).
124-
Build()
125-
126-
addr := fmt.Sprintf("127.0.0.1:%d", port)
127-
128-
server := &http.Server{
129-
Handler: router,
130-
Addr: addr,
131-
}
132-
133-
log.Info().Msgf("Server started on %s\n", addr)
134-
135-
go func() {
136-
sigChan := make(chan os.Signal, 1)
137-
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
138-
<-sigChan
139-
140-
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
141-
defer cancel()
142-
143-
log.Info().Msg("Server shutting down ...")
144-
if err := projectManager.Cleanup(ctx); err != nil {
145-
log.Warn().Err(err).Msgf("Failed to cleanup projects")
146-
}
147-
148-
if err := server.Shutdown(ctx); err != nil {
149-
log.Warn().Err(err).Msgf("HTTP shutdown error: %v", err)
150-
}
151-
}()
152-
153-
if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
154-
log.Fatal().Err(err).Msgf("HTTP server error: %v", err)
155-
}
156-
157-
fmt.Println("👋 Goodbye!")
158-
},
52+
Use: "run",
53+
Short: "Runs Hide service",
54+
PreRun: func(cmd *cobra.Command, args []string) {
55+
setupLogger(debug)
56+
},
57+
Run: func(cmd *cobra.Command, args []string) {
58+
fmt.Print(splash)
59+
60+
_, err := os.Stat(envPath)
61+
62+
if os.IsNotExist(err) {
63+
log.Debug().Msgf("Environment file %s does not exist.", envPath)
64+
}
65+
66+
if err == nil {
67+
dir, file := filepath.Split(envPath)
68+
69+
if dir == "" {
70+
dir = "."
71+
}
72+
73+
err := util.LoadEnv(os.DirFS(dir), file)
74+
if err != nil {
75+
log.Error().Err(err).Msgf("Cannot load environment variables from %s", envPath)
76+
}
77+
}
78+
79+
dockerUser := os.Getenv("DOCKER_USER")
80+
dockerToken := os.Getenv("DOCKER_TOKEN")
81+
82+
if dockerUser == "" || dockerToken == "" {
83+
log.Warn().Msg("DOCKER_USER or DOCKER_TOKEN environment variables are empty. This might cause problems when pulling images from Docker Hub.")
84+
}
85+
86+
dockerClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
87+
if err != nil {
88+
log.Fatal().Err(err).Msg("Cannot initialize docker client")
89+
}
90+
91+
containerRunner := devcontainer.NewDockerRunner(devcontainer.NewExecutorImpl(), devcontainer.NewImageManager(dockerClient, random.String, devcontainer.NewDockerHubRegistryCredentials(dockerUser, dockerToken)), devcontainer.NewDockerContainerManager(dockerClient))
92+
projectStore := project.NewInMemoryStore(make(map[string]*model.Project))
93+
home, err := os.UserHomeDir()
94+
if err != nil {
95+
log.Fatal().Err(err).Msg("User's home directory is not set")
96+
}
97+
98+
projectsDir := filepath.Join(home, HidePath, ProjectsDir)
99+
100+
fileManager := files.NewFileManager(gitignore.NewMatcherFactory())
101+
languageDetector := lsp.NewLanguageDetector()
102+
diagnosticsService := lsp.NewDiagnosticsService()
103+
clientPool := lsp.NewClientPool()
104+
lspService := lsp.NewService(languageDetector, lsp.LspServerExecutables, diagnosticsService, clientPool)
105+
projectManager := project.NewProjectManager(containerRunner, projectStore, projectsDir, fileManager, lspService, languageDetector, random.String, git.NewClient())
106+
validator := validator.New(validator.WithRequiredStructEnabled())
107+
108+
router := handlers.
109+
NewRouter().
110+
WithCreateProjectHandler(handlers.CreateProjectHandler{Manager: projectManager, Validator: validator}).
111+
WithDeleteProjectHandler(handlers.DeleteProjectHandler{Manager: projectManager}).
112+
WithCreateTaskHandler(handlers.CreateTaskHandler{Manager: projectManager}).
113+
WithGetProjectHandler(handlers.GetProjectHandler{Manager: projectManager}).
114+
WithGetProjectsHandler(handlers.GetProjectsHandler{Manager: projectManager}).
115+
WithListTasksHandler(handlers.ListTasksHandler{Manager: projectManager}).
116+
WithCreateFileHandler(handlers.CreateFileHandler{ProjectManager: projectManager}).
117+
WithListFilesHandler(handlers.ListFilesHandler{ProjectManager: projectManager}).
118+
WithReadFileHandler(middleware.PathValidator(handlers.ReadFileHandler{ProjectManager: projectManager})).
119+
WithUpdateFileHandler(middleware.PathValidator(handlers.UpdateFileHandler{ProjectManager: projectManager})).
120+
WithDeleteFileHandler(middleware.PathValidator(handlers.DeleteFileHandler{ProjectManager: projectManager})).
121+
WithSearchFileHandler(handlers.SearchFilesHandler{ProjectManager: projectManager}).
122+
WithSearchSymbolsHandler(handlers.NewSearchSymbolsHandler(projectManager)).
123+
WithDocumentOutlineHandler(handlers.DocumentOutline{ProjectManager: projectManager}).
124+
Build()
125+
126+
addr := fmt.Sprintf("127.0.0.1:%d", port)
127+
128+
server := &http.Server{
129+
Handler: router,
130+
Addr: addr,
131+
}
132+
133+
log.Info().Msgf("Server started on %s\n", addr)
134+
135+
go func() {
136+
sigChan := make(chan os.Signal, 1)
137+
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
138+
<-sigChan
139+
140+
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
141+
defer cancel()
142+
143+
log.Info().Msg("Server shutting down ...")
144+
if err := projectManager.Cleanup(ctx); err != nil {
145+
log.Warn().Err(err).Msgf("Failed to cleanup projects")
146+
}
147+
148+
if err := server.Shutdown(ctx); err != nil {
149+
log.Warn().Err(err).Msgf("HTTP shutdown error: %v", err)
150+
}
151+
}()
152+
153+
if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
154+
log.Fatal().Err(err).Msgf("HTTP server error: %v", err)
155+
}
156+
157+
fmt.Println("👋 Goodbye!")
158+
},
159159
}
160160

161161
func setupLogger(debug bool) {
162-
zerolog.TimeFieldFormat = zerolog.TimeFormatUnixMs
163-
output := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339Nano}
164-
log.Logger = log.Output(output).With().Caller().Logger()
165-
166-
zerolog.SetGlobalLevel(zerolog.InfoLevel)
167-
if debug {
168-
zerolog.SetGlobalLevel(zerolog.DebugLevel)
169-
}
162+
zerolog.TimeFieldFormat = zerolog.TimeFormatUnixMs
163+
output := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339Nano}
164+
log.Logger = log.Output(output).With().Caller().Logger()
165+
166+
zerolog.SetGlobalLevel(zerolog.InfoLevel)
167+
if debug {
168+
zerolog.SetGlobalLevel(zerolog.DebugLevel)
169+
}
170170
}

0 commit comments

Comments
 (0)