Skip to content

Commit

Permalink
Add proto_common.direct_source_infos
Browse files Browse the repository at this point in the history
This change adds a helper to extract information about direct sources
of `ProtoInfo` providers.

Design doc:
https://docs.google.com/document/d/1u95vlQ1lWeQNR4bUw5T4cMeHTGJla2_e1dHHx7v4Dvg/edit#

Note that this was originally named `proto_common.protos_to_generate`,
but was renamed because it applies more broadly.
  • Loading branch information
Yannic committed Dec 21, 2019
1 parent 2c04683 commit e89dc51
Show file tree
Hide file tree
Showing 12 changed files with 454 additions and 2 deletions.
10 changes: 10 additions & 0 deletions .bazelci/presubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,29 @@ platforms:
macos:
build_targets:
- "..."
test_targets:
- "//..."

rbe_ubuntu1604:
build_targets:
- "..."
test_targets:
- "//..."

ubuntu1604:
build_targets:
- "..."
test_targets:
- "//..."

ubuntu1804:
build_targets:
- "..."
test_targets:
- "//..."

windows:
build_targets:
- "..."
test_targets:
- "//..."
4 changes: 4 additions & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ rules_proto_dependencies()

rules_proto_toolchains()

load("@bazel_skylib//lib:unittest.bzl", "register_unittest_toolchains")

register_unittest_toolchains()

http_archive(
name = "bazel_toolchains",
sha256 = "1e16833a9f0e32b292568c0dfee7bd48133c2038605757d3a430551394310006",
Expand Down
13 changes: 11 additions & 2 deletions proto/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@

"""Starlark rules for building protocol buffers."""

load("//proto/private:native.bzl", "NativeProtoInfo", "native_proto_common")
load("//proto/private:native.bzl", "NativeProtoInfo")
load(
"//proto/private/utils:direct_source_infos.bzl",
"direct_source_infos",
_ProtoFileInfo = "ProtoFileInfo",
)

_MIGRATION_TAG = "__PROTO_RULES_MIGRATION_DO_NOT_USE_WILL_BREAK__"

Expand Down Expand Up @@ -54,7 +59,11 @@ def proto_library(**attrs):
# https://docs.bazel.build/versions/master/skylark/lib/ProtoInfo.html
ProtoInfo = NativeProtoInfo

ProtoFileInfo = _ProtoFileInfo

# Utilities for protocol buffers.
#
# https://docs.bazel.build/versions/master/skylark/lib/proto_common.html
proto_common = native_proto_common
proto_common = struct(
direct_source_infos = direct_source_infos,
)
1 change: 1 addition & 0 deletions proto/private/utils/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Intentionally left empty (for now).
69 changes: 69 additions & 0 deletions proto/private/utils/direct_source_infos.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Copyright 2019 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Contains the implementation for `proto_common.direct_source_infos`."""

ProtoFileInfo = provider(
doc = "Encapsulates information about a single `.proto` file.",
fields = {
"file": "The source file.",
"import_path": "The import path of the `.proto` file.",
},
)

def direct_source_infos(proto_info, provided_sources = []):
"""Returns sequence of `ProtoFileInfo` for `proto_info`'s direct sources.
Files that are both in `proto_info`'s direct sources and in
`provided_sources` are skipped. This is useful, e.g., for well-known
protos that are already provided by the Protobuf runtime.
Args:
proto_info: An instance of `ProtoInfo`.
provided_sources: Optional. A sequence of files to ignore.
Returns: A sequence of `ProtoFileInfo` containing information about
`proto_info`'s direct sources.
"""

srcs = proto_info.direct_sources
return [_info(f, proto_info) for f in srcs if f not in provided_sources]

def _info(file, proto_info):
"""Computes `ProtoFileInfo` for a single file.
Args:
file: The proto file to generate `ProtoFileInfo` for. Must be in
`direct_sources` of `proto_info`.
proto_info: An instance of `ProtoInfo`.
Returns: An instance of `ProtoFileInfo`.
"""

if "." == proto_info.proto_source_root:
# The `proto_library` didn't specify `import_prefix` or
# `strip_import_prefix`, and `file` is a regular source file
# (i.e. not generated) in the main workspace.

return ProtoFileInfo(
file = file,
import_path = file.path,
)

source_root = proto_info.proto_source_root
offset = len(source_root) + 1 # + '/'.
return ProtoFileInfo(
file = file,
import_path = file.path[offset:],
)
107 changes: 107 additions & 0 deletions tests/BUILD
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,8 +1,115 @@
load("//proto:defs.bzl", "proto_library")

WORKSPACE_PREFIX = "" # copybara-workspace-prefix(WORKSPACE_PREFIX)

proto_library(
name = "multiple_srcs_proto",
srcs = [
"empty.proto",
"prefix/empty.proto",
],
visibility = [
"//tests:__subpackages__",
],
)

proto_library(
name = "empty_proto",
srcs = [
"empty.proto",
],
visibility = [
"//tests:__subpackages__",
],
)

proto_library(
name = "empty_with_prefix_proto",
srcs = [
"prefix/empty.proto",
],
visibility = [
"//tests:__subpackages__",
],
)

proto_library(
name = "empty_with_absolute_strip_prefix_proto",
srcs = [
"empty.proto",
],
strip_import_prefix = "/" + WORKSPACE_PREFIX + "tests",
visibility = [
"//tests:__subpackages__",
],
)

proto_library(
name = "empty_with_relative_strip_prefix_proto",
srcs = [
"prefix/empty.proto",
],
strip_import_prefix = "prefix",
visibility = [
"//tests:__subpackages__",
],
)

proto_library(
name = "empty_with_empty_strip_prefix_proto",
srcs = [
"empty.proto",
],
strip_import_prefix = "",
visibility = [
"//tests:__subpackages__",
],
)

proto_library(
name = "empty_with_add_and_absolute_strip_prefix_proto",
srcs = [
"empty.proto",
],
import_prefix = "foo",
strip_import_prefix = "/" + WORKSPACE_PREFIX + "/tests",
visibility = [
"//tests:__subpackages__",
],
)

proto_library(
name = "empty_with_add_and_relative_strip_prefix_proto",
srcs = [
"prefix/empty.proto",
],
import_prefix = "foo",
strip_import_prefix = "prefix",
visibility = [
"//tests:__subpackages__",
],
)

proto_library(
name = "empty_with_add_and_empty_strip_prefix_proto",
srcs = [
"empty.proto",
],
import_prefix = "foo",
strip_import_prefix = "",
visibility = [
"//tests:__subpackages__",
],
)

proto_library(
name = "empty_with_add_and_empty_strip_prefix_proto_in_subdir",
srcs = [
"prefix/empty.proto",
],
import_prefix = "foo",
strip_import_prefix = "",
visibility = [
"//tests:__subpackages__",
],
)
5 changes: 5 additions & 0 deletions tests/analysis/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
load("//tests/analysis:proto_common_contains_native_fields_test.bzl", "proto_common_contains_native_fields_test")

proto_common_contains_native_fields_test(
name = "proto_common_contains_native_fields_test",
)
45 changes: 45 additions & 0 deletions tests/analysis/proto_common_contains_native_fields_test.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Copyright 2019 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Unit-test to verify that the Starlark `proto_common` shim contains all fields
of the native version of `proto_common`, excluding fields that are considered
to be an implementation detail (thus not part of the public API).
"""

load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest")
load("//proto:defs.bzl", "proto_common")
load("//proto/private:native.bzl", "native_proto_common") # buildifier: disable=bzl-visibility

def _impl(ctx):
"""Verifies that the Starlark `proto_common` contains all necessary fields.
Args:
ctx: The rule context.
Returns: A (not further specified) sequence of providers.
"""

env = unittest.begin(ctx)

for field in dir(native_proto_common):
# Starlark `proto_common` only exports fields that are part of the
# stable and supported API of native `proto_common`.
if not field.endswith("_do_not_use_or_we_will_break_you_without_mercy"):
asserts.true(env, hasattr(proto_common, field))
else:
asserts.false(env, hasattr(proto_common, field))

return unittest.end(env)

proto_common_contains_native_fields_test = unittest.make(_impl)
Empty file modified tests/empty.proto
100644 → 100755
Empty file.
17 changes: 17 additions & 0 deletions tests/prefix/empty.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2019 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package rules_proto.tests.prefix;
Loading

0 comments on commit e89dc51

Please sign in to comment.