Skip to content

Commit

Permalink
Add 'go_naming_convention' support.
Browse files Browse the repository at this point in the history
Add directive 'go_naming_convention' to control the name of
generated Go rules.

go_default_library: Legacy behaviour.
import: Name targets after their import path.
import_alias: Same as import, but generate alias targets to
  maintain backwards compatibility with go_default_library.

We also add a `build_naming_convention` attribute to
`go_repository` rules, allowing per-external control over
the naming convention.

gazelle fix is augmented to migrate between the different
styles, both forwards and backwards.

FIXES=bazel-contrib#5
  • Loading branch information
tomlu committed Jun 10, 2020
1 parent be9c2a8 commit bc48cd1
Show file tree
Hide file tree
Showing 34 changed files with 1,381 additions and 38 deletions.
21 changes: 21 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,11 @@ The following flags are accepted:
| See `Predefined plugins`_ for available options; commonly used options include |
| ``@io_bazel_rules_go//proto:gofast_grpc`` and ``@io_bazel_rules_go//proto:gogofaster_grpc``. |
+--------------------------------------------------------------+----------------------------------------+
| :flag:`-go_naming_convention` | |
+--------------------------------------------------------------+----------------------------------------+
| Controls the names of generated Go targets. Equivalent to the |
| # gazelle:go_naming_convention directive. |
+--------------------------------------------------------------+----------------------------------------+
| :flag:`-go_prefix example.com/repo` | |
+--------------------------------------------------------------+----------------------------------------+
| A prefix of import paths for libraries in the repository that corresponds to |
Expand Down Expand Up @@ -575,6 +580,22 @@ The following directives are recognized:
| ``@io_bazel_rules_go//proto:gofast_grpc`` and |
| ``@io_bazel_rules_go//proto:gogofaster_grpc``. |
+---------------------------------------------------+----------------------------------------+
| :direc:`# gazelle:go_naming_convention` | n/a |
+---------------------------------------------------+----------------------------------------+
| Controls the names of generated Go targets. By default, library targets are named |
| `go_default_library` and test targets `go_default_test`. |
| Valid values are: |
| * ``go_default_library``: Library targets are named ``go_default_library``, test targets |
| are named ``go_default_test``. |
| * ``import``: Library and test targets are named after the last segment of their import |
| path. |
| For example, ``example.repo/foo`` is named ``foo``, and the test target is ``foo_test``. |
| Major version suffixes like ``/v2`` are dropped. |
| For a main package with a binary ``foobin``, the names are instead ``foobin_lib`` and |
| ``foobin_test``. |
| * ``import_alias``: Same as ``import``, but an ``alias`` target is generated named |
| ``go_default_library`` to ensure backwards compatibility. |
+---------------------------------------------------+----------------------------------------+
| :direc:`# gazelle:go_proto_compilers` | ``@io_bazel_rules_go//proto:go_proto`` |
+---------------------------------------------------+----------------------------------------+
| The protocol buffers compiler(s) to use for building go bindings. |
Expand Down
11 changes: 7 additions & 4 deletions cmd/gazelle/fix-update.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,15 @@ func (ucr *updateConfigurer) CheckFlags(fs *flag.FlagSet, c *config.Config) erro
GoPrefix: imp,
})
}
goRepos := make(map[string]repo.Repo)
for _, r := range c.Repos {
if r.Kind() == "go_repository" {
uc.repos = append(uc.repos, repo.Repo{
Name: r.Name(),
GoPrefix: r.AttrString("importpath"),
})
gr := repo.Repo{
Name: r.Name(),
GoPrefix: r.AttrString("importpath"),
}
uc.repos = append(uc.repos, gr)
goRepos[r.Name()] = gr
}
}

Expand Down
9 changes: 8 additions & 1 deletion internal/go_repository.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,6 @@ go_repository = repository_rule(
attrs = {
# Fundamental attributes of a go repository
"importpath": attr.string(mandatory = True),

# Attributes for a repository that should be checked out from VCS
"commit": attr.string(),
"tag": attr.string(),
Expand Down Expand Up @@ -235,6 +234,14 @@ go_repository = repository_rule(
"off",
],
),
"build_naming_convention": attr.string(
values = [
"",
"go_default_library",
"import",
"import_alias",
],
),
"build_tags": attr.string_list(),
"build_file_proto_mode": attr.string(
values = [
Expand Down
90 changes: 89 additions & 1 deletion language/go/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ type goConfig struct {
// goGenerateProto indicates whether to generate go_proto_library
goGenerateProto bool

// goNamingConvention controls the name of generated targets
goNamingConvention namingConvention

// goProtoCompilers is the protocol buffers compiler(s) to use for go code.
goProtoCompilers []string

Expand Down Expand Up @@ -104,6 +107,10 @@ type goConfig struct {
// resolved differently (also depending on goRepositoryMode).
moduleMode bool

// map between external repo names and their `build_naming_convention`
// attribute.
repoNamingConvention map[string]namingConvention

// submodules is a list of modules which have the current module's path
// as a prefix of their own path. This affects visibility attributes
// in internal packages.
Expand Down Expand Up @@ -171,6 +178,15 @@ func (gc *goConfig) setBuildTags(tags string) error {
return nil
}

func (gc *goConfig) setNamingConvention(s string) error {
if nc, err := namingConventionFromString(s); err == nil {
gc.goNamingConvention = nc
return nil
} else {
return err
}
}

func getProtoMode(c *config.Config) proto.Mode {
if gc := getGoConfig(c); !gc.goGenerateProto {
return proto.DisableMode
Expand Down Expand Up @@ -236,6 +252,59 @@ func (f tagsFlag) String() string {
return ""
}

type namingConventionFlag func(string) error

func (f namingConventionFlag) Set(value string) error {
return f(value)
}

func (f namingConventionFlag) String() string {
return ""
}

// namingConvention determines how go targets are named.
type namingConvention int

const (
// 'go_default_library' and 'go_default_test'
goDefaultLibraryNamingConvention = iota

// For an import path that ends with foo, the go_library rules target is
// named 'foo', the go_test is named 'foo_test'.
// For a main package, the go_binary takes the 'foo' name, the library
// is named 'foo_lib', and the go_test is named 'foo_test'.
importNamingConvention

// Same as importNamingConvention, but generate alias rules for libraries that have
// the legacy 'go_default_library' name.
importAliasNamingConvention
)

func (nc namingConvention) String() string {
switch nc {
case goDefaultLibraryNamingConvention:
return "go_default_library"
case importNamingConvention:
return "import"
case importAliasNamingConvention:
return "import_alias"
}
return ""
}

func namingConventionFromString(s string) (namingConvention, error) {
switch s {
case "go_default_library":
return goDefaultLibraryNamingConvention, nil
case "import":
return importNamingConvention, nil
case "import_alias":
return importAliasNamingConvention, nil
default:
return goDefaultLibraryNamingConvention, fmt.Errorf("unknown naming convention %q", s)
}
}

type moduleRepo struct {
repoName, modulePath string
}
Expand All @@ -249,6 +318,7 @@ func (*goLang) KnownDirectives() []string {
"build_tags",
"go_generate_proto",
"go_grpc_compilers",
"go_naming_convention",
"go_proto_compilers",
"go_visibility",
"importmap_prefix",
Expand Down Expand Up @@ -290,6 +360,10 @@ func (*goLang) RegisterFlags(fs *flag.FlagSet, cmd string, c *config.Config) {
"go_repository_module_mode",
false,
"set when gazelle is invoked by go_repository in module mode")
fs.Var(
namingConventionFlag(gc.setNamingConvention),
"go_naming_convention",
"controls generated library names. One of (go_default_library, import, import_alias)")

case "update-repos":
fs.Var(&gzflag.AllowedStringFlag{Value: &gc.buildExternalAttr, Allowed: validBuildExternalAttr},
Expand Down Expand Up @@ -372,6 +446,17 @@ Update io_bazel_rules_go to a newer version in your WORKSPACE file.`
log.Printf("Found RULES_GO_VERSION %s. Minimum compatible version is %s.\n%s", gc.rulesGoVersion, minimumRulesGoVersion, message)
}
}
repoNamingConvention := map[string]namingConvention{}
for _, repo := range c.Repos {
if repo.Kind() == "go_repository" {
if nc, err := namingConventionFromString(repo.AttrString("build_naming_convention")); err == nil {
repoNamingConvention[repo.Name()] = nc
} else {
log.Printf("%v\n", err)
}
}
}
gc.repoNamingConvention = repoNamingConvention
}

if !gc.moduleMode {
Expand Down Expand Up @@ -408,12 +493,15 @@ Update io_bazel_rules_go to a newer version in your WORKSPACE file.`
gc.preprocessTags()
gc.setBuildTags(d.Value)
case "go_generate_proto":

if goGenerateProto, err := strconv.ParseBool(d.Value); err == nil {
gc.goGenerateProto = goGenerateProto
} else {
log.Printf("parsing go_generate_proto: %v", err)
}
case "go_naming_convention":
if err := gc.setNamingConvention(d.Value); err != nil {
log.Print(err)
}
case "go_grpc_compilers":
// Special syntax (empty value) to reset directive.
if d.Value == "" {
Expand Down
4 changes: 4 additions & 0 deletions language/go/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func TestCommandLine(t *testing.T) {
t,
"-build_tags=foo,bar",
"-go_prefix=example.com/repo",
"-go_naming_convention=import_alias",
"-external=vendored",
"-repo_root=.")
gc := getGoConfig(c)
Expand All @@ -78,6 +79,9 @@ func TestCommandLine(t *testing.T) {
if gc.depMode != vendorMode {
t.Errorf("got dep mode %v; want %v", gc.depMode, vendorMode)
}
if gc.goNamingConvention != importAliasNamingConvention {
t.Errorf("got naming convention %v; want %v", gc.goNamingConvention, importAliasNamingConvention)
}
}

func TestDirectives(t *testing.T) {
Expand Down
Loading

0 comments on commit bc48cd1

Please sign in to comment.