Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / internal / lsp / cmd / imports.go
1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package cmd
6
7 import (
8         "context"
9         "flag"
10         "fmt"
11         "io/ioutil"
12
13         "golang.org/x/tools/internal/lsp/diff"
14         "golang.org/x/tools/internal/lsp/protocol"
15         "golang.org/x/tools/internal/lsp/source"
16         "golang.org/x/tools/internal/span"
17         "golang.org/x/tools/internal/tool"
18         errors "golang.org/x/xerrors"
19 )
20
21 // imports implements the import verb for gopls.
22 type imports struct {
23         Diff  bool `flag:"d" help:"display diffs instead of rewriting files"`
24         Write bool `flag:"w" help:"write result to (source) file instead of stdout"`
25
26         app *Application
27 }
28
29 func (t *imports) Name() string      { return "imports" }
30 func (t *imports) Usage() string     { return "<filename>" }
31 func (t *imports) ShortHelp() string { return "updates import statements" }
32 func (t *imports) DetailedHelp(f *flag.FlagSet) {
33         fmt.Fprintf(f.Output(), `
34 Example: update imports statements in a file:
35
36   $ gopls imports -w internal/lsp/cmd/check.go
37
38 gopls imports flags are:
39 `)
40         f.PrintDefaults()
41 }
42
43 // Run performs diagnostic checks on the file specified and either;
44 // - if -w is specified, updates the file in place;
45 // - if -d is specified, prints out unified diffs of the changes; or
46 // - otherwise, prints the new versions to stdout.
47 func (t *imports) Run(ctx context.Context, args ...string) error {
48         if len(args) != 1 {
49                 return tool.CommandLineErrorf("imports expects 1 argument")
50         }
51         conn, err := t.app.connect(ctx)
52         if err != nil {
53                 return err
54         }
55         defer conn.terminate(ctx)
56
57         from := span.Parse(args[0])
58         uri := from.URI()
59         file := conn.AddFile(ctx, uri)
60         if file.err != nil {
61                 return file.err
62         }
63         actions, err := conn.CodeAction(ctx, &protocol.CodeActionParams{
64                 TextDocument: protocol.TextDocumentIdentifier{
65                         URI: protocol.URIFromSpanURI(uri),
66                 },
67         })
68         if err != nil {
69                 return errors.Errorf("%v: %v", from, err)
70         }
71         var edits []protocol.TextEdit
72         for _, a := range actions {
73                 if a.Title != "Organize Imports" {
74                         continue
75                 }
76                 for _, c := range a.Edit.DocumentChanges {
77                         if fileURI(c.TextDocument.URI) == uri {
78                                 edits = append(edits, c.Edits...)
79                         }
80                 }
81         }
82         sedits, err := source.FromProtocolEdits(file.mapper, edits)
83         if err != nil {
84                 return errors.Errorf("%v: %v", edits, err)
85         }
86         newContent := diff.ApplyEdits(string(file.mapper.Content), sedits)
87
88         filename := file.uri.Filename()
89         switch {
90         case t.Write:
91                 if len(edits) > 0 {
92                         ioutil.WriteFile(filename, []byte(newContent), 0644)
93                 }
94         case t.Diff:
95                 diffs := diff.ToUnified(filename+".orig", filename, string(file.mapper.Content), sedits)
96                 fmt.Print(diffs)
97         default:
98                 fmt.Print(string(newContent))
99         }
100         return nil
101 }