Skip to content
This repository was archived by the owner on Jan 31, 2024. It is now read-only.

Commit 62da059

Browse files
author
Henry Wong
committed
[elastic] Move the deps download into 'intialize' request handle
The original implementation relies on 'go list' to download the deps. And 'go list' will be called by the request handler indirectly. This approach is unpredictable and 'go list' is black box to us. So it's better download the deps manually in 'ManageDeps', i.e. inside 'initialize' request handler. For security, set 'GO111MODULE=off' by default, once we set 'GO111MODULE=off', we pass option to `-mod=vendor` to any `go list` command, so we can resolve packages from `vendor` folder. And we can jump to the `vendor` folder.
1 parent 2702523 commit 62da059

File tree

6 files changed

+52
-4
lines changed

6 files changed

+52
-4
lines changed

go/packages/golist.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,31 @@ func invokeGo(cfg *Config, args ...string) (*bytes.Buffer, error) {
861861
cfg.Logf("%s for %v, stderr: <<%s>>\n", time.Since(start), cmdDebugStr(cmd, args...), stderr)
862862
}(time.Now())
863863

864+
enableVendor := func(cfg *Config) bool {
865+
l := len(cfg.Env)
866+
for i := range cfg.Env {
867+
if cfg.Env[l-i-1] == "GO111MODULE=off" {
868+
return true
869+
}
870+
}
871+
return false
872+
}(cfg)
873+
for i := range cmd.Args {
874+
if cmd.Args[i] == "list" && len(cmd.Args) != i {
875+
if enableVendor {
876+
l := len(cmd.Env)
877+
for j := range cmd.Env {
878+
if cmd.Env[l-j-1] == "GO111MODULE=off" {
879+
cmd.Env[l-j-1] = "GO111MODULE=on"
880+
cmd.Args = append(cmd.Args[:i+1], append([]string{"-mod=vendor"}, cmd.Args[i+1:]...)...)
881+
break
882+
}
883+
}
884+
break
885+
}
886+
}
887+
}
888+
864889
if err := cmd.Run(); err != nil {
865890
// Check for 'go' executable not being found.
866891
if ee, ok := err.(*exec.Error); ok && ee.Err == exec.ErrNotFound {

internal/lsp/cache/session.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ func (s *session) NewView(ctx context.Context, name string, folder span.URI) sou
9393
},
9494
ignoredURIs: make(map[span.URI]struct{}),
9595
}
96+
// Disable 'GO111MODULE' by default, 'GO111MODULE=off' will disallow the deps download for the repos under mod mode
97+
disableGoModule(v)
9698
// Preemptively build the builtin package,
9799
// so we immediately add builtin.go to the list of ignored files.
98100
v.buildBuiltinPkg(ctx)
@@ -382,3 +384,13 @@ func (s debugSession) File(hash string) *debug.File {
382384
Hash: hash,
383385
}
384386
}
387+
388+
func disableGoModule(v *view) {
389+
for _, ev := range v.env {
390+
if ev == "GO111MODULE=off" {
391+
return
392+
}
393+
}
394+
// TODO(henrywong) Use 'GOPROXY=off' to disable the network access
395+
v.env = append(v.env, "GO111MODULE=off")
396+
}

internal/lsp/elasticserver.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,8 @@ type WorkspaceFolderMeta struct {
189189
// manageDeps will try its best to convert the folders to modules. The core functions, like deps downloading and deps
190190
// management, will be implemented in the package 'cache'.
191191
func (s ElasticServer) ManageDeps(folders *[]protocol.WorkspaceFolder) error {
192-
// Note: For the upstream go langserver, granularity of the workspace folders is repository. But for the elastic go
193-
// language server, there are repositories contain multiple modules. In order to handle the modules separately, we
194-
// consider different modules as different workspace folders, so we can manage the dependency of different modules
195-
// separately.
192+
// In order to handle the modules separately, we consider different modules as different workspace folders, so we
193+
// can manage the dependency of different modules separately.
196194
for _, folder := range *folders {
197195
metadata := &WorkspaceFolderMeta{}
198196
if folder.URI != "" {

internal/lsp/general.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ func (s *Server) initialize(ctx context.Context, params *protocol.InitializePara
3838
if opt, ok := opts["noIncrementalSync"].(bool); ok && opt {
3939
s.textDocumentSyncKind = protocol.Full
4040
}
41+
if opt, ok := opts["installGoDependency"].(bool); ok && opt {
42+
s.installGoDependency = true
43+
}
4144
}
4245

4346
// Default to using synopsis as a default for hover information.

internal/lsp/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ type Server struct {
8888
preferredContentFormat protocol.MarkupKind
8989
disabledAnalyses map[string]struct{}
9090
wantSuggestedFixes bool
91+
installGoDependency bool
9192

9293
supportedCodeActions map[source.FileKind]map[protocol.CodeActionKind]bool
9394

internal/lsp/workspace.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ import (
88
"context"
99

1010
"golang.org/x/tools/internal/lsp/protocol"
11+
"golang.org/x/tools/internal/lsp/telemetry/log"
1112
"golang.org/x/tools/internal/span"
1213
errors "golang.org/x/xerrors"
14+
"os/exec"
1315
)
1416

1517
func (s *Server) changeFolders(ctx context.Context, event protocol.WorkspaceFoldersChangeEvent) error {
@@ -31,6 +33,13 @@ func (s *Server) changeFolders(ctx context.Context, event protocol.WorkspaceFold
3133
}
3234

3335
func (s *Server) addView(ctx context.Context, name string, uri span.URI) error {
36+
if s.installGoDependency {
37+
cmd := exec.Command("go", "mod", "download")
38+
cmd.Dir = uri.Filename()
39+
if err := cmd.Run(); err != nil {
40+
log.Error(ctx, "failed to download the dependencies", err)
41+
}
42+
}
3443
view := s.session.NewView(ctx, name, uri)
3544
s.stateMu.Lock()
3645
state := s.state

0 commit comments

Comments
 (0)