diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cf6ffeb66..83a0ad1d1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,7 +29,7 @@ the one above, the add [tests](https://github.com/bazelbuild/bazel-gazelle/tree/master/tests). Run the existing tests with `bazel test //...`. Update [README.rst](https://github.com/bazelbuild/bazel-gazelle/blob/master/README.rst) - if appropriate. + if appropriate. 1. [Create a pull request](https://help.github.com/articles/creating-a-pull-request/). This will start the code review process. **All submissions, including submissions by project members, require review.** diff --git a/README.rst b/README.rst index 55e411996..5e70eded7 100644 --- a/README.rst +++ b/README.rst @@ -329,134 +329,134 @@ Subdirectories will be processed recursively. The following flags are accepted: -+--------------------------------------------------------------+----------------------------------------+ -| **Name** | **Default value** | -+==============================================================+========================================+ -| :flag:`-build_file_name file1,file2,...` | :value:`BUILD.bazel,BUILD` | -+--------------------------------------------------------------+----------------------------------------+ -| Comma-separated list of file names. Gazelle recognizes these files as Bazel | -| build files. New files will use the first name in this list. Use this if | -| your project contains non-Bazel files named ``BUILD`` (or ``build`` on | -| case-insensitive file systems). | -+--------------------------------------------------------------+----------------------------------------+ -| :flag:`-build_tags tag1,tag2` | | -+--------------------------------------------------------------+----------------------------------------+ -| List of Go build tags Gazelle will consider to be true. Gazelle applies | -| constraints when generating Go rules. It assumes certain tags are true on | -| certain platforms (for example, ``amd64,linux``). It assumes all Go release | -| tags are true (for example, ``go1.8``). It considers other tags to be false | -| (for example, ``ignore``). This flag overrides that behavior. | -| | -| Bazel may still filter sources with these tags. Use | -| ``bazel build --define gotags=foo,bar`` to set tags at build time. | -+--------------------------------------------------------------+----------------------------------------+ -| :flag:`-exclude pattern` | | -+--------------------------------------------------------------+----------------------------------------+ -| Prevents Gazelle from processing a file or directory if the given | -| `doublestar.Match`_ pattern matches. If the pattern refers to a source file, | -| Gazelle won't include it in any rules. If the pattern refers to a directory, | -| Gazelle won't recurse into it. | -| | -| This option may be repeated. Patterns must be slash-separated, relative to the | -| repository root. This is equivalent to the ``# gazelle:exclude pattern`` | -| directive. | -+--------------------------------------------------------------+----------------------------------------+ -| :flag:`-external external|vendored` | :value:`external` | -+--------------------------------------------------------------+----------------------------------------+ -| Determines how Gazelle resolves import paths that cannot be resolve in the | -| current repository. May be :value:`external` or :value:`vendored`. See | -| `Dependency resolution`_. | -+--------------------------------------------------------------+----------------------------------------+ -| :flag:`-index true|false` | :value:`true` | -+--------------------------------------------------------------+----------------------------------------+ -| Determines whether Gazelle should index the libraries in the current repository and whether it | -| should use the index to resolve dependencies. If this is switched off, Gazelle would rely on | -| ``# gazelle:prefix`` directive or ``-go_prefix`` flag to resolve dependencies. | -+--------------------------------------------------------------+----------------------------------------+ -| :flag:`-go_grpc_compiler` | ``@io_bazel_rules_go//proto:go_grpc`` | -+--------------------------------------------------------------+----------------------------------------+ -| The protocol buffers compiler to use for building go bindings for gRPC. May be repeated. | -| | -| 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. See details in | -| `Directives`_ below. | -+--------------------------------------------------------------+----------------------------------------+ -| :flag:`-go_naming_convention_external` | | -+--------------------------------------------------------------+----------------------------------------+ -| Controls the default naming convention used when resolving libraries in | -| external repositories with unknown naming conventions. Equivalent to the | -| ``# gazelle:go_naming_convention_external`` directive. | -+--------------------------------------------------------------+----------------------------------------+ -| :flag:`-go_prefix example.com/repo` | | -+--------------------------------------------------------------+----------------------------------------+ -| A prefix of import paths for libraries in the repository that corresponds to | -| the repository root. Equivalent to setting the ``# gazelle:prefix`` directive | -| in the root BUILD.bazel file or the ``prefix`` attribute of the ``gazelle`` rule. If | -| neither of those are set, this option is mandatory. | -| | -| This prefix is used to determine whether an import path refers to a library | -| in the current repository or an external dependency. | -+--------------------------------------------------------------+----------------------------------------+ -| :flag:`-go_proto_compiler` | ``@io_bazel_rules_go//proto:go_proto`` | -+--------------------------------------------------------------+----------------------------------------+ -| The protocol buffers compiler to use for building go bindings. May be repeated. | -| | -| See `Predefined plugins`_ for available options; commonly used options include | -| ``@io_bazel_rules_go//proto:gofast_proto`` and ``@io_bazel_rules_go//proto:gogofaster_proto``. | -+--------------------------------------------------------------+----------------------------------------+ -| :flag:`-known_import example.com` | | -+--------------------------------------------------------------+----------------------------------------+ -| Skips import path resolution for a known domain. May be repeated. | -| | -| When Gazelle resolves an import path to an external dependency, it attempts | -| to discover the remote repository root over HTTP. Gazelle skips this | -| discovery step for a few well-known domains with predictable structure, like | -| golang.org and github.com. This flag specifies additional domains to skip, | -| which is useful in situations where the lookup would fail for some reason. | -+--------------------------------------------------------------+----------------------------------------+ -| :flag:`-mode fix|print|diff` | :value:`fix` | -+--------------------------------------------------------------+----------------------------------------+ -| Method for emitting merged build files. | -| | -| In ``fix`` mode, Gazelle writes generated and merged files to disk. In | -| ``print`` mode, it prints them to stdout. In ``diff`` mode, it prints a | -| unified diff. | -+--------------------------------------------------------------+----------------------------------------+ -| :flag:`-proto default|package|legacy|disable|disable_global` | :value:`default` | -+--------------------------------------------------------------+----------------------------------------+ -| Determines how Gazelle should generate rules for .proto files. See details | -| in `Directives`_ below. | -+--------------------------------------------------------------+----------------------------------------+ -| :flag:`-proto_group group` | :value:`""` | -+--------------------------------------------------------------+----------------------------------------+ -| Determines the proto option Gazelle uses to group .proto files into rules | -| when in ``package`` mode. See details in `Directives`_ below. | -+--------------------------------------------------------------+----------------------------------------+ -| :flag:`-proto_import_prefix path` | | -+--------------------------------------------------------------+----------------------------------------+ -| Sets the `import_prefix`_ attribute of generated ``proto_library`` rules. | -| This adds a prefix to the string used to import ``.proto`` files listed in | -| the ``srcs`` attribute of generated rules. Equivalent to the | -| ``# gazelle:proto_import_prefix`` directive. See details in `Directives`_ below. | -+--------------------------------------------------------------+----------------------------------------+ -| :flag:`-repo_root dir` | | -+--------------------------------------------------------------+----------------------------------------+ -| The root directory of the repository. Gazelle normally infers this to be the | -| directory containing the WORKSPACE file. | -| | -| Gazelle will not process packages outside this directory. | -+--------------------------------------------------------------+----------------------------------------+ -| :flag:`-lang lang1,lang2,...` | :value:`""` | -+--------------------------------------------------------------+----------------------------------------+ -| Selects languages for which to compose and index rules. | -| | -| By default, all languages that this Gazelle was built with are processed. | -+--------------------------------------------------------------+----------------------------------------+ ++===================================================================+========================================+ +| **Name** | **Default value** | ++-------------------------------------------------------------------+----------------------------------------+ +| :flag:`-build_file_name file1,file2,...` | :value:`BUILD.bazel,BUILD` | ++-------------------------------------------------------------------+----------------------------------------+ +| Comma-separated list of file names. Gazelle recognizes these files as Bazel | +| build files. New files will use the first name in this list. Use this if | +| your project contains non-Bazel files named ``BUILD`` (or ``build`` on | +| case-insensitive file systems). | ++-------------------------------------------------------------------+----------------------------------------+ +| :flag:`-build_tags tag1,tag2` | | ++-------------------------------------------------------------------+----------------------------------------+ +| List of Go build tags Gazelle will consider to be true. Gazelle applies | +| constraints when generating Go rules. It assumes certain tags are true on | +| certain platforms (for example, ``amd64,linux``). It assumes all Go release | +| tags are true (for example, ``go1.8``). It considers other tags to be false | +| (for example, ``ignore``). This flag overrides that behavior. | +| | +| Bazel may still filter sources with these tags. Use | +| ``bazel build --define gotags=foo,bar`` to set tags at build time. | ++-------------------------------------------------------------------+----------------------------------------+ +| :flag:`-exclude pattern` | | ++-------------------------------------------------------------------+----------------------------------------+ +| Prevents Gazelle from processing a file or directory if the given | +| `doublestar.Match`_ pattern matches. If the pattern refers to a source file, | +| Gazelle won't include it in any rules. If the pattern refers to a directory, | +| Gazelle won't recurse into it. | +| | +| This option may be repeated. Patterns must be slash-separated, relative to the | +| repository root. This is equivalent to the ``# gazelle:exclude pattern`` | +| directive. | ++-------------------------------------------------------------------+----------------------------------------+ +| :flag:`-external external|vendored` | :value:`external` | ++-------------------------------------------------------------------+----------------------------------------+ +| Determines how Gazelle resolves import paths that cannot be resolve in the | +| current repository. May be :value:`external` or :value:`vendored`. See | +| `Dependency resolution`_. | ++-------------------------------------------------------------------+----------------------------------------+ +| :flag:`-index true|false` | :value:`true` | ++-------------------------------------------------------------------+----------------------------------------+ +| Determines whether Gazelle should index the libraries in the current repository and whether it | +| should use the index to resolve dependencies. If this is switched off, Gazelle would rely on | +| ``# gazelle:prefix`` directive or ``-go_prefix`` flag to resolve dependencies. | ++-------------------------------------------------------------------+----------------------------------------+ +| :flag:`-go_grpc_compiler` | ``@io_bazel_rules_go//proto:go_grpc`` | ++-------------------------------------------------------------------+----------------------------------------+ +| The protocol buffers compiler to use for building go bindings for gRPC. May be repeated. | +| | +| 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. See details in | +| `Directives`_ below. | ++-------------------------------------------------------------------+----------------------------------------+ +| :flag:`-go_naming_convention_external` | | ++-------------------------------------------------------------------+----------------------------------------+ +| Controls the default naming convention used when resolving libraries in | +| external repositories with unknown naming conventions. Equivalent to the | +| ``# gazelle:go_naming_convention_external`` directive. | ++-------------------------------------------------------------------+----------------------------------------+ +| :flag:`-go_prefix example.com/repo` | | ++-------------------------------------------------------------------+----------------------------------------+ +| A prefix of import paths for libraries in the repository that corresponds to | +| the repository root. Equivalent to setting the ``# gazelle:prefix`` directive | +| in the root BUILD.bazel file or the ``prefix`` attribute of the ``gazelle`` rule. If | +| neither of those are set, this option is mandatory. | +| | +| This prefix is used to determine whether an import path refers to a library | +| in the current repository or an external dependency. | ++-------------------------------------------------------------------+----------------------------------------+ +| :flag:`-go_proto_compiler` | ``@io_bazel_rules_go//proto:go_proto`` | ++-------------------------------------------------------------------+----------------------------------------+ +| The protocol buffers compiler to use for building go bindings. May be repeated. | +| | +| See `Predefined plugins`_ for available options; commonly used options include | +| ``@io_bazel_rules_go//proto:gofast_proto`` and ``@io_bazel_rules_go//proto:gogofaster_proto``. | ++-------------------------------------------------------------------+----------------------------------------+ +| :flag:`-known_import example.com` | | ++-------------------------------------------------------------------+----------------------------------------+ +| Skips import path resolution for a known domain. May be repeated. | +| | +| When Gazelle resolves an import path to an external dependency, it attempts | +| to discover the remote repository root over HTTP. Gazelle skips this | +| discovery step for a few well-known domains with predictable structure, like | +| golang.org and github.com. This flag specifies additional domains to skip, | +| which is useful in situations where the lookup would fail for some reason. | ++-------------------------------------------------------------------+----------------------------------------+ +| :flag:`-mode fix|print|diff` | :value:`fix` | ++-------------------------------------------------------------------+----------------------------------------+ +| Method for emitting merged build files. | +| | +| In ``fix`` mode, Gazelle writes generated and merged files to disk. In | +| ``print`` mode, it prints them to stdout. In ``diff`` mode, it prints a | +| unified diff. | ++-------------------------------------------------------------------+----------------------------------------+ +| :flag:`-proto default|file|package|legacy|disable|disable_global` | :value:`default` | ++-------------------------------------------------------------------+----------------------------------------+ +| Determines how Gazelle should generate rules for .proto files. See details | +| in `Directives`_ below. | ++-------------------------------------------------------------------+----------------------------------------+ +| :flag:`-proto_group group` | :value:`""` | ++-------------------------------------------------------------------+----------------------------------------+ +| Determines the proto option Gazelle uses to group .proto files into rules | +| when in ``package`` mode. See details in `Directives`_ below. | ++-------------------------------------------------------------------+----------------------------------------+ +| :flag:`-proto_import_prefix path` | | ++-------------------------------------------------------------------+----------------------------------------+ +| Sets the `import_prefix`_ attribute of generated ``proto_library`` rules. | +| This adds a prefix to the string used to import ``.proto`` files listed in | +| the ``srcs`` attribute of generated rules. Equivalent to the | +| ``# gazelle:proto_import_prefix`` directive. See details in `Directives`_ below. | ++-------------------------------------------------------------------+----------------------------------------+ +| :flag:`-repo_root dir` | | ++-------------------------------------------------------------------+----------------------------------------+ +| The root directory of the repository. Gazelle normally infers this to be the | +| directory containing the WORKSPACE file. | +| | +| Gazelle will not process packages outside this directory. | ++-------------------------------------------------------------------+----------------------------------------+ +| :flag:`-lang lang1,lang2,...` | :value:`""` | ++-------------------------------------------------------------------+----------------------------------------+ +| Selects languages for which to compose and index rules. | +| | +| By default, all languages that this Gazelle was built with are processed. | ++===================================================================+========================================+ .. _Predefined plugins: https://github.com/bazelbuild/rules_go/blob/master/proto/core.rst#predefined-plugins @@ -729,6 +729,7 @@ The following directives are recognized: | * ``default``: ``proto_library``, ``go_proto_library``, and ``go_library`` | | rules are generated using ``@io_bazel_rules_go//proto:def.bzl``. Only one | | of each rule may be generated per directory. This is the default mode. | +| * ``file``: a ``proto_library`` rule is generated for every .proto file. | | * ``package``: multiple ``proto_library`` and ``go_proto_library`` rules | | may be generated in the same directory. .proto files are grouped into | | rules based on their package name or another option (see ``proto_group``). | diff --git a/language/proto/config.go b/language/proto/config.go index a0bc20648..c86eddd41 100644 --- a/language/proto/config.go +++ b/language/proto/config.go @@ -97,6 +97,9 @@ const ( // PackageMode generates a proto_library for each set of .proto files with // the same package name in each directory. PackageMode + + // FileMode generates a proto_library for each .proto file. + FileMode ) func ModeFromString(s string) (Mode, error) { @@ -111,6 +114,8 @@ func ModeFromString(s string) (Mode, error) { return LegacyMode, nil case "package": return PackageMode, nil + case "file": + return FileMode, nil default: return 0, fmt.Errorf("unrecognized proto mode: %q", s) } @@ -128,6 +133,8 @@ func (m Mode) String() string { return "legacy" case PackageMode: return "package" + case FileMode: + return "file" default: log.Panicf("unknown mode %d", m) return "" diff --git a/language/proto/generate.go b/language/proto/generate.go index 2b4eabd39..5fdcf1d4d 100644 --- a/language/proto/generate.go +++ b/language/proto/generate.go @@ -119,7 +119,10 @@ func buildPackages(pc *ProtoConfig, dir, rel string, protoFiles, genFiles []stri for _, name := range protoFiles { info := protoFileInfo(dir, name) key := info.PackageName - if pc.groupOption != "" { + + if pc.Mode == FileMode { + key = strings.TrimSuffix(name, ".proto") + } else if pc.groupOption != "" { // implicitly PackageMode for _, opt := range info.Options { if opt.Key == pc.groupOption { key = opt.Value @@ -127,10 +130,14 @@ func buildPackages(pc *ProtoConfig, dir, rel string, protoFiles, genFiles []stri } } } + if packageMap[key] == nil { packageMap[key] = newPackage(info.PackageName) } packageMap[key].addFile(info) + if key != info.PackageName { + packageMap[key].RuleName = key + } } switch pc.Mode { @@ -147,7 +154,7 @@ func buildPackages(pc *ProtoConfig, dir, rel string, protoFiles, genFiles []stri } return []*Package{pkg} - case PackageMode: + case PackageMode, FileMode: pkgs := make([]*Package, 0, len(packageMap)) for _, pkg := range packageMap { pkgs = append(pkgs, pkg) @@ -212,7 +219,7 @@ func generateProto(pc *ProtoConfig, rel string, pkg *Package, shouldSetVisibilit if pc.Mode == DefaultMode { name = RuleName(goPackageName(pkg), pc.GoPrefix, rel) } else { - name = RuleName(pkg.Options[pc.groupOption], pkg.Name, rel) + name = RuleName(pkg.RuleName, pkg.Name, rel) } r := rule.NewRule("proto_library", name) srcs := make([]string, 0, len(pkg.Files)) diff --git a/language/proto/package.go b/language/proto/package.go index fba05f0c3..8b17a5d0b 100644 --- a/language/proto/package.go +++ b/language/proto/package.go @@ -21,6 +21,7 @@ import "path/filepath" // same package name. This translates to a proto_library rule. type Package struct { Name string + RuleName string // if not set, defaults to Name Files map[string]FileInfo Imports map[string]bool Options map[string]string diff --git a/language/proto/resolve_test.go b/language/proto/resolve_test.go index 5e189d72d..8f3ceea63 100644 --- a/language/proto/resolve_test.go +++ b/language/proto/resolve_test.go @@ -350,6 +350,41 @@ proto_library( name = "dep_proto", deps = ["//foo:foo_proto"], ) +`, + }, { + desc: "test single file resolution in file mode", + index: []buildFile{{ + rel: "somedir", + content: ` +# gazelle:proto file + +proto_library( + name = "foo_proto", + srcs = ["foo.proto"], +) + +proto_library( + name = "bar_proto", + srcs = ["bar.proto"], +) + +proto_library( + name = "baz_proto", + srcs = ["baz.proto"], +) +`, + }}, + old: ` +proto_library( + name = "other_proto", + _imports = ["somedir/bar.proto"], +) +`, + want: ` +proto_library( + name = "other_proto", + deps = ["//somedir:bar_proto"], +) `, }, } { diff --git a/language/proto/testdata/file_mode/BUILD.old b/language/proto/testdata/file_mode/BUILD.old new file mode 100644 index 000000000..fe57d9d3d --- /dev/null +++ b/language/proto/testdata/file_mode/BUILD.old @@ -0,0 +1 @@ +# gazelle:proto file diff --git a/language/proto/testdata/file_mode/BUILD.want b/language/proto/testdata/file_mode/BUILD.want new file mode 100644 index 000000000..d34e19b4a --- /dev/null +++ b/language/proto/testdata/file_mode/BUILD.want @@ -0,0 +1,13 @@ +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "bar_proto", + srcs = ["bar.proto"], + visibility = ["//visibility:public"], +) + +proto_library( + name = "foo_proto", + srcs = ["foo.proto"], + visibility = ["//visibility:public"], +) diff --git a/language/proto/testdata/file_mode/bar.proto b/language/proto/testdata/file_mode/bar.proto new file mode 100644 index 000000000..1529c0383 --- /dev/null +++ b/language/proto/testdata/file_mode/bar.proto @@ -0,0 +1,3 @@ +syntax = "proto3"; + +package file_mode; diff --git a/language/proto/testdata/file_mode/foo.proto b/language/proto/testdata/file_mode/foo.proto new file mode 100644 index 000000000..1529c0383 --- /dev/null +++ b/language/proto/testdata/file_mode/foo.proto @@ -0,0 +1,3 @@ +syntax = "proto3"; + +package file_mode;