aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/golangci/gofmt
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-07-04 11:12:55 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-07-04 15:05:30 +0200
commitc7d7f10bdff703e4a3c0414e8a33d4e45c91eb35 (patch)
tree0dff0ee1f98dbfa3ad8776112053a450d176592b /vendor/github.com/golangci/gofmt
parent9573094ce235bd9afe88f5da27a47dd6bcc1e13b (diff)
go.mod: vendor golangci-lint
Diffstat (limited to 'vendor/github.com/golangci/gofmt')
-rw-r--r--vendor/github.com/golangci/gofmt/gofmt/LICENSE27
-rw-r--r--vendor/github.com/golangci/gofmt/gofmt/doc.go104
-rw-r--r--vendor/github.com/golangci/gofmt/gofmt/gofmt.go327
-rw-r--r--vendor/github.com/golangci/gofmt/gofmt/golangci.go46
-rw-r--r--vendor/github.com/golangci/gofmt/gofmt/internal.go176
-rw-r--r--vendor/github.com/golangci/gofmt/gofmt/rewrite.go303
-rw-r--r--vendor/github.com/golangci/gofmt/gofmt/simplify.go165
-rw-r--r--vendor/github.com/golangci/gofmt/goimports/LICENSE27
-rw-r--r--vendor/github.com/golangci/gofmt/goimports/goimports.go358
-rw-r--r--vendor/github.com/golangci/gofmt/goimports/golangci.go33
10 files changed, 1566 insertions, 0 deletions
diff --git a/vendor/github.com/golangci/gofmt/gofmt/LICENSE b/vendor/github.com/golangci/gofmt/gofmt/LICENSE
new file mode 100644
index 000000000..6a66aea5e
--- /dev/null
+++ b/vendor/github.com/golangci/gofmt/gofmt/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/golangci/gofmt/gofmt/doc.go b/vendor/github.com/golangci/gofmt/gofmt/doc.go
new file mode 100644
index 000000000..da0c8581d
--- /dev/null
+++ b/vendor/github.com/golangci/gofmt/gofmt/doc.go
@@ -0,0 +1,104 @@
+// Copyright 2009 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.
+
+/*
+Gofmt formats Go programs.
+It uses tabs for indentation and blanks for alignment.
+Alignment assumes that an editor is using a fixed-width font.
+
+Without an explicit path, it processes the standard input. Given a file,
+it operates on that file; given a directory, it operates on all .go files in
+that directory, recursively. (Files starting with a period are ignored.)
+By default, gofmt prints the reformatted sources to standard output.
+
+Usage:
+ gofmt [flags] [path ...]
+
+The flags are:
+ -d
+ Do not print reformatted sources to standard output.
+ If a file's formatting is different than gofmt's, print diffs
+ to standard output.
+ -e
+ Print all (including spurious) errors.
+ -l
+ Do not print reformatted sources to standard output.
+ If a file's formatting is different from gofmt's, print its name
+ to standard output.
+ -r rule
+ Apply the rewrite rule to the source before reformatting.
+ -s
+ Try to simplify code (after applying the rewrite rule, if any).
+ -w
+ Do not print reformatted sources to standard output.
+ If a file's formatting is different from gofmt's, overwrite it
+ with gofmt's version. If an error occurred during overwriting,
+ the original file is restored from an automatic backup.
+
+Debugging support:
+ -cpuprofile filename
+ Write cpu profile to the specified file.
+
+
+The rewrite rule specified with the -r flag must be a string of the form:
+
+ pattern -> replacement
+
+Both pattern and replacement must be valid Go expressions.
+In the pattern, single-character lowercase identifiers serve as
+wildcards matching arbitrary sub-expressions; those expressions
+will be substituted for the same identifiers in the replacement.
+
+When gofmt reads from standard input, it accepts either a full Go program
+or a program fragment. A program fragment must be a syntactically
+valid declaration list, statement list, or expression. When formatting
+such a fragment, gofmt preserves leading indentation as well as leading
+and trailing spaces, so that individual sections of a Go program can be
+formatted by piping them through gofmt.
+
+Examples
+
+To check files for unnecessary parentheses:
+
+ gofmt -r '(a) -> a' -l *.go
+
+To remove the parentheses:
+
+ gofmt -r '(a) -> a' -w *.go
+
+To convert the package tree from explicit slice upper bounds to implicit ones:
+
+ gofmt -r 'α[β:len(α)] -> α[β:]' -w $GOROOT/src
+
+The simplify command
+
+When invoked with -s gofmt will make the following source transformations where possible.
+
+ An array, slice, or map composite literal of the form:
+ []T{T{}, T{}}
+ will be simplified to:
+ []T{{}, {}}
+
+ A slice expression of the form:
+ s[a:len(s)]
+ will be simplified to:
+ s[a:]
+
+ A range of the form:
+ for x, _ = range v {...}
+ will be simplified to:
+ for x = range v {...}
+
+ A range of the form:
+ for _ = range v {...}
+ will be simplified to:
+ for range v {...}
+
+This may result in changes that are incompatible with earlier versions of Go.
+*/
+package gofmt
+
+// BUG(rsc): The implementation of -r is a bit slow.
+// BUG(gri): If -w fails, the restored original file may not have some of the
+// original file attributes.
diff --git a/vendor/github.com/golangci/gofmt/gofmt/gofmt.go b/vendor/github.com/golangci/gofmt/gofmt/gofmt.go
new file mode 100644
index 000000000..fb9c8cb37
--- /dev/null
+++ b/vendor/github.com/golangci/gofmt/gofmt/gofmt.go
@@ -0,0 +1,327 @@
+// Copyright 2009 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 gofmt
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/printer"
+ "go/scanner"
+ "go/token"
+ "io"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "runtime/pprof"
+ "strings"
+ "sync"
+)
+
+var (
+ // main operation modes
+ list = flag.Bool("gofmt.l", false, "list files whose formatting differs from gofmt's")
+ write = flag.Bool("gofmt.w", false, "write result to (source) file instead of stdout")
+ rewriteRule = flag.String("gofmt.r", "", "rewrite rule (e.g., 'a[b:len(a)] -> a[b:]')")
+ simplifyAST = flag.Bool("gofmt.s", false, "simplify code")
+ doDiff = flag.Bool("gofmt.d", false, "display diffs instead of rewriting files")
+ allErrors = flag.Bool("gofmt.e", false, "report all errors (not just the first 10 on different lines)")
+
+ // debugging
+ cpuprofile = flag.String("gofmt.cpuprofile", "", "write cpu profile to this file")
+)
+
+const (
+ tabWidth = 8
+ printerMode = printer.UseSpaces | printer.TabIndent
+)
+
+var (
+ fileSet = token.NewFileSet() // per process FileSet
+ exitCode = 0
+ rewrite func(*ast.File) *ast.File
+ parserMode parser.Mode
+ parserModeInitOnce sync.Once
+)
+
+func report(err error) {
+ scanner.PrintError(os.Stderr, err)
+ exitCode = 2
+}
+
+func usage() {
+ fmt.Fprintf(os.Stderr, "usage: gofmt [flags] [path ...]\n")
+ flag.PrintDefaults()
+}
+
+func initParserMode() {
+ parserModeInitOnce.Do(func() {
+ parserMode = parser.ParseComments
+ if *allErrors {
+ parserMode |= parser.AllErrors
+ }
+ })
+}
+
+func isGoFile(f os.FileInfo) bool {
+ // ignore non-Go files
+ name := f.Name()
+ return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
+}
+
+// If in == nil, the source is the contents of the file with the given filename.
+func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error {
+ var perm os.FileMode = 0644
+ if in == nil {
+ f, err := os.Open(filename)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ fi, err := f.Stat()
+ if err != nil {
+ return err
+ }
+ in = f
+ perm = fi.Mode().Perm()
+ }
+
+ src, err := ioutil.ReadAll(in)
+ if err != nil {
+ return err
+ }
+
+ file, sourceAdj, indentAdj, err := parse(fileSet, filename, src, stdin)
+ if err != nil {
+ return err
+ }
+
+ if rewrite != nil {
+ if sourceAdj == nil {
+ file = rewrite(file)
+ } else {
+ fmt.Fprintf(os.Stderr, "warning: rewrite ignored for incomplete programs\n")
+ }
+ }
+
+ ast.SortImports(fileSet, file)
+
+ if *simplifyAST {
+ simplify(file)
+ }
+
+ res, err := format(fileSet, file, sourceAdj, indentAdj, src, printer.Config{Mode: printerMode, Tabwidth: tabWidth})
+ if err != nil {
+ return err
+ }
+
+ if !bytes.Equal(src, res) {
+ // formatting has changed
+ if *list {
+ fmt.Fprintln(out, filename)
+ }
+ if *write {
+ // make a temporary backup before overwriting original
+ bakname, err := backupFile(filename+".", src, perm)
+ if err != nil {
+ return err
+ }
+ err = ioutil.WriteFile(filename, res, perm)
+ if err != nil {
+ os.Rename(bakname, filename)
+ return err
+ }
+ err = os.Remove(bakname)
+ if err != nil {
+ return err
+ }
+ }
+ if *doDiff {
+ data, err := diff(src, res, filename)
+ if err != nil {
+ return fmt.Errorf("computing diff: %s", err)
+ }
+ fmt.Printf("diff -u %s %s\n", filepath.ToSlash(filename+".orig"), filepath.ToSlash(filename))
+ out.Write(data)
+ }
+ }
+
+ if !*list && !*write && !*doDiff {
+ _, err = out.Write(res)
+ }
+
+ return err
+}
+
+func visitFile(path string, f os.FileInfo, err error) error {
+ if err == nil && isGoFile(f) {
+ err = processFile(path, nil, os.Stdout, false)
+ }
+ // Don't complain if a file was deleted in the meantime (i.e.
+ // the directory changed concurrently while running gofmt).
+ if err != nil && !os.IsNotExist(err) {
+ report(err)
+ }
+ return nil
+}
+
+func walkDir(path string) {
+ filepath.Walk(path, visitFile)
+}
+
+func gofmtMain() {
+ flag.Usage = usage
+ flag.Parse()
+
+ if *cpuprofile != "" {
+ f, err := os.Create(*cpuprofile)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "creating cpu profile: %s\n", err)
+ exitCode = 2
+ return
+ }
+ defer f.Close()
+ pprof.StartCPUProfile(f)
+ defer pprof.StopCPUProfile()
+ }
+
+ initParserMode()
+ initRewrite()
+
+ if flag.NArg() == 0 {
+ if *write {
+ fmt.Fprintln(os.Stderr, "error: cannot use -w with standard input")
+ exitCode = 2
+ return
+ }
+ if err := processFile("<standard input>", os.Stdin, os.Stdout, true); err != nil {
+ report(err)
+ }
+ return
+ }
+
+ for i := 0; i < flag.NArg(); i++ {
+ path := flag.Arg(i)
+ switch dir, err := os.Stat(path); {
+ case err != nil:
+ report(err)
+ case dir.IsDir():
+ walkDir(path)
+ default:
+ if err := processFile(path, nil, os.Stdout, false); err != nil {
+ report(err)
+ }
+ }
+ }
+}
+
+func writeTempFile(dir, prefix string, data []byte) (string, error) {
+ file, err := ioutil.TempFile(dir, prefix)
+ if err != nil {
+ return "", err
+ }
+ _, err = file.Write(data)
+ if err1 := file.Close(); err == nil {
+ err = err1
+ }
+ if err != nil {
+ os.Remove(file.Name())
+ return "", err
+ }
+ return file.Name(), nil
+}
+
+func diff(b1, b2 []byte, filename string) (data []byte, err error) {
+ f1, err := writeTempFile("", "gofmt", b1)
+ if err != nil {
+ return
+ }
+ defer os.Remove(f1)
+
+ f2, err := writeTempFile("", "gofmt", b2)
+ if err != nil {
+ return
+ }
+ defer os.Remove(f2)
+
+ cmd := "diff"
+ if runtime.GOOS == "plan9" {
+ cmd = "/bin/ape/diff"
+ }
+
+ data, err = exec.Command(cmd, "-u", f1, f2).CombinedOutput()
+ if len(data) > 0 {
+ // diff exits with a non-zero status when the files don't match.
+ // Ignore that failure as long as we get output.
+ return replaceTempFilename(data, filename)
+ }
+ return
+}
+
+// replaceTempFilename replaces temporary filenames in diff with actual one.
+//
+// --- /tmp/gofmt316145376 2017-02-03 19:13:00.280468375 -0500
+// +++ /tmp/gofmt617882815 2017-02-03 19:13:00.280468375 -0500
+// ...
+// ->
+// --- path/to/file.go.orig 2017-02-03 19:13:00.280468375 -0500
+// +++ path/to/file.go 2017-02-03 19:13:00.280468375 -0500
+// ...
+func replaceTempFilename(diff []byte, filename string) ([]byte, error) {
+ bs := bytes.SplitN(diff, []byte{'\n'}, 3)
+ if len(bs) < 3 {
+ return nil, fmt.Errorf("got unexpected diff for %s", filename)
+ }
+ // Preserve timestamps.
+ var t0, t1 []byte
+ if i := bytes.LastIndexByte(bs[0], '\t'); i != -1 {
+ t0 = bs[0][i:]
+ }
+ if i := bytes.LastIndexByte(bs[1], '\t'); i != -1 {
+ t1 = bs[1][i:]
+ }
+ // Always print filepath with slash separator.
+ f := filepath.ToSlash(filename)
+ bs[0] = []byte(fmt.Sprintf("--- %s%s", f+".orig", t0))
+ bs[1] = []byte(fmt.Sprintf("+++ %s%s", f, t1))
+ return bytes.Join(bs, []byte{'\n'}), nil
+}
+
+const chmodSupported = runtime.GOOS != "windows"
+
+// backupFile writes data to a new file named filename<number> with permissions perm,
+// with <number randomly chosen such that the file name is unique. backupFile returns
+// the chosen file name.
+func backupFile(filename string, data []byte, perm os.FileMode) (string, error) {
+ // create backup file
+ f, err := ioutil.TempFile(filepath.Dir(filename), filepath.Base(filename))
+ if err != nil {
+ return "", err
+ }
+ bakname := f.Name()
+ if chmodSupported {
+ err = f.Chmod(perm)
+ if err != nil {
+ f.Close()
+ os.Remove(bakname)
+ return bakname, err
+ }
+ }
+
+ // write data to backup file
+ n, err := f.Write(data)
+ if err == nil && n < len(data) {
+ err = io.ErrShortWrite
+ }
+ if err1 := f.Close(); err == nil {
+ err = err1
+ }
+
+ return bakname, err
+}
diff --git a/vendor/github.com/golangci/gofmt/gofmt/golangci.go b/vendor/github.com/golangci/gofmt/gofmt/golangci.go
new file mode 100644
index 000000000..0f5a0d408
--- /dev/null
+++ b/vendor/github.com/golangci/gofmt/gofmt/golangci.go
@@ -0,0 +1,46 @@
+package gofmt
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/printer"
+ "io/ioutil"
+)
+
+func Run(filename string, needSimplify bool) ([]byte, error) {
+ src, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return nil, err
+ }
+
+ initParserMode()
+
+ file, sourceAdj, indentAdj, err := parse(fileSet, filename, src, false)
+ if err != nil {
+ return nil, err
+ }
+
+ ast.SortImports(fileSet, file)
+
+ if needSimplify {
+ simplify(file)
+ }
+
+ res, err := format(fileSet, file, sourceAdj, indentAdj, src, printer.Config{Mode: printerMode, Tabwidth: tabWidth})
+ if err != nil {
+ return nil, err
+ }
+
+ if bytes.Equal(src, res) {
+ return nil, nil
+ }
+
+ // formatting has changed
+ data, err := diff(src, res, filename)
+ if err != nil {
+ return nil, fmt.Errorf("error computing diff: %s", err)
+ }
+
+ return data, nil
+}
diff --git a/vendor/github.com/golangci/gofmt/gofmt/internal.go b/vendor/github.com/golangci/gofmt/gofmt/internal.go
new file mode 100644
index 000000000..8b76d39d5
--- /dev/null
+++ b/vendor/github.com/golangci/gofmt/gofmt/internal.go
@@ -0,0 +1,176 @@
+// Copyright 2015 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.
+
+// TODO(gri): This file and the file src/go/format/internal.go are
+// the same (but for this comment and the package name). Do not modify
+// one without the other. Determine if we can factor out functionality
+// in a public API. See also #11844 for context.
+
+package gofmt
+
+import (
+ "bytes"
+ "go/ast"
+ "go/parser"
+ "go/printer"
+ "go/token"
+ "strings"
+)
+
+// parse parses src, which was read from the named file,
+// as a Go source file, declaration, or statement list.
+func parse(fset *token.FileSet, filename string, src []byte, fragmentOk bool) (
+ file *ast.File,
+ sourceAdj func(src []byte, indent int) []byte,
+ indentAdj int,
+ err error,
+) {
+ // Try as whole source file.
+ file, err = parser.ParseFile(fset, filename, src, parserMode)
+ // If there's no error, return. If the error is that the source file didn't begin with a
+ // package line and source fragments are ok, fall through to
+ // try as a source fragment. Stop and return on any other error.
+ if err == nil || !fragmentOk || !strings.Contains(err.Error(), "expected 'package'") {
+ return
+ }
+
+ // If this is a declaration list, make it a source file
+ // by inserting a package clause.
+ // Insert using a ;, not a newline, so that the line numbers
+ // in psrc match the ones in src.
+ psrc := append([]byte("package p;"), src...)
+ file, err = parser.ParseFile(fset, filename, psrc, parserMode)
+ if err == nil {
+ sourceAdj = func(src []byte, indent int) []byte {
+ // Remove the package clause.
+ // Gofmt has turned the ; into a \n.
+ src = src[indent+len("package p\n"):]
+ return bytes.TrimSpace(src)
+ }
+ return
+ }
+ // If the error is that the source file didn't begin with a
+ // declaration, fall through to try as a statement list.
+ // Stop and return on any other error.
+ if !strings.Contains(err.Error(), "expected declaration") {
+ return
+ }
+
+ // If this is a statement list, make it a source file
+ // by inserting a package clause and turning the list
+ // into a function body. This handles expressions too.
+ // Insert using a ;, not a newline, so that the line numbers
+ // in fsrc match the ones in src. Add an extra '\n' before the '}'
+ // to make sure comments are flushed before the '}'.
+ fsrc := append(append([]byte("package p; func _() {"), src...), '\n', '\n', '}')
+ file, err = parser.ParseFile(fset, filename, fsrc, parserMode)
+ if err == nil {
+ sourceAdj = func(src []byte, indent int) []byte {
+ // Cap adjusted indent to zero.
+ if indent < 0 {
+ indent = 0
+ }
+ // Remove the wrapping.
+ // Gofmt has turned the ; into a \n\n.
+ // There will be two non-blank lines with indent, hence 2*indent.
+ src = src[2*indent+len("package p\n\nfunc _() {"):]
+ // Remove only the "}\n" suffix: remaining whitespaces will be trimmed anyway
+ src = src[:len(src)-len("}\n")]
+ return bytes.TrimSpace(src)
+ }
+ // Gofmt has also indented the function body one level.
+ // Adjust that with indentAdj.
+ indentAdj = -1
+ }
+
+ // Succeeded, or out of options.
+ return
+}
+
+// format formats the given package file originally obtained from src
+// and adjusts the result based on the original source via sourceAdj
+// and indentAdj.
+func format(
+ fset *token.FileSet,
+ file *ast.File,
+ sourceAdj func(src []byte, indent int) []byte,
+ indentAdj int,
+ src []byte,
+ cfg printer.Config,
+) ([]byte, error) {
+ if sourceAdj == nil {
+ // Complete source file.
+ var buf bytes.Buffer
+ err := cfg.Fprint(&buf, fset, file)
+ if err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+ }
+
+ // Partial source file.
+ // Determine and prepend leading space.
+ i, j := 0, 0
+ for j < len(src) && isSpace(src[j]) {
+ if src[j] == '\n' {
+ i = j + 1 // byte offset of last line in leading space
+ }
+ j++
+ }
+ var res []byte
+ res = append(res, src[:i]...)
+
+ // Determine and prepend indentation of first code line.
+ // Spaces are ignored unless there are no tabs,
+ // in which case spaces count as one tab.
+ indent := 0
+ hasSpace := false
+ for _, b := range src[i:j] {
+ switch b {
+ case ' ':
+ hasSpace = true
+ case '\t':
+ indent++
+ }
+ }
+ if indent == 0 && hasSpace {
+ indent = 1
+ }
+ for i := 0; i < indent; i++ {
+ res = append(res, '\t')
+ }
+
+ // Format the source.
+ // Write it without any leading and trailing space.
+ cfg.Indent = indent + indentAdj
+ var buf bytes.Buffer
+ err := cfg.Fprint(&buf, fset, file)
+ if err != nil {
+ return nil, err
+ }
+ out := sourceAdj(buf.Bytes(), cfg.Indent)
+
+ // If the adjusted output is empty, the source
+ // was empty but (possibly) for white space.
+ // The result is the incoming source.
+ if len(out) == 0 {
+ return src, nil
+ }
+
+ // Otherwise, append output to leading space.
+ res = append(res, out...)
+
+ // Determine and append trailing space.
+ i = len(src)
+ for i > 0 && isSpace(src[i-1]) {
+ i--
+ }
+ return append(res, src[i:]...), nil
+}
+
+// isSpace reports whether the byte is a space character.
+// isSpace defines a space as being among the following bytes: ' ', '\t', '\n' and '\r'.
+func isSpace(b byte) bool {
+ return b == ' ' || b == '\t' || b == '\n' || b == '\r'
+}
diff --git a/vendor/github.com/golangci/gofmt/gofmt/rewrite.go b/vendor/github.com/golangci/gofmt/gofmt/rewrite.go
new file mode 100644
index 000000000..73741e0a9
--- /dev/null
+++ b/vendor/github.com/golangci/gofmt/gofmt/rewrite.go
@@ -0,0 +1,303 @@
+// Copyright 2009 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 gofmt
+
+import (
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/token"
+ "os"
+ "reflect"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+func initRewrite() {
+ if *rewriteRule == "" {
+ rewrite = nil // disable any previous rewrite
+ return
+ }
+ f := strings.Split(*rewriteRule, "->")
+ if len(f) != 2 {
+ fmt.Fprintf(os.Stderr, "rewrite rule must be of the form 'pattern -> replacement'\n")
+ os.Exit(2)
+ }
+ pattern := parseExpr(f[0], "pattern")
+ replace := parseExpr(f[1], "replacement")
+ rewrite = func(p *ast.File) *ast.File { return rewriteFile(pattern, replace, p) }
+}
+
+// parseExpr parses s as an expression.
+// It might make sense to expand this to allow statement patterns,
+// but there are problems with preserving formatting and also
+// with what a wildcard for a statement looks like.
+func parseExpr(s, what string) ast.Expr {
+ x, err := parser.ParseExpr(s)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "parsing %s %s at %s\n", what, s, err)
+ os.Exit(2)
+ }
+ return x
+}
+
+// Keep this function for debugging.
+/*
+func dump(msg string, val reflect.Value) {
+ fmt.Printf("%s:\n", msg)
+ ast.Print(fileSet, val.Interface())
+ fmt.Println()
+}
+*/
+
+// rewriteFile applies the rewrite rule 'pattern -> replace' to an entire file.
+func rewriteFile(pattern, replace ast.Expr, p *ast.File) *ast.File {
+ cmap := ast.NewCommentMap(fileSet, p, p.Comments)
+ m := make(map[string]reflect.Value)
+ pat := reflect.ValueOf(pattern)
+ repl := reflect.ValueOf(replace)
+
+ var rewriteVal func(val reflect.Value) reflect.Value
+ rewriteVal = func(val reflect.Value) reflect.Value {
+ // don't bother if val is invalid to start with
+ if !val.IsValid() {
+ return reflect.Value{}
+ }
+ val = apply(rewriteVal, val)
+ for k := range m {
+ delete(m, k)
+ }
+ if match(m, pat, val) {
+ val = subst(m, repl, reflect.ValueOf(val.Interface().(ast.Node).Pos()))
+ }
+ return val
+ }
+
+ r := apply(rewriteVal, reflect.ValueOf(p)).Interface().(*ast.File)
+ r.Comments = cmap.Filter(r).Comments() // recreate comments list
+ return r
+}
+
+// set is a wrapper for x.Set(y); it protects the caller from panics if x cannot be changed to y.
+func set(x, y reflect.Value) {
+ // don't bother if x cannot be set or y is invalid
+ if !x.CanSet() || !y.IsValid() {
+ return
+ }
+ defer func() {
+ if x := recover(); x != nil {
+ if s, ok := x.(string); ok &&
+ (strings.Contains(s, "type mismatch") || strings.Contains(s, "not assignable")) {
+ // x cannot be set to y - ignore this rewrite
+ return
+ }
+ panic(x)
+ }
+ }()
+ x.Set(y)
+}
+
+// Values/types for special cases.
+var (
+ objectPtrNil = reflect.ValueOf((*ast.Object)(nil))
+ scopePtrNil = reflect.ValueOf((*ast.Scope)(nil))
+
+ identType = reflect.TypeOf((*ast.Ident)(nil))
+ objectPtrType = reflect.TypeOf((*ast.Object)(nil))
+ positionType = reflect.TypeOf(token.NoPos)
+ callExprType = reflect.TypeOf((*ast.CallExpr)(nil))
+ scopePtrType = reflect.TypeOf((*ast.Scope)(nil))
+)
+
+// apply replaces each AST field x in val with f(x), returning val.
+// To avoid extra conversions, f operates on the reflect.Value form.
+func apply(f func(reflect.Value) reflect.Value, val reflect.Value) reflect.Value {
+ if !val.IsValid() {
+ return reflect.Value{}
+ }
+
+ // *ast.Objects introduce cycles and are likely incorrect after
+ // rewrite; don't follow them but replace with nil instead
+ if val.Type() == objectPtrType {
+ return objectPtrNil
+ }
+
+ // similarly for scopes: they are likely incorrect after a rewrite;
+ // replace them with nil
+ if val.Type() == scopePtrType {
+ return scopePtrNil
+ }
+
+ switch v := reflect.Indirect(val); v.Kind() {
+ case reflect.Slice:
+ for i := 0; i < v.Len(); i++ {
+ e := v.Index(i)
+ set(e, f(e))
+ }
+ case reflect.Struct:
+ for i := 0; i < v.NumField(); i++ {
+ e := v.Field(i)
+ set(e, f(e))
+ }
+ case reflect.Interface:
+ e := v.Elem()
+ set(v, f(e))
+ }
+ return val
+}
+
+func isWildcard(s string) bool {
+ rune, size := utf8.DecodeRuneInString(s)
+ return size == len(s) && unicode.IsLower(rune)
+}
+
+// match reports whether pattern matches val,
+// recording wildcard submatches in m.
+// If m == nil, match checks whether pattern == val.
+func match(m map[string]reflect.Value, pattern, val reflect.Value) bool {
+ // Wildcard matches any expression. If it appears multiple
+ // times in the pattern, it must match the same expression
+ // each time.
+ if m != nil && pattern.IsValid() && pattern.Type() == identType {
+ name := pattern.Interface().(*ast.Ident).Name
+ if isWildcard(name) && val.IsValid() {
+ // wildcards only match valid (non-nil) expressions.
+ if _, ok := val.Interface().(ast.Expr); ok && !val.IsNil() {
+ if old, ok := m[name]; ok {
+ return match(nil, old, val)
+ }
+ m[name] = val
+ return true
+ }
+ }
+ }
+
+ // Otherwise, pattern and val must match recursively.
+ if !pattern.IsValid() || !val.IsValid() {
+ return !pattern.IsValid() && !val.IsValid()
+ }
+ if pattern.Type() != val.Type() {
+ return false
+ }
+
+ // Special cases.
+ switch pattern.Type() {
+ case identType:
+ // For identifiers, only the names need to match
+ // (and none of the other *ast.Object information).
+ // This is a common case, handle it all here instead
+ // of recursing down any further via reflection.
+ p := pattern.Interface().(*ast.Ident)
+ v := val.Interface().(*ast.Ident)
+ return p == nil && v == nil || p != nil && v != nil && p.Name == v.Name
+ case objectPtrType, positionType:
+ // object pointers and token positions always match
+ return true
+ case callExprType:
+ // For calls, the Ellipsis fields (token.Position) must
+ // match since that is how f(x) and f(x...) are different.
+ // Check them here but fall through for the remaining fields.
+ p := pattern.Interface().(*ast.CallExpr)
+ v := val.Interface().(*ast.CallExpr)
+ if p.Ellipsis.IsValid() != v.Ellipsis.IsValid() {
+ return false
+ }
+ }
+
+ p := reflect.Indirect(pattern)
+ v := reflect.Indirect(val)
+ if !p.IsValid() || !v.IsValid() {
+ return !p.IsValid() && !v.IsValid()
+ }
+
+ switch p.Kind() {
+ case reflect.Slice:
+ if p.Len() != v.Len() {
+ return false
+ }
+ for i := 0; i < p.Len(); i++ {
+ if !match(m, p.Index(i), v.Index(i)) {
+ return false
+ }
+ }
+ return true
+
+ case reflect.Struct:
+ for i := 0; i < p.NumField(); i++ {
+ if !match(m, p.Field(i), v.Field(i)) {
+ return false
+ }
+ }
+ return true
+
+ case reflect.Interface:
+ return match(m, p.Elem(), v.Elem())
+ }
+
+ // Handle token integers, etc.
+ return p.Interface() == v.Interface()
+}
+
+// subst returns a copy of pattern with values from m substituted in place
+// of wildcards and pos used as the position of tokens from the pattern.
+// if m == nil, subst returns a copy of pattern and doesn't change the line
+// number information.
+func subst(m map[string]reflect.Value, pattern reflect.Value, pos reflect.Value) reflect.Value {
+ if !pattern.IsValid() {
+ return reflect.Value{}
+ }
+
+ // Wildcard gets replaced with map value.
+ if m != nil && pattern.Type() == identType {
+ name := pattern.Interface().(*ast.Ident).Name
+ if isWildcard(name) {
+ if old, ok := m[name]; ok {
+ return subst(nil, old, reflect.Value{})
+ }
+ }
+ }
+
+ if pos.IsValid() && pattern.Type() == positionType {
+ // use new position only if old position was valid in the first place
+ if old := pattern.Interface().(token.Pos); !old.IsValid() {
+ return pattern
+ }
+ return pos
+ }
+
+ // Otherwise copy.
+ switch p := pattern; p.Kind() {
+ case reflect.Slice:
+ v := reflect.MakeSlice(p.Type(), p.Len(), p.Len())
+ for i := 0; i < p.Len(); i++ {
+ v.Index(i).Set(subst(m, p.Index(i), pos))
+ }
+ return v
+
+ case reflect.Struct:
+ v := reflect.New(p.Type()).Elem()
+ for i := 0; i < p.NumField(); i++ {
+ v.Field(i).Set(subst(m, p.Field(i), pos))
+ }
+ return v
+
+ case reflect.Ptr:
+ v := reflect.New(p.Type()).Elem()
+ if elem := p.Elem(); elem.IsValid() {
+ v.Set(subst(m, elem, pos).Addr())
+ }
+ return v
+
+ case reflect.Interface:
+ v := reflect.New(p.Type()).Elem()
+ if elem := p.Elem(); elem.IsValid() {
+ v.Set(subst(m, elem, pos))
+ }
+ return v
+ }
+
+ return pattern
+}
diff --git a/vendor/github.com/golangci/gofmt/gofmt/simplify.go b/vendor/github.com/golangci/gofmt/gofmt/simplify.go
new file mode 100644
index 000000000..2c75495a6
--- /dev/null
+++ b/vendor/github.com/golangci/gofmt/gofmt/simplify.go
@@ -0,0 +1,165 @@
+// Copyright 2010 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 gofmt
+
+import (
+ "go/ast"
+ "go/token"
+ "reflect"
+)
+
+type simplifier struct{}
+
+func (s simplifier) Visit(node ast.Node) ast.Visitor {
+ switch n := node.(type) {
+ case *ast.CompositeLit:
+ // array, slice, and map composite literals may be simplified
+ outer := n
+ var keyType, eltType ast.Expr
+ switch typ := outer.Type.(type) {
+ case *ast.ArrayType:
+ eltType = typ.Elt
+ case *ast.MapType:
+ keyType = typ.Key
+ eltType = typ.Value
+ }
+
+ if eltType != nil {
+ var ktyp reflect.Value
+ if keyType != nil {
+ ktyp = reflect.ValueOf(keyType)
+ }
+ typ := reflect.ValueOf(eltType)
+ for i, x := range outer.Elts {
+ px := &outer.Elts[i]
+ // look at value of indexed/named elements
+ if t, ok := x.(*ast.KeyValueExpr); ok {
+ if keyType != nil {
+ s.simplifyLiteral(ktyp, keyType, t.Key, &t.Key)
+ }
+ x = t.Value
+ px = &t.Value
+ }
+ s.simplifyLiteral(typ, eltType, x, px)
+ }
+ // node was simplified - stop walk (there are no subnodes to simplify)
+ return nil
+ }
+
+ case *ast.SliceExpr:
+ // a slice expression of the form: s[a:len(s)]
+ // can be simplified to: s[a:]
+ // if s is "simple enough" (for now we only accept identifiers)
+ //
+ // Note: This may not be correct because len may have been redeclared in another
+ // file belonging to the same package. However, this is extremely unlikely
+ // and so far (April 2016, after years of supporting this rewrite feature)
+ // has never come up, so let's keep it working as is (see also #15153).
+ if n.Max != nil {
+ // - 3-index slices always require the 2nd and 3rd index
+ break
+ }
+ if s, _ := n.X.(*ast.Ident); s != nil && s.Obj != nil {
+ // the array/slice object is a single, resolved identifier
+ if call, _ := n.High.(*ast.CallExpr); call != nil && len(call.Args) == 1 && !call.Ellipsis.IsValid() {
+ // the high expression is a function call with a single argument
+ if fun, _ := call.Fun.(*ast.Ident); fun != nil && fun.Name == "len" && fun.Obj == nil {
+ // the function called is "len" and it is not locally defined; and
+ // because we don't have dot imports, it must be the predefined len()
+ if arg, _ := call.Args[0].(*ast.Ident); arg != nil && arg.Obj == s.Obj {
+ // the len argument is the array/slice object
+ n.High = nil
+ }
+ }
+ }
+ }
+ // Note: We could also simplify slice expressions of the form s[0:b] to s[:b]
+ // but we leave them as is since sometimes we want to be very explicit
+ // about the lower bound.
+ // An example where the 0 helps:
+ // x, y, z := b[0:2], b[2:4], b[4:6]
+ // An example where it does not:
+ // x, y := b[:n], b[n:]
+
+ case *ast.RangeStmt:
+ // - a range of the form: for x, _ = range v {...}
+ // can be simplified to: for x = range v {...}
+ // - a range of the form: for _ = range v {...}
+ // can be simplified to: for range v {...}
+ if isBlank(n.Value) {
+ n.Value = nil
+ }
+ if isBlank(n.Key) && n.Value == nil {
+ n.Key = nil
+ }
+ }
+
+ return s
+}
+
+func (s simplifier) simplifyLiteral(typ reflect.Value, astType, x ast.Expr, px *ast.Expr) {
+ ast.Walk(s, x) // simplify x
+
+ // if the element is a composite literal and its literal type
+ // matches the outer literal's element type exactly, the inner
+ // literal type may be omitted
+ if inner, ok := x.(*ast.CompositeLit); ok {
+ if match(nil, typ, reflect.ValueOf(inner.Type)) {
+ inner.Type = nil
+ }
+ }
+ // if the outer literal's element type is a pointer type *T
+ // and the element is & of a composite literal of type T,
+ // the inner &T may be omitted.
+ if ptr, ok := astType.(*ast.StarExpr); ok {
+ if addr, ok := x.(*ast.UnaryExpr); ok && addr.Op == token.AND {
+ if inner, ok := addr.X.(*ast.CompositeLit); ok {
+ if match(nil, reflect.ValueOf(ptr.X), reflect.ValueOf(inner.Type)) {
+ inner.Type = nil // drop T
+ *px = inner // drop &
+ }
+ }
+ }
+ }
+}
+
+func isBlank(x ast.Expr) bool {
+ ident, ok := x.(*ast.Ident)
+ return ok && ident.Name == "_"
+}
+
+func simplify(f *ast.File) {
+ // remove empty declarations such as "const ()", etc
+ removeEmptyDeclGroups(f)
+
+ var s simplifier
+ ast.Walk(s, f)
+}
+
+func removeEmptyDeclGroups(f *ast.File) {
+ i := 0
+ for _, d := range f.Decls {
+ if g, ok := d.(*ast.GenDecl); !ok || !isEmpty(f, g) {
+ f.Decls[i] = d
+ i++
+ }
+ }
+ f.Decls = f.Decls[:i]
+}
+
+func isEmpty(f *ast.File, g *ast.GenDecl) bool {
+ if g.Doc != nil || g.Specs != nil {
+ return false
+ }
+
+ for _, c := range f.Comments {
+ // if there is a comment in the declaration, it is not considered empty
+ if g.Pos() <= c.Pos() && c.End() <= g.End() {
+ return false
+ }
+ }
+
+ return true
+}
diff --git a/vendor/github.com/golangci/gofmt/goimports/LICENSE b/vendor/github.com/golangci/gofmt/goimports/LICENSE
new file mode 100644
index 000000000..6a66aea5e
--- /dev/null
+++ b/vendor/github.com/golangci/gofmt/goimports/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/golangci/gofmt/goimports/goimports.go b/vendor/github.com/golangci/gofmt/goimports/goimports.go
new file mode 100644
index 000000000..8878b700d
--- /dev/null
+++ b/vendor/github.com/golangci/gofmt/goimports/goimports.go
@@ -0,0 +1,358 @@
+// Copyright 2013 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 goimports
+
+import (
+ "bufio"
+ "bytes"
+ "errors"
+ "flag"
+ "fmt"
+ "go/scanner"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "runtime/pprof"
+ "strings"
+
+ "golang.org/x/tools/imports"
+)
+
+var (
+ // main operation modes
+ list = flag.Bool("goimports.l", false, "list files whose formatting differs from goimport's")
+ write = flag.Bool("goimports.w", false, "write result to (source) file instead of stdout")
+ doDiff = flag.Bool("goimports.d", false, "display diffs instead of rewriting files")
+ srcdir = flag.String("goimports.srcdir", "", "choose imports as if source code is from `dir`. When operating on a single file, dir may instead be the complete file name.")
+ verbose bool // verbose logging
+
+ cpuProfile = flag.String("goimports.cpuprofile", "", "CPU profile output")
+ memProfile = flag.String("goimports.memprofile", "", "memory profile output")
+ memProfileRate = flag.Int("goimports.memrate", 0, "if > 0, sets runtime.MemProfileRate")
+
+ options = &imports.Options{
+ TabWidth: 8,
+ TabIndent: true,
+ Comments: true,
+ Fragment: true,
+ }
+ exitCode = 0
+)
+
+func init() {
+ flag.BoolVar(&options.AllErrors, "goimports.e", false, "report all errors (not just the first 10 on different lines)")
+ flag.StringVar(&imports.LocalPrefix, "goimports.local", "", "put imports beginning with this string after 3rd-party packages; comma-separated list")
+}
+
+func report(err error) {
+ scanner.PrintError(os.Stderr, err)
+ exitCode = 2
+}
+
+func usage() {
+ fmt.Fprintf(os.Stderr, "usage: goimports [flags] [path ...]\n")
+ flag.PrintDefaults()
+ os.Exit(2)
+}
+
+func isGoFile(f os.FileInfo) bool {
+ // ignore non-Go files
+ name := f.Name()
+ return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
+}
+
+// argumentType is which mode goimports was invoked as.
+type argumentType int
+
+const (
+ // fromStdin means the user is piping their source into goimports.
+ fromStdin argumentType = iota
+
+ // singleArg is the common case from editors, when goimports is run on
+ // a single file.
+ singleArg
+
+ // multipleArg is when the user ran "goimports file1.go file2.go"
+ // or ran goimports on a directory tree.
+ multipleArg
+)
+
+func processFile(filename string, in io.Reader, out io.Writer, argType argumentType) error {
+ opt := options
+ if argType == fromStdin {
+ nopt := *options
+ nopt.Fragment = true
+ opt = &nopt
+ }
+
+ if in == nil {
+ f, err := os.Open(filename)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ in = f
+ }
+
+ src, err := ioutil.ReadAll(in)
+ if err != nil {
+ return err
+ }
+
+ target := filename
+ if *srcdir != "" {
+ // Determine whether the provided -srcdirc is a directory or file
+ // and then use it to override the target.
+ //
+ // See https://github.com/dominikh/go-mode.el/issues/146
+ if isFile(*srcdir) {
+ if argType == multipleArg {
+ return errors.New("-srcdir value can't be a file when passing multiple arguments or when walking directories")
+ }
+ target = *srcdir
+ } else if argType == singleArg && strings.HasSuffix(*srcdir, ".go") && !isDir(*srcdir) {
+ // For a file which doesn't exist on disk yet, but might shortly.
+ // e.g. user in editor opens $DIR/newfile.go and newfile.go doesn't yet exist on disk.
+ // The goimports on-save hook writes the buffer to a temp file
+ // first and runs goimports before the actual save to newfile.go.
+ // The editor's buffer is named "newfile.go" so that is passed to goimports as:
+ // goimports -srcdir=/gopath/src/pkg/newfile.go /tmp/gofmtXXXXXXXX.go
+ // and then the editor reloads the result from the tmp file and writes
+ // it to newfile.go.
+ target = *srcdir
+ } else {
+ // Pretend that file is from *srcdir in order to decide
+ // visible imports correctly.
+ target = filepath.Join(*srcdir, filepath.Base(filename))
+ }
+ }
+
+ res, err := imports.Process(target, src, opt)
+ if err != nil {
+ return err
+ }
+
+ if !bytes.Equal(src, res) {
+ // formatting has changed
+ if *list {
+ fmt.Fprintln(out, filename)
+ }
+ if *write {
+ if argType == fromStdin {
+ // filename is "<standard input>"
+ return errors.New("can't use -w on stdin")
+ }
+ err = ioutil.WriteFile(filename, res, 0)
+ if err != nil {
+ return err
+ }
+ }
+ if *doDiff {
+ if argType == fromStdin {
+ filename = "stdin.go" // because <standard input>.orig looks silly
+ }
+ data, err := diff(src, res, filename)
+ if err != nil {
+ return fmt.Errorf("computing diff: %s", err)
+ }
+ fmt.Printf("diff -u %s %s\n", filepath.ToSlash(filename+".orig"), filepath.ToSlash(filename))
+ out.Write(data)
+ }
+ }
+
+ if !*list && !*write && !*doDiff {
+ _, err = out.Write(res)
+ }
+
+ return err
+}
+
+func visitFile(path string, f os.FileInfo, err error) error {
+ if err == nil && isGoFile(f) {
+ err = processFile(path, nil, os.Stdout, multipleArg)
+ }
+ if err != nil {
+ report(err)
+ }
+ return nil
+}
+
+func walkDir(path string) {
+ filepath.Walk(path, visitFile)
+}
+
+// parseFlags parses command line flags and returns the paths to process.
+// It's a var so that custom implementations can replace it in other files.
+var parseFlags = func() []string {
+ flag.BoolVar(&verbose, "v", false, "verbose logging")
+
+ flag.Parse()
+ return flag.Args()
+}
+
+func bufferedFileWriter(dest string) (w io.Writer, close func()) {
+ f, err := os.Create(dest)
+ if err != nil {
+ log.Fatal(err)
+ }
+ bw := bufio.NewWriter(f)
+ return bw, func() {
+ if err := bw.Flush(); err != nil {
+ log.Fatalf("error flushing %v: %v", dest, err)
+ }
+ if err := f.Close(); err != nil {
+ log.Fatal(err)
+ }
+ }
+}
+
+func gofmtMain() {
+ flag.Usage = usage
+ paths := parseFlags()
+
+ if *cpuProfile != "" {
+ bw, flush := bufferedFileWriter(*cpuProfile)
+ pprof.StartCPUProfile(bw)
+ defer flush()
+ defer pprof.StopCPUProfile()
+ }
+ // doTrace is a conditionally compiled wrapper around runtime/trace. It is
+ // used to allow goimports to compile under gccgo, which does not support
+ // runtime/trace. See https://golang.org/issue/15544.
+ if *memProfileRate > 0 {
+ runtime.MemProfileRate = *memProfileRate
+ bw, flush := bufferedFileWriter(*memProfile)
+ defer func() {
+ runtime.GC() // materialize all statistics
+ if err := pprof.WriteHeapProfile(bw); err != nil {
+ log.Fatal(err)
+ }
+ flush()
+ }()
+ }
+
+ if verbose {
+ log.SetFlags(log.LstdFlags | log.Lmicroseconds)
+ imports.Debug = true
+ }
+ if options.TabWidth < 0 {
+ fmt.Fprintf(os.Stderr, "negative tabwidth %d\n", options.TabWidth)
+ exitCode = 2
+ return
+ }
+
+ if len(paths) == 0 {
+ if err := processFile("<standard input>", os.Stdin, os.Stdout, fromStdin); err != nil {
+ report(err)
+ }
+ return
+ }
+
+ argType := singleArg
+ if len(paths) > 1 {
+ argType = multipleArg
+ }
+
+ for _, path := range paths {
+ switch dir, err := os.Stat(path); {
+ case err != nil:
+ report(err)
+ case dir.IsDir():
+ walkDir(path)
+ default:
+ if err := processFile(path, nil, os.Stdout, argType); err != nil {
+ report(err)
+ }
+ }
+ }
+}
+
+func writeTempFile(dir, prefix string, data []byte) (string, error) {
+ file, err := ioutil.TempFile(dir, prefix)
+ if err != nil {
+ return "", err
+ }
+ _, err = file.Write(data)
+ if err1 := file.Close(); err == nil {
+ err = err1
+ }
+ if err != nil {
+ os.Remove(file.Name())
+ return "", err
+ }
+ return file.Name(), nil
+}
+
+func diff(b1, b2 []byte, filename string) (data []byte, err error) {
+ f1, err := writeTempFile("", "gofmt", b1)
+ if err != nil {
+ return
+ }
+ defer os.Remove(f1)
+
+ f2, err := writeTempFile("", "gofmt", b2)
+ if err != nil {
+ return
+ }
+ defer os.Remove(f2)
+
+ cmd := "diff"
+ if runtime.GOOS == "plan9" {
+ cmd = "/bin/ape/diff"
+ }
+
+ data, err = exec.Command(cmd, "-u", f1, f2).CombinedOutput()
+ if len(data) > 0 {
+ // diff exits with a non-zero status when the files don't match.
+ // Ignore that failure as long as we get output.
+ return replaceTempFilename(data, filename)
+ }
+ return
+}
+
+// replaceTempFilename replaces temporary filenames in diff with actual one.
+//
+// --- /tmp/gofmt316145376 2017-02-03 19:13:00.280468375 -0500
+// +++ /tmp/gofmt617882815 2017-02-03 19:13:00.280468375 -0500
+// ...
+// ->
+// --- path/to/file.go.orig 2017-02-03 19:13:00.280468375 -0500
+// +++ path/to/file.go 2017-02-03 19:13:00.280468375 -0500
+// ...
+func replaceTempFilename(diff []byte, filename string) ([]byte, error) {
+ bs := bytes.SplitN(diff, []byte{'\n'}, 3)
+ if len(bs) < 3 {
+ return nil, fmt.Errorf("got unexpected diff for %s", filename)
+ }
+ // Preserve timestamps.
+ var t0, t1 []byte
+ if i := bytes.LastIndexByte(bs[0], '\t'); i != -1 {
+ t0 = bs[0][i:]
+ }
+ if i := bytes.LastIndexByte(bs[1], '\t'); i != -1 {
+ t1 = bs[1][i:]
+ }
+ // Always print filepath with slash separator.
+ f := filepath.ToSlash(filename)
+ bs[0] = []byte(fmt.Sprintf("--- %s%s", f+".orig", t0))
+ bs[1] = []byte(fmt.Sprintf("+++ %s%s", f, t1))
+ return bytes.Join(bs, []byte{'\n'}), nil
+}
+
+// isFile reports whether name is a file.
+func isFile(name string) bool {
+ fi, err := os.Stat(name)
+ return err == nil && fi.Mode().IsRegular()
+}
+
+// isDir reports whether name is a directory.
+func isDir(name string) bool {
+ fi, err := os.Stat(name)
+ return err == nil && fi.IsDir()
+}
diff --git a/vendor/github.com/golangci/gofmt/goimports/golangci.go b/vendor/github.com/golangci/gofmt/goimports/golangci.go
new file mode 100644
index 000000000..e9d013d58
--- /dev/null
+++ b/vendor/github.com/golangci/gofmt/goimports/golangci.go
@@ -0,0 +1,33 @@
+package goimports
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+
+ "golang.org/x/tools/imports"
+)
+
+func Run(filename string) ([]byte, error) {
+ src, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return nil, err
+ }
+
+ res, err := imports.Process(filename, src, options)
+ if err != nil {
+ return nil, err
+ }
+
+ if bytes.Equal(src, res) {
+ return nil, nil
+ }
+
+ // formatting has changed
+ data, err := diff(src, res, filename)
+ if err != nil {
+ return nil, fmt.Errorf("error computing diff: %s", err)
+ }
+
+ return data, nil
+}