@@ -6,10 +6,8 @@ package lsp
6
6
7
7
import (
8
8
"context"
9
- "encoding/json"
10
9
"fmt"
11
10
"io"
12
- "strings"
13
11
14
12
"golang.org/x/tools/internal/event"
15
13
"golang.org/x/tools/internal/lsp/debug/tag"
@@ -20,11 +18,6 @@ import (
20
18
errors "golang.org/x/xerrors"
21
19
)
22
20
23
- type CommandRangeArgument struct {
24
- URI protocol.DocumentURI `json:"uri,omitempty"`
25
- Range protocol.Range `json:"range,omitempty"`
26
- }
27
-
28
21
func (s * Server ) executeCommand (ctx context.Context , params * protocol.ExecuteCommandParams ) (interface {}, error ) {
29
22
var found bool
30
23
for _ , command := range s .session .Options ().SupportedCommands {
@@ -36,82 +29,86 @@ func (s *Server) executeCommand(ctx context.Context, params *protocol.ExecuteCom
36
29
if ! found {
37
30
return nil , fmt .Errorf ("unsupported command detected: %s" , params .Command )
38
31
}
39
- switch params .Command {
40
- case source .CommandTest :
41
- unsaved := false
42
- for _ , overlay := range s .session .Overlays () {
43
- if ! overlay .Saved () {
44
- unsaved = true
45
- break
46
- }
47
- }
48
- if unsaved {
32
+ // Some commands require that all files are saved to disk. If we detect
33
+ // unsaved files, warn the user instead of running the commands.
34
+ unsaved := false
35
+ for _ , overlay := range s .session .Overlays () {
36
+ if ! overlay .Saved () {
37
+ unsaved = true
38
+ break
39
+ }
40
+ }
41
+ if unsaved {
42
+ switch params .Command {
43
+ case source .CommandTest , source .CommandGenerate :
49
44
return nil , s .client .ShowMessage (ctx , & protocol.ShowMessageParams {
50
45
Type : protocol .Error ,
51
- Message : "could not run tests, there are unsaved files in the view" ,
46
+ Message : fmt . Sprintf ( "cannot run command %s: unsaved files in the view", params . Command ) ,
52
47
})
53
48
}
54
- funcName , uri , err := getRunTestArguments (params .Arguments )
55
- if err != nil {
49
+ }
50
+ switch params .Command {
51
+ case source .CommandTest :
52
+ var uri protocol.DocumentURI
53
+ var funcName string
54
+ if err := source .DecodeArgs (params .Arguments , & uri , & funcName ); err != nil {
56
55
return nil , err
57
56
}
58
- view , err := s .session . ViewOf ( uri )
59
- if err != nil {
57
+ snapshot , _ , ok , err := s .beginFileRequest ( ctx , uri , source . UnknownKind )
58
+ if ! ok {
60
59
return nil , err
61
60
}
62
- go s .runTest (ctx , view . Snapshot () , funcName )
61
+ go s .runGoTest (ctx , snapshot , funcName )
63
62
case source .CommandGenerate :
64
- dir , recursive , err := getGenerateRequest (params .Arguments )
65
- if err != nil {
63
+ var uri protocol.DocumentURI
64
+ var recursive bool
65
+ if err := source .DecodeArgs (params .Arguments , & uri , & recursive ); err != nil {
66
66
return nil , err
67
67
}
68
- go s .runGoGenerate (xcontext .Detach (ctx ), dir , recursive )
68
+ go s .runGoGenerate (xcontext .Detach (ctx ), uri . SpanURI () , recursive )
69
69
case source .CommandRegenerateCgo :
70
+ var uri protocol.DocumentURI
71
+ if err := source .DecodeArgs (params .Arguments , & uri ); err != nil {
72
+ return nil , err
73
+ }
70
74
mod := source.FileModification {
71
- URI : protocol . DocumentURI ( params . Arguments [ 0 ].( string )) .SpanURI (),
75
+ URI : uri .SpanURI (),
72
76
Action : source .InvalidateMetadata ,
73
77
}
74
78
_ , err := s .didModifyFiles (ctx , []source.FileModification {mod }, FromRegenerateCgo )
75
79
return nil , err
76
80
case source .CommandTidy , source .CommandVendor :
77
- if len (params .Arguments ) == 0 || len (params .Arguments ) > 1 {
78
- return nil , errors .Errorf ("expected 1 argument, got %v" , params .Arguments )
81
+ var uri protocol.DocumentURI
82
+ if err := source .DecodeArgs (params .Arguments , & uri ); err != nil {
83
+ return nil , err
79
84
}
80
- uri := protocol .DocumentURI (params .Arguments [0 ].(string ))
81
-
82
85
// The flow for `go mod tidy` and `go mod vendor` is almost identical,
83
86
// so we combine them into one case for convenience.
84
- arg := "tidy"
87
+ a := "tidy"
85
88
if params .Command == source .CommandVendor {
86
- arg = "vendor"
89
+ a = "vendor"
87
90
}
88
- err := s .directGoModCommand (ctx , uri , "mod" , []string {arg }... )
91
+ err := s .directGoModCommand (ctx , uri , "mod" , []string {a }... )
89
92
return nil , err
90
93
case source .CommandUpgradeDependency :
91
- if len (params .Arguments ) < 2 {
92
- return nil , errors .Errorf ("expected 2 arguments, got %v" , params .Arguments )
94
+ var uri protocol.DocumentURI
95
+ var deps []string
96
+ if err := source .DecodeArgs (params .Arguments , & uri , & deps ); err != nil {
97
+ return nil , err
93
98
}
94
- uri := protocol .DocumentURI (params .Arguments [0 ].(string ))
95
- deps := params .Arguments [1 ].(string )
96
- err := s .directGoModCommand (ctx , uri , "get" , strings .Split (deps , " " )... )
99
+ err := s .directGoModCommand (ctx , uri , "get" , deps ... )
97
100
return nil , err
98
101
case source .CommandFillStruct :
99
- if len (params .Arguments ) != 1 {
100
- return nil , fmt .Errorf ("expected 1 arguments, got %v: %v" , len (params .Arguments ), params .Arguments )
101
- }
102
- var arg CommandRangeArgument
103
- str , ok := params .Arguments [0 ].(string )
104
- if ! ok {
105
- return nil , fmt .Errorf ("expected string, got %v (%T)" , params .Arguments [0 ], params .Arguments [0 ])
106
- }
107
- if err := json .Unmarshal ([]byte (str ), & arg ); err != nil {
102
+ var uri protocol.DocumentURI
103
+ var rng protocol.Range
104
+ if err := source .DecodeArgs (params .Arguments , & uri , & rng ); err != nil {
108
105
return nil , err
109
106
}
110
- snapshot , fh , ok , err := s .beginFileRequest (ctx , arg . URI , source .Go )
107
+ snapshot , fh , ok , err := s .beginFileRequest (ctx , uri , source .Go )
111
108
if ! ok {
112
109
return nil , err
113
110
}
114
- edits , err := source .FillStruct (ctx , snapshot , fh , arg . Range )
111
+ edits , err := source .FillStruct (ctx , snapshot , fh , rng )
115
112
if err != nil {
116
113
return nil , err
117
114
}
@@ -129,6 +126,8 @@ func (s *Server) executeCommand(ctx context.Context, params *protocol.ExecuteCom
129
126
Message : fmt .Sprintf ("fillstruct failed: %v" , r .FailureReason ),
130
127
})
131
128
}
129
+ default :
130
+ return nil , fmt .Errorf ("unknown command: %s" , params .Command )
132
131
}
133
132
return nil , nil
134
133
}
@@ -141,7 +140,7 @@ func (s *Server) directGoModCommand(ctx context.Context, uri protocol.DocumentUR
141
140
return view .Snapshot ().RunGoCommandDirect (ctx , verb , args )
142
141
}
143
142
144
- func (s * Server ) runTest (ctx context.Context , snapshot source.Snapshot , funcName string ) error {
143
+ func (s * Server ) runGoTest (ctx context.Context , snapshot source.Snapshot , funcName string ) error {
145
144
ctx , cancel := context .WithCancel (ctx )
146
145
defer cancel ()
147
146
@@ -171,7 +170,7 @@ func (s *Server) runTest(ctx context.Context, snapshot source.Snapshot, funcName
171
170
// generate commands. It is exported for testing purposes.
172
171
const GenerateWorkDoneTitle = "generate"
173
172
174
- func (s * Server ) runGoGenerate (ctx context.Context , dir string , recursive bool ) error {
173
+ func (s * Server ) runGoGenerate (ctx context.Context , uri span. URI , recursive bool ) error {
175
174
ctx , cancel := context .WithCancel (ctx )
176
175
defer cancel ()
177
176
@@ -184,7 +183,6 @@ func (s *Server) runGoGenerate(ctx context.Context, dir string, recursive bool)
184
183
}
185
184
186
185
stderr := io .MultiWriter (er , wc )
187
- uri := span .URIFromPath (dir )
188
186
view , err := s .session .ViewOf (uri )
189
187
if err != nil {
190
188
return err
@@ -202,33 +200,3 @@ func (s *Server) runGoGenerate(ctx context.Context, dir string, recursive bool)
202
200
}
203
201
return nil
204
202
}
205
-
206
- func getRunTestArguments (args []interface {}) (string , span.URI , error ) {
207
- if len (args ) != 2 {
208
- return "" , "" , errors .Errorf ("expected one test func name and one file path, got %v" , args )
209
- }
210
- funcName , ok := args [0 ].(string )
211
- if ! ok {
212
- return "" , "" , errors .Errorf ("expected func name to be a string, got %T" , args [0 ])
213
- }
214
- filename , ok := args [1 ].(string )
215
- if ! ok {
216
- return "" , "" , errors .Errorf ("expected file to be a string, got %T" , args [1 ])
217
- }
218
- return funcName , span .URIFromPath (filename ), nil
219
- }
220
-
221
- func getGenerateRequest (args []interface {}) (string , bool , error ) {
222
- if len (args ) != 2 {
223
- return "" , false , errors .Errorf ("expected exactly 2 arguments but got %d" , len (args ))
224
- }
225
- dir , ok := args [0 ].(string )
226
- if ! ok {
227
- return "" , false , errors .Errorf ("expected dir to be a string value but got %T" , args [0 ])
228
- }
229
- recursive , ok := args [1 ].(bool )
230
- if ! ok {
231
- return "" , false , errors .Errorf ("expected recursive to be a boolean but got %T" , args [1 ])
232
- }
233
- return dir , recursive , nil
234
- }
0 commit comments