LoginSignup
0
0

More than 5 years have passed since last update.

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

Posted at

TR;DR

golang.org/x/tools を 2018-10-13 以降のバージョン,具体的には 13ebad8 が含まれるバージョンまでアップデートしましょう.

発端

ある日,grapi で .go generate ./...` を実行したら突然死した.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 を使っていた.

とりあえず pattern= で grep する.

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}
  }

internal/wire/parse.go#L332-L348

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

packagesgolang.org/x/tools/go/packages で, 静的解析まわりを使いやすくするためのラッパー.ここでもおもむろに "pattern" とかで grep する.

  // 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)
          }
      }
  }

go/packages/golist.go#L55-L84 - github.com/golang/tools@3c39ce7

引数をパースしてる.おもむろに blame すると,10/13のコミット で追加されたことがわかる.

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

余談

packages は内部で go list 叩くんですね.
go list の内部実装が internal になってるのを export しないのはなんでなんだろう.

// 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
  }

go/packages/golist.go#L185-L205@13ebad8 - github.com/golang/tools@13ebad8

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0