wire に `-: cannot find package "pattern=." in any of:` って言われたら

## TR;DR

`golang.org/x/tools` を 2018-10-13 以降のバージョン，具体的には [`13ebad8`](https://github.com/golang/tools/commit/13ebad898d587c5cd7762e13ce1393af81826e8d) が含まれるバージョンまでアップデートしましょう．


## 発端

ある日，grapi で .go generate ./...` を実行したら突然死した．[wire](https://github.com/google/wire) がすべて失敗しているようだった．

```
-: cannot find package "pattern=." in any of:
                /usr/local/Cellar/go/1.11.1/libexec/src/pattern=. (from $GOROOT)
                /Users/izumin/src/pattern=. (from $GOPATH)
wire: generate failed
cmd/grapi-gen-type/di/wire_gen.go:3: running "wire": exit status 1
```

`pattern=.` とは :thinking: 


## 調査
当時の wire のバージョンは [v0.2.0](https://github.com/google/wire/releases/tag/v0.2.0) を使っていた．

とりあえず `pattern=` で grep する．

> ```go
> func load(ctx context.Context, wd string, env []string, patterns []string) ([]*packages.Package, []error) {
> 	cfg := &packages.Config{
> 		Context:    ctx,
> 		Mode:       packages.LoadAllSyntax,
> 		Dir:        wd,
> 		Env:        env,
> 		BuildFlags: []string{"-tags=wireinject"},
> 		// TODO(light): Use ParseFile to skip function bodies and comments in indirect packages.
> 	}
> 	escaped := make([]string, len(patterns))
> 	for i := range patterns {
> 		escaped[i] = "pattern=" + patterns[i]
> 	}
> 	pkgs, err := packages.Load(cfg, escaped...)
> 	if err != nil {
> 		return nil, []error{err}
> 	}
> ```
> 
> <cite>[internal/wire/parse.go#L332-L348](https://github.com/google/wire/blob/v0.2.0/internal/wire/parse.go#L332-L348)</cite>

`internal/wire.load` はコード生成時の初っ端に呼ばれる関数．`patterns` には引数 or `.` が入っている．これの各要素に対して `pattern=` という prefix をつけている．

`packages` は [`golang.org/x/tools/go/packages`](https://godoc.org/golang.org/x/tools/go/packages) で， 静的解析まわりを使いやすくするためのラッパー．ここでもおもむろに `"pattern"` とかで grep する．


> ```go
> 	// Extract file= and other [querytype]= patterns. Report an error if querytype
> 	// doesn't exist.
> extractQueries:
> 	for _, pattern := range patterns {
> 		eqidx := strings.Index(pattern, "=")
> 		if eqidx < 0 {
> 			restPatterns = append(restPatterns, pattern)
> 		} else {
> 			query, value := pattern[:eqidx], pattern[eqidx+len("="):]
> 			switch query {
> 			case "file":
> 				containFiles = append(containFiles, value)
> 			case "pattern":
> 				restPatterns = append(restPatterns, value)
> 			case "name":
> 				packagesNamed = append(packagesNamed, value)
> 			case "": // not a reserved query
> 				restPatterns = append(restPatterns, pattern)
> 			default:
> 				for _, rune := range query {
> 					if rune < 'a' || rune > 'z' { // not a reserved query
> 						restPatterns = append(restPatterns, pattern)
> 						continue extractQueries
> 					}
> 				}
> 				// Reject all other patterns containing "="
> 				return nil, fmt.Errorf("invalid query type %q in query pattern %q", query, pattern)
> 			}
> 		}
> 	}
> ```
>
> <cite>[go/packages/golist.go#L55-L84 - github.com/golang/tools@3c39ce7](https://github.com/golang/tools/blob/3c39ce7b61056afe4473b651789da5f89d4aeb20/go/packages/golist.go#L55-L84)</cite>

引数をパースしてる．おもむろに blame すると，[10/13のコミット](https://github.com/golang/tools/commit/13ebad898d587c5cd7762e13ce1393af81826e8d) で追加されたことがわかる．

と，いうことで `golang.org/x/tools` のバージョンを上げましょう．


## 余談
`packages` は内部で `go list` 叩くんですね．
[`go list` の内部実装が `internal` になってる](https://github.com/golang/go/tree/go1.11.4/src/cmd/go/internal/list)のを export しないのはなんでなんだろう．

> ```go
> // golistDriverCurrent uses the "go list" command to expand the
> // pattern words and return metadata for the specified packages.
> // dir may be "" and env may be nil, as per os/exec.Command.
> func golistDriverCurrent(cfg *Config, words ...string) (*driverResponse, error) {
> 	// go list uses the following identifiers in ImportPath and Imports:
> 	//
> 	// 	"p"			-- importable package or main (command)
> 	//      "q.test"		-- q's test executable
> 	// 	"p [q.test]"		-- variant of p as built for q's test executable
> 	//	"q_test [q.test]"	-- q's external test package
> 	//
> 	// The packages p that are built differently for a test q.test
> 	// are q itself, plus any helpers used by the external test q_test,
> 	// typically including "testing" and all its dependencies.
> 
> 	// Run "go list" for complete
> 	// information on the specified packages.
> 	buf, err := golist(cfg, golistargs(cfg, words))
> 	if err != nil {
> 		return nil, err
> 	}
> ```
>
> <cite>[go/packages/golist.go#L185-L205@13ebad8 - github.com/golang/tools@13ebad8](https://github.com/golang/tools/blob/13ebad898d587c5cd7762e13ce1393af81826e8d/go/packages/golist.go#L185-L205)</cite>