mirror of
https://github.com/golang/go
synced 2024-11-18 18:54:42 -07:00
e33b02e766
This change adds support for returning versions along with file URIs, so that the client can know when to apply changes. The version is not yet propagated along to the internal/lsp/cache package, so this change will have no effect (VS Code ignores a version of 0 and still applies the changes). A few minor changes made in the rename code (to remove the view parameter). Some minor staticcheck fixes. Updates golang/go#35243 Change-Id: Icc26bd9d9e5703c699f555424b94034c97b01d6f Reviewed-on: https://go-review.googlesource.com/c/tools/+/206882 Run-TryBot: Rebecca Stambler <rstambler@golang.org> Reviewed-by: Ian Cottrell <iancottrell@google.com>
102 lines
2.6 KiB
Go
102 lines
2.6 KiB
Go
// Copyright 2019 The Go Authors. All rights reserved.
|
||
// Use of this source code is governed by a BSD-style
|
||
// license that can be found in the LICENSE file.
|
||
|
||
package cmd
|
||
|
||
import (
|
||
"context"
|
||
"flag"
|
||
"fmt"
|
||
"io/ioutil"
|
||
|
||
"golang.org/x/tools/internal/lsp/diff"
|
||
"golang.org/x/tools/internal/lsp/protocol"
|
||
"golang.org/x/tools/internal/lsp/source"
|
||
"golang.org/x/tools/internal/span"
|
||
"golang.org/x/tools/internal/tool"
|
||
errors "golang.org/x/xerrors"
|
||
)
|
||
|
||
// imports implements the import verb for gopls.
|
||
type imports struct {
|
||
Diff bool `flag:"d" help:"display diffs instead of rewriting files"`
|
||
Write bool `flag:"w" help:"write result to (source) file instead of stdout"`
|
||
|
||
app *Application
|
||
}
|
||
|
||
func (t *imports) Name() string { return "imports" }
|
||
func (t *imports) Usage() string { return "<filename>" }
|
||
func (t *imports) ShortHelp() string { return "updates import statements" }
|
||
func (t *imports) DetailedHelp(f *flag.FlagSet) {
|
||
fmt.Fprintf(f.Output(), `
|
||
Example: update imports statements in a file:
|
||
|
||
$ gopls imports -w internal/lsp/cmd/check.go
|
||
|
||
gopls imports flags are:
|
||
`)
|
||
f.PrintDefaults()
|
||
}
|
||
|
||
// Run performs diagnostic checks on the file specified and either;
|
||
// - if -w is specified, updates the file in place;
|
||
// - if -d is specified, prints out unified diffs of the changes; or
|
||
// - otherwise, prints the new versions to stdout.
|
||
func (t *imports) Run(ctx context.Context, args ...string) error {
|
||
if len(args) != 1 {
|
||
return tool.CommandLineErrorf("imports expects 1 argument")
|
||
}
|
||
conn, err := t.app.connect(ctx)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer conn.terminate(ctx)
|
||
|
||
from := span.Parse(args[0])
|
||
uri := from.URI()
|
||
file := conn.AddFile(ctx, uri)
|
||
if file.err != nil {
|
||
return file.err
|
||
}
|
||
actions, err := conn.CodeAction(ctx, &protocol.CodeActionParams{
|
||
TextDocument: protocol.TextDocumentIdentifier{
|
||
URI: protocol.NewURI(uri),
|
||
},
|
||
})
|
||
if err != nil {
|
||
return errors.Errorf("%v: %v", from, err)
|
||
}
|
||
var edits []protocol.TextEdit
|
||
for _, a := range actions {
|
||
if a.Title != "Organize Imports" {
|
||
continue
|
||
}
|
||
for _, c := range a.Edit.DocumentChanges {
|
||
if c.TextDocument.URI == string(uri) {
|
||
edits = append(edits, c.Edits...)
|
||
}
|
||
}
|
||
}
|
||
sedits, err := source.FromProtocolEdits(file.mapper, edits)
|
||
if err != nil {
|
||
return errors.Errorf("%v: %v", edits, err)
|
||
}
|
||
newContent := diff.ApplyEdits(string(file.mapper.Content), sedits)
|
||
|
||
filename := file.uri.Filename()
|
||
switch {
|
||
case t.Write:
|
||
if len(edits) > 0 {
|
||
ioutil.WriteFile(filename, []byte(newContent), 0644)
|
||
}
|
||
case t.Diff:
|
||
diffs := diff.ToUnified(filename+".orig", filename, string(file.mapper.Content), sedits)
|
||
fmt.Print(diffs)
|
||
default:
|
||
fmt.Print(string(newContent))
|
||
}
|
||
return nil
|
||
}
|