Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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

izumin5210
ʕ ◔ϖ◔ʔ < I'm a Rubyist.
https://blog.izum.in
wantedly
「シゴトでココロオドル」ためのビジネスSNS「Wantedly」の開発・運営をしています。
https://wantedlyinc.com/ja/presentations
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした