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.
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 errors "golang.org/x/xerrors"
20 // format implements the format verb for gopls.
22 Diff bool `flag:"d" help:"display diffs instead of rewriting files"`
23 Write bool `flag:"w" help:"write result to (source) file instead of stdout"`
24 List bool `flag:"l" help:"list files whose formatting differs from gofmt's"`
29 func (c *format) Name() string { return "format" }
30 func (c *format) Usage() string { return "<filerange>" }
31 func (c *format) ShortHelp() string { return "format the code according to the go standard" }
32 func (c *format) DetailedHelp(f *flag.FlagSet) {
33 fmt.Fprint(f.Output(), `
34 The arguments supplied may be simple file names, or ranges within files.
36 Example: reformat this file:
38 $ gopls format -w internal/lsp/cmd/check.go
40 gopls format flags are:
45 // Run performs the check on the files specified by args and prints the
47 func (c *format) Run(ctx context.Context, args ...string) error {
49 // no files, so no results
52 // now we ready to kick things off
53 conn, err := c.app.connect(ctx)
57 defer conn.terminate(ctx)
58 for _, arg := range args {
59 spn := span.Parse(arg)
60 file := conn.AddFile(ctx, spn.URI())
64 filename := spn.URI().Filename()
65 loc, err := file.mapper.Location(spn)
69 if loc.Range.Start != loc.Range.End {
70 return errors.Errorf("only full file formatting supported")
72 p := protocol.DocumentFormattingParams{
73 TextDocument: protocol.TextDocumentIdentifier{URI: loc.URI},
75 edits, err := conn.Formatting(ctx, &p)
77 return errors.Errorf("%v: %v", spn, err)
79 sedits, err := source.FromProtocolEdits(file.mapper, edits)
81 return errors.Errorf("%v: %v", spn, err)
83 formatted := diff.ApplyEdits(string(file.mapper.Content), sedits)
94 ioutil.WriteFile(filename, []byte(formatted), 0644)
99 u := diff.ToUnified(filename+".orig", filename, string(file.mapper.Content), sedits)