aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornickreid <nickreid@google.com>2023-02-18 11:03:54 -0800
committerCopybara-Service <copybara-worker@google.com>2023-02-18 11:04:28 -0800
commitc04423eb627441bfbdfb57db339440f2609b9dd5 (patch)
tree30a66ab0bab901dbe07ffca75ee5bd71480c377f
parent85f1316233777c96da04a5b166a9032e964531e9 (diff)
downloadbazelbuild-kotlin-rules-c04423eb627441bfbdfb57db339440f2609b9dd5.tar.gz
Rework the implementation of FileFactory and add tests.
PiperOrigin-RevId: 510678619 Change-Id: I04dbe628417439db19c6d695ebe9a8686e848d0a
-rw-r--r--kotlin/common.bzl2
-rw-r--r--kotlin/jvm/internal_do_not_use/util/file_factory.bzl25
-rw-r--r--tests/analysis/internal_do_not_use/util/file_factory/BUILD41
-rw-r--r--tests/analysis/internal_do_not_use/util/file_factory/check_base_file_valid.bzl38
-rw-r--r--tests/analysis/internal_do_not_use/util/file_factory/happy_test.bzl78
-rw-r--r--tests/analysis/internal_do_not_use/util/file_factory/sub/BUILD22
6 files changed, 197 insertions, 9 deletions
diff --git a/kotlin/common.bzl b/kotlin/common.bzl
index f487f0f..a4431a7 100644
--- a/kotlin/common.bzl
+++ b/kotlin/common.bzl
@@ -994,7 +994,7 @@ def _kt_jvm_import(
if not jars:
fail("Must import at least one JAR")
- file_factory = FileFactory(ctx, jars[0])
+ file_factory = FileFactory(ctx, ctx.label.name)
deps = java_common.merge(deps + kt_toolchain.kotlin_libs)
# Check that any needed deps are declared unless neverlink, in which case Jars won't be used
diff --git a/kotlin/jvm/internal_do_not_use/util/file_factory.bzl b/kotlin/jvm/internal_do_not_use/util/file_factory.bzl
index 51e18f9..2e076c3 100644
--- a/kotlin/jvm/internal_do_not_use/util/file_factory.bzl
+++ b/kotlin/jvm/internal_do_not_use/util/file_factory.bzl
@@ -16,8 +16,8 @@
load("//:visibility.bzl", "RULES_KOTLIN")
-def FileFactory(ctx, base, suffix = None):
- """Creates files with names derived from some base file
+def FileFactory(ctx, base):
+ """Creates files with names derived from some base file or prefix
Including the name of a rule is not always enough to guarantee unique filenames. For example,
helper functions that declare their own output files may be called multiple times in the same
@@ -25,26 +25,35 @@ def FileFactory(ctx, base, suffix = None):
Args:
ctx: ctx
- base: [File] The file to derive other filenames from
- suffix: [Optional[string]] An additional suffix to differentiate declared files
+ base: [File|string] The file to derive other filenames from, or an exact base prefix
Returns:
FileFactory
"""
- base_name = base.basename.rsplit(".", 1)[0] + (suffix or "")
+ if type(base) == "File":
+ base = _scrub_base_file(ctx, base)
def declare_directory(suffix):
- return ctx.actions.declare_directory(base_name + suffix, sibling = base)
+ return ctx.actions.declare_directory(base + suffix)
def declare_file(suffix):
- return ctx.actions.declare_file(base_name + suffix, sibling = base)
+ return ctx.actions.declare_file(base + suffix)
def derive(suffix):
- return FileFactory(ctx, base, suffix)
+ return FileFactory(ctx, base + suffix)
return struct(
+ base_as_path = ctx.bin_dir.path + "/" + ctx.label.package + "/" + base,
declare_directory = declare_directory,
declare_file = declare_file,
derive = derive,
)
+
+def _scrub_base_file(ctx, file):
+ if not file.extension:
+ fail("Base file must have an extension: was %s" % (file.path))
+ if file.owner.package != ctx.label.package:
+ fail("Base file must be from ctx package: was %s expected %s" % (file.owner.package, ctx.label.package))
+
+ return file.short_path.removeprefix(ctx.label.package + "/").rsplit(".", 1)[0]
diff --git a/tests/analysis/internal_do_not_use/util/file_factory/BUILD b/tests/analysis/internal_do_not_use/util/file_factory/BUILD
new file mode 100644
index 0000000..d92e379
--- /dev/null
+++ b/tests/analysis/internal_do_not_use/util/file_factory/BUILD
@@ -0,0 +1,41 @@
+# Copyright 2022 Google LLC. 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.
+
+load(":happy_test.bzl", "file_factory_happy_test")
+load(":check_base_file_valid.bzl", "check_base_file_valid")
+load("//tests/analysis:assert_failure_test.bzl", "assert_failure_test")
+
+licenses(["notice"])
+
+file_factory_happy_test(
+ name = "happy_test",
+)
+
+assert_failure_test(
+ name = "base_without_extension_test",
+ msg_contains = "file must have an extension",
+ target_under_test = check_base_file_valid(
+ name = "base_without_extension",
+ base_file = "BUILD",
+ ),
+)
+
+assert_failure_test(
+ name = "base_from_other_package_test",
+ msg_contains = "file must be from ctx package",
+ target_under_test = check_base_file_valid(
+ name = "base_from_other_package",
+ base_file = "//tests/analysis/internal_do_not_use/util/file_factory/sub",
+ ),
+)
diff --git a/tests/analysis/internal_do_not_use/util/file_factory/check_base_file_valid.bzl b/tests/analysis/internal_do_not_use/util/file_factory/check_base_file_valid.bzl
new file mode 100644
index 0000000..9ca1f05
--- /dev/null
+++ b/tests/analysis/internal_do_not_use/util/file_factory/check_base_file_valid.bzl
@@ -0,0 +1,38 @@
+# Copyright 2022 Google LLC. 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.
+
+"""Happy tests for FileFactory."""
+
+load("//kotlin/jvm/internal_do_not_use/util:file_factory.bzl", "FileFactory")
+load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS")
+load("//:visibility.bzl", "RULES_KOTLIN")
+
+def _check_base_file_valid_impl(ctx):
+ FileFactory(ctx, ctx.file.base_file)
+ return []
+
+_check_base_file_valid = rule(
+ implementation = _check_base_file_valid_impl,
+ attrs = dict(
+ base_file = attr.label(allow_single_file = True, mandatory = True),
+ ),
+)
+
+def check_base_file_valid(name, tags = [], **kwargs):
+ _check_base_file_valid(
+ name = name,
+ tags = tags + ONLY_FOR_ANALYSIS_TEST_TAGS,
+ **kwargs
+ )
+ return name
diff --git a/tests/analysis/internal_do_not_use/util/file_factory/happy_test.bzl b/tests/analysis/internal_do_not_use/util/file_factory/happy_test.bzl
new file mode 100644
index 0000000..1a2a655
--- /dev/null
+++ b/tests/analysis/internal_do_not_use/util/file_factory/happy_test.bzl
@@ -0,0 +1,78 @@
+# Copyright 2022 Google LLC. 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.
+
+"""file_factory_happy_test"""
+
+load("//kotlin/jvm/internal_do_not_use/util:file_factory.bzl", "FileFactory")
+load("//:visibility.bzl", "RULES_KOTLIN")
+
+def _test_base_from_file(ctx, pkg_path):
+ base_file = ctx.actions.declare_file("file/base.txt")
+ factory = FileFactory(ctx, base_file)
+
+ _assert_equals(pkg_path + "/file/base", factory.base_as_path)
+
+ return [base_file]
+
+def _test_declare(ctx, pkg_path):
+ factory = FileFactory(ctx, "string/base")
+
+ _assert_equals(pkg_path + "/string/base", factory.base_as_path)
+
+ a_file = factory.declare_file("a.txt")
+ _assert_equals(pkg_path + "/string/basea.txt", a_file.path)
+
+ b_dir = factory.declare_directory("b_dir")
+ _assert_equals(pkg_path + "/string/baseb_dir", b_dir.path)
+
+ return [a_file, b_dir]
+
+def _test_derive(ctx, pkg_path):
+ factory = FileFactory(ctx, "")
+
+ # Once
+ factory_once = factory.derive("once")
+ _assert_equals(pkg_path + "/once", factory_once.base_as_path)
+
+ # Twice
+ factory_twice = factory_once.derive("/twice")
+ _assert_equals(pkg_path + "/once/twice", factory_twice.base_as_path)
+
+def _assert_equals(expected, actual):
+ if expected != actual:
+ fail("Expected '%s' but was '%s'" % (expected, actual))
+
+def _file_factory_happy_test_impl(ctx):
+ pkg_path = ctx.bin_dir.path + "/" + ctx.label.package
+ all_files = []
+
+ all_files.extend(_test_base_from_file(ctx, pkg_path))
+ all_files.extend(_test_declare(ctx, pkg_path))
+ _test_derive(ctx, pkg_path)
+
+ ctx.actions.run_shell(
+ outputs = all_files,
+ command = "exit 1",
+ )
+
+ test_script = ctx.actions.declare_file(ctx.label.name + "_test.sh")
+ ctx.actions.write(test_script, "#!/bin/bash", True)
+ return [
+ DefaultInfo(executable = test_script),
+ ]
+
+file_factory_happy_test = rule(
+ implementation = _file_factory_happy_test_impl,
+ test = True,
+)
diff --git a/tests/analysis/internal_do_not_use/util/file_factory/sub/BUILD b/tests/analysis/internal_do_not_use/util/file_factory/sub/BUILD
new file mode 100644
index 0000000..db873cf
--- /dev/null
+++ b/tests/analysis/internal_do_not_use/util/file_factory/sub/BUILD
@@ -0,0 +1,22 @@
+# Copyright 2022 Google LLC. 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.
+
+licenses(["notice"])
+
+genrule(
+ name = "sub",
+ outs = ["sub.txt"],
+ cmd = "touch $(OUTS)",
+ visibility = ["//tests/analysis/internal_do_not_use/util/file_factory:__pkg__"],
+)