Skip to content

Commit

Permalink
Gazelle: fix import resolution for vendored WKT protos (#945)
Browse files Browse the repository at this point in the history
* When resolving proto_library dependencies, a vendor/ prefix will no
  longer be added in any case. These rules can't build because the
  protoc import paths are not modified (and can't be right now).
* go_proto_library dependencies for Well Known Types will be resolved
  to something in //vendor/github.com/golang/protobuf. This will
  change in the future when we have better support for alternative
  proto toolchains.
* There is now a special case for google/protobuf/descriptor.proto.

Fixes #888
Related #940
  • Loading branch information
jayconrod authored Oct 23, 2017
1 parent 697e080 commit 4374be3
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 40 deletions.
46 changes: 33 additions & 13 deletions go/tools/gazelle/resolve/resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package resolve
import (
"fmt"
"go/build"
"log"
"path"
"strings"

Expand Down Expand Up @@ -85,6 +86,7 @@ func (r *Resolver) ResolveGo(imp, pkgRel string) (Label, error) {
const (
wellKnownPrefix = "google/protobuf/"
wellKnownGoProtoPkg = "ptypes"
descriptorPkg = "protoc-gen-go/descriptor"
)

// ResolveProto resolves an import statement in a .proto file to a label
Expand All @@ -101,14 +103,6 @@ func (r *Resolver) ResolveProto(imp, pkgRel string) (Label, error) {
return Label{Repo: config.WellKnownTypesProtoRepo, Name: name}, nil
}

// Temporary hack: guess the label based on the proto file name. We assume
// all proto files in a directory belong to the same package, and the
// package name matches the directory base name. We also assume that protos
// in the vendor directory must refer to something else in vendor.
// TODO(#859): use dependency table to resolve once it exists.
if pkgRel == "vendor" || strings.HasPrefix(pkgRel, "vendor/") {
imp = path.Join("vendor", imp)
}
rel := path.Dir(imp)
if rel == "." {
rel = ""
Expand All @@ -127,12 +121,38 @@ func (r *Resolver) ResolveGoProto(imp, pkgRel string) (Label, error) {

if isWellKnown(imp) {
// Well Known Type
pkg := path.Join(wellKnownGoProtoPkg, path.Base(imp))
label := r.l.LibraryLabel(pkg)
if r.c.GoPrefix != config.WellKnownTypesGoPrefix {
label.Repo = config.WellKnownTypesGoProtoRepo
base := path.Base(imp)
if base == "descriptor" {
switch r.c.DepMode {
case config.ExternalMode:
label := r.l.LibraryLabel(descriptorPkg)
if r.c.GoPrefix != config.WellKnownTypesGoPrefix {
label.Repo = config.WellKnownTypesGoProtoRepo
}
return label, nil
case config.VendorMode:
pkg := path.Join("vendor", config.WellKnownTypesGoPrefix, descriptorPkg)
label := r.l.LibraryLabel(pkg)
return label, nil
default:
log.Panicf("unknown external mode: %v", r.c.DepMode)
}
}

switch r.c.DepMode {
case config.ExternalMode:
pkg := path.Join(wellKnownGoProtoPkg, base)
label := r.l.LibraryLabel(pkg)
if r.c.GoPrefix != config.WellKnownTypesGoPrefix {
label.Repo = config.WellKnownTypesGoProtoRepo
}
return label, nil
case config.VendorMode:
pkg := path.Join("vendor", config.WellKnownTypesGoPrefix, wellKnownGoProtoPkg, base)
return r.l.LibraryLabel(pkg), nil
default:
log.Panicf("unknown external mode: %v", r.c.DepMode)
}
return label, nil
}

// Temporary hack: guess the label based on the proto file name. We assume
Expand Down
66 changes: 39 additions & 27 deletions go/tools/gazelle/resolve/resolve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ func TestResolveProto(t *testing.T) {
prefix := "example.com/repo"
for _, tc := range []struct {
desc, imp, pkgRel string
mode config.StructureMode
structureMode config.StructureMode
depMode config.DependencyMode
wantProto, wantGoProto Label
}{
{
Expand All @@ -162,50 +163,61 @@ func TestResolveProto(t *testing.T) {
wantGoProto: Label{Pkg: "foo/bar", Name: config.DefaultLibName},
}, {
desc: "vendor",
depMode: config.VendorMode,
imp: "foo/bar/bar.proto",
pkgRel: "vendor",
wantProto: Label{Pkg: "vendor/foo/bar", Name: "bar_proto"},
wantProto: Label{Pkg: "foo/bar", Name: "bar_proto"},
wantGoProto: Label{Pkg: "vendor/foo/bar", Name: config.DefaultLibName},
}, {
desc: "vendor sub",
imp: "foo/bar/bar.proto",
pkgRel: "vendor/baz",
wantProto: Label{Pkg: "vendor/foo/bar", Name: "bar_proto"},
wantGoProto: Label{Pkg: "vendor/foo/bar", Name: config.DefaultLibName},
desc: "flat sub",
structureMode: config.FlatMode,
imp: "foo/bar/bar.proto",
wantProto: Label{Name: "foo/bar/bar_proto"},
wantGoProto: Label{Name: "foo/bar"},
}, {
desc: "flat sub",
mode: config.FlatMode,
imp: "foo/bar/bar.proto",
wantProto: Label{Name: "foo/bar/bar_proto"},
wantGoProto: Label{Name: "foo/bar"},
}, {
desc: "flat vendor",
mode: config.FlatMode,
imp: "foo/bar/bar.proto",
pkgRel: "vendor",
wantProto: Label{Name: "vendor/foo/bar/bar_proto"},
wantGoProto: Label{Name: "vendor/foo/bar"},
desc: "flat vendor",
structureMode: config.FlatMode,
depMode: config.VendorMode,
imp: "foo/bar/bar.proto",
pkgRel: "vendor",
wantProto: Label{Name: "foo/bar/bar_proto"},
wantGoProto: Label{Name: "vendor/foo/bar"},
}, {
desc: "well known",
imp: "google/protobuf/any.proto",
wantProto: Label{Repo: "com_google_protobuf", Name: "any_proto"},
wantGoProto: Label{Repo: "com_github_golang_protobuf", Pkg: "ptypes/any", Name: config.DefaultLibName},
}, {
desc: "well known flat",
mode: config.FlatMode,
imp: "google/protobuf/any.proto",
wantProto: Label{Repo: "com_google_protobuf", Name: "any_proto"},
wantGoProto: Label{Repo: "com_github_golang_protobuf", Name: "ptypes/any"},
desc: "well known flat",
structureMode: config.FlatMode,
imp: "google/protobuf/any.proto",
wantProto: Label{Repo: "com_google_protobuf", Name: "any_proto"},
wantGoProto: Label{Repo: "com_github_golang_protobuf", Name: "ptypes/any"},
}, {
desc: "well known vendor",
depMode: config.VendorMode,
imp: "google/protobuf/any.proto",
pkgRel: "vendor",
wantProto: Label{Repo: "com_google_protobuf", Name: "any_proto"},
wantGoProto: Label{Repo: "com_github_golang_protobuf", Pkg: "ptypes/any", Name: config.DefaultLibName},
wantGoProto: Label{Pkg: "vendor/github.com/golang/protobuf/ptypes/any", Name: config.DefaultLibName},
}, {
desc: "descriptor",
imp: "google/protobuf/descriptor.proto",
wantProto: Label{Repo: "com_google_protobuf", Name: "descriptor_proto"},
wantGoProto: Label{Repo: "com_github_golang_protobuf", Pkg: "protoc-gen-go/descriptor", Name: config.DefaultLibName},
}, {
desc: "descriptor vendor",
depMode: config.VendorMode,
imp: "google/protobuf/descriptor.proto",
wantProto: Label{Repo: "com_google_protobuf", Name: "descriptor_proto"},
wantGoProto: Label{Pkg: "vendor/github.com/golang/protobuf/protoc-gen-go/descriptor", Name: config.DefaultLibName},
},
} {
t.Run(tc.desc, func(t *testing.T) {
c := &config.Config{GoPrefix: prefix, StructureMode: tc.mode}
c := &config.Config{
GoPrefix: prefix,
DepMode: tc.depMode,
StructureMode: tc.structureMode,
}
l := NewLabeler(c)
r := NewResolver(c, l)

Expand Down

0 comments on commit 4374be3

Please sign in to comment.