aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRomain Jobredeaux <jobredeaux@google.com>2022-09-08 10:07:11 -0400
committerRomain Jobredeaux <jobredeaux@google.com>2022-09-08 13:27:56 -0400
commitbf11c5015e45147f77e0bfac4f3fbb00cf4df640 (patch)
treeb91320c4efbc40d509071afe32f324436068dd92
parentca807f220265d0063f234e8251ffca5e1c6cae00 (diff)
parentaebca278376b63c9c07296c9aa052845e0c1fe2a (diff)
downloadbazelbuild-kotlin-rules-main-16k.tar.gz
Initial merge of kotlin rules remote-tracking branch 'aosp/upstream-main'.main-16k
Change-Id: I00d5acb3726073c05cdd79f5d7adb19ae868d610 Test: added manual target to CI Bug: 186462641
-rw-r--r--.bazeliskrc15
-rw-r--r--AUTHORS23
-rw-r--r--BUILD24
-rw-r--r--CONTRIBUTING.md55
-rw-r--r--CONTRIBUTORS31
-rw-r--r--LICENSE202
-rw-r--r--METADATA18
-rw-r--r--MODULE_LICENSE_APACHE20
-rw-r--r--OWNERS2
-rw-r--r--README.md21
-rw-r--r--WORKSPACE108
-rw-r--r--bazel/BUILD42
-rw-r--r--bazel/clang_llvm_darwin_macos.BUILD19
-rw-r--r--bazel/clang_llvm_linux_x86_64.BUILD31
-rw-r--r--bazel/dagger.BUILD17
-rw-r--r--bazel/gcc_toolchain_linux_x86_64.BUILD45
-rw-r--r--bazel/kotlin_native_linux_x86_64.BUILD35
-rw-r--r--bazel/kotlin_native_macos.BUILD35
-rw-r--r--bazel/kotlinc.BUILD83
-rw-r--r--bazel/stubs.bzl34
-rw-r--r--kokoro/presubmit.cfg32
-rwxr-xr-xkokoro/presubmit.sh54
-rw-r--r--kotlin/BUILD15
-rw-r--r--kotlin/common.bzl1169
-rw-r--r--kotlin/compiler_opt.bzl83
-rw-r--r--kotlin/compiler_plugin.bzl82
-rw-r--r--kotlin/compiler_plugin_export.bzl62
-rw-r--r--kotlin/direct_jdeps.bzl26
-rw-r--r--kotlin/forbidden_deps.bzl65
-rw-r--r--kotlin/friend_jars.bzl66
-rw-r--r--kotlin/java_plugin.internal.bzl36
-rw-r--r--kotlin/jvm_compile.bzl207
-rw-r--r--kotlin/jvm_import.bzl164
-rw-r--r--kotlin/jvm_library.bzl126
-rw-r--r--kotlin/jvm_library.internal.bzl253
-rw-r--r--kotlin/jvm_test.bzl85
-rw-r--r--kotlin/rules.bzl25
-rw-r--r--kotlin/traverse_exports.bzl121
-rw-r--r--tests/BUILD13
-rw-r--r--tests/analysis/BUILD27
-rw-r--r--tests/analysis/assert_failure_test.bzl30
-rw-r--r--tests/analysis/compiler_plugin/BUILD23
-rw-r--r--tests/analysis/compiler_plugin/forbidden_target/BUILD19
-rw-r--r--tests/analysis/compiler_plugin/propagation/BUILD79
-rw-r--r--tests/analysis/compiler_plugin/propagation/assert_propagation_test.bzl56
-rw-r--r--tests/analysis/compiler_plugin/provider_ctor/BUILD19
-rw-r--r--tests/analysis/compiler_plugin/provider_ctor/fake_compiler_plugin.bzl37
-rw-r--r--tests/analysis/compiler_plugin/provider_output/BUILD58
-rw-r--r--tests/analysis/compiler_plugin/provider_output/assert_compiler_plugin_test.bzl37
-rw-r--r--tests/analysis/jvm_compile_test.bzl390
-rw-r--r--tests/analysis/jvm_import_test.bzl168
-rw-r--r--tests/analysis/jvm_library/friends/BUILD105
-rw-r--r--tests/analysis/jvm_library/friends/Input.java19
-rw-r--r--tests/analysis/jvm_library/friends/Input.kt17
-rw-r--r--tests/analysis/jvm_library/friends/sub/BUILD60
-rw-r--r--tests/analysis/jvm_library/friends/sub/Input.kt17
-rw-r--r--tests/analysis/jvm_library_test.bzl838
-rw-r--r--tests/analysis/testinputs/Bar.java21
-rw-r--r--tests/analysis/testinputs/CommonSrcs.kt19
-rw-r--r--tests/analysis/testinputs/Data.java21
-rw-r--r--tests/analysis/testinputs/Deps.java21
-rw-r--r--tests/analysis/testinputs/Foo.java21
-rw-r--r--tests/analysis/testinputs/Resources.java21
-rw-r--r--tests/analysis/testinputs/RuntimeDeps.java21
-rw-r--r--tests/analysis/testinputs/Srcs.kt19
-rw-r--r--tests/analysis/util.bzl97
-rw-r--r--tests/jvm/java/beer/BUILD45
-rw-r--r--tests/jvm/java/beer/Beer.kt186
-rwxr-xr-xtests/jvm/java/beer/build_data_test.sh25
-rw-r--r--tests/jvm/java/functions/BUILD96
-rw-r--r--tests/jvm/java/functions/CarDemo.kt33
-rw-r--r--tests/jvm/java/functions/CarInlineDemo.kt38
-rw-r--r--tests/jvm/java/functions/car/BUILD65
-rw-r--r--tests/jvm/java/functions/car/Car.kt23
-rw-r--r--tests/jvm/java/functions/car/CarExtraUtils.kt19
-rw-r--r--tests/jvm/java/functions/car/CarInlineUtils.kt19
-rw-r--r--tests/jvm/java/functions/car/CarUtils.kt22
-rw-r--r--tests/jvm/java/ijar/BUILD120
-rw-r--r--tests/jvm/java/ijar/DoubleInline.kt35
-rw-r--r--tests/jvm/java/ijar/InlineCapture.kt27
-rw-r--r--tests/jvm/java/ijar/InlineInnerClass.kt35
-rw-r--r--tests/jvm/java/ijar/InlineWhenMapping.kt21
-rw-r--r--tests/jvm/java/ijar/InlineWhenMappingUser.kt21
-rw-r--r--tests/jvm/java/ijar/JvmStatics.kt29
-rw-r--r--tests/jvm/java/ijar/Main.kt25
-rw-r--r--tests/jvm/java/ijar/ReifiedInline.kt21
-rw-r--r--tests/jvm/java/ijar/SamExt.kt20
-rw-r--r--tests/jvm/java/ijar/SamExtUser.kt21
-rw-r--r--tests/jvm/java/ijar/SamInJava.java35
-rw-r--r--tests/jvm/java/ijar/SuspendTest.kt46
-rw-r--r--tests/jvm/java/internal/BUILD49
-rw-r--r--tests/jvm/java/internal/Internal.kt25
-rw-r--r--tests/jvm/java/internal/InternalTest.kt42
-rw-r--r--tests/jvm/java/jni/BUILD92
-rw-r--r--tests/jvm/java/jni/NativeApi.java27
-rw-r--r--tests/jvm/java/jni/NativeApi.kt24
-rw-r--r--tests/jvm/java/jni/NativeApiTest.kt31
-rwxr-xr-xtests/jvm/java/jni/jdk_check.sh20
-rw-r--r--tests/jvm/java/jni/jni_NativeApi.cc26
-rw-r--r--tests/jvm/java/jni/jni_NativeApi.h35
-rw-r--r--tests/jvm/java/junit/BUILD59
-rw-r--r--tests/jvm/java/junit/BarTest.kt31
-rw-r--r--tests/jvm/java/junit/FooTest.kt31
-rw-r--r--tests/jvm/java/junit/SampleTest.kt35
-rw-r--r--tests/jvm/java/kapt/AP.java75
-rw-r--r--tests/jvm/java/kapt/APTest.kt60
-rw-r--r--tests/jvm/java/kapt/BUILD313
-rw-r--r--tests/jvm/java/kapt/Count.java23
-rw-r--r--tests/jvm/java/kapt/DaggerA.kt32
-rw-r--r--tests/jvm/java/kapt/DaggerB.kt21
-rw-r--r--tests/jvm/java/kapt/DaggerC.kt22
-rw-r--r--tests/jvm/java/kapt/DaggerTopLevel.kt23
-rw-r--r--tests/jvm/java/kapt/FailingProcessor.java49
-rw-r--r--tests/jvm/java/kapt/FlagTest.kt22
-rw-r--r--tests/jvm/java/kapt/GeneratesServices.kt28
-rw-r--r--tests/jvm/java/kapt/GeneratesServicesTest.kt35
-rw-r--r--tests/jvm/java/kapt/InnerEnumImport.kt36
-rw-r--r--tests/jvm/java/kapt/InterfaceWithDefaultImpls.kt25
-rw-r--r--tests/jvm/java/kapt/KTest.kt21
-rw-r--r--tests/jvm/java/kapt/MakeHelper.kt22
-rw-r--r--tests/jvm/java/kapt/MakeHelperClass.java.template20
-rw-r--r--tests/jvm/java/kapt/NonServiceProcessor.java45
-rw-r--r--tests/jvm/java/kapt/Noop.kt20
-rw-r--r--tests/jvm/java/kapt/ProcessorWithData.kt65
-rw-r--r--tests/jvm/java/kapt/SealedClasses.kt21
-rw-r--r--tests/jvm/java/kapt/StaticImport.kt25
-rw-r--r--tests/jvm/java/kapt/StaticMethod.java32
-rw-r--r--tests/jvm/java/kapt/Test.java22
-rw-r--r--tests/jvm/java/kapt/TriggerHelper.kt24
-rw-r--r--tests/jvm/java/metasyntactic/BUILD60
-rw-r--r--tests/jvm/java/metasyntactic/Bar.kt21
-rw-r--r--tests/jvm/java/metasyntactic/BazQux.kt23
-rw-r--r--tests/jvm/java/metasyntactic/Corge.java25
-rw-r--r--tests/jvm/java/metasyntactic/FooBar.java29
-rw-r--r--tests/jvm/java/metasyntactic/Main.kt23
-rw-r--r--tests/jvm/java/metasyntactic/QuuxCorge.kt23
-rw-r--r--tests/jvm/java/metasyntactic/QuuxCorgeGrault.java29
-rw-r--r--tests/jvm/java/metasyntactic/Qux.java25
-rw-r--r--tests/jvm/java/metasyntactic/Qux.kt21
-rw-r--r--tests/jvm/java/mockito/BUILD29
-rw-r--r--tests/jvm/java/mockito/MockitoTest.kt39
-rw-r--r--tests/jvm/java/multijarimport/A.kt20
-rw-r--r--tests/jvm/java/multijarimport/B.kt22
-rw-r--r--tests/jvm/java/multijarimport/BUILD65
-rw-r--r--tests/jvm/java/multijarimport/TestRunner.kt30
-rw-r--r--tests/jvm/java/srcartifacts/BUILD118
-rw-r--r--tests/jvm/java/srcartifacts/JavaInJavaDir.java31
-rw-r--r--tests/jvm/java/srcartifacts/JavaSrc.java31
-rw-r--r--tests/jvm/java/srcartifacts/JavaSrcjar.java31
-rw-r--r--tests/jvm/java/srcartifacts/KtInKotlinDir.kt29
-rw-r--r--tests/jvm/java/srcartifacts/KtSrc.kt29
-rw-r--r--tests/jvm/java/srcartifacts/SrcArtifactsTest.kt58
-rw-r--r--toolchains/kotlin_jvm/BUILD50
-rw-r--r--toolchains/kotlin_jvm/java_toolchains.bzl28
-rw-r--r--toolchains/kotlin_jvm/kt_jvm_toolchains.bzl257
-rw-r--r--tools/BUILD27
-rw-r--r--tools/coverage/BUILD27
-rwxr-xr-xtools/coverage/bazel_jar_instrumenter.sh42
158 files changed, 9661 insertions, 0 deletions
diff --git a/.bazeliskrc b/.bazeliskrc
new file mode 100644
index 0000000..1797a0f
--- /dev/null
+++ b/.bazeliskrc
@@ -0,0 +1,15 @@
+# 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.
+
+USE_BAZEL_VERSION=5.1.0
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..f4b7da6
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,23 @@
+# 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.
+
+# This the official list of authors for copyright purposes.
+# This file is distinct from the CONTRIBUTORS files.
+# See the latter for an explanation.
+
+# Names should be added to this file as:
+# Name or Organization <email address>
+# The email address is not required for organizations.
+
+Google LLC
diff --git a/BUILD b/BUILD
new file mode 100644
index 0000000..c72ec85
--- /dev/null
+++ b/BUILD
@@ -0,0 +1,24 @@
+# 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"])
+
+exports_files(["LICENSE"])
+
+package_group(
+ name = "internal",
+ packages = [
+ "//...",
+ ],
+)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..8557c96
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,55 @@
+<!--
+ 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.
+-->
+
+Want to contribute? Great! First, read this page (including the small print at
+the end).
+
+### Before you contribute
+**Before we can use your code, you must sign the
+[Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual?csw=1)
+(CLA)**, which you can do online.
+
+The CLA is necessary mainly because you own the copyright to your changes,
+even after your contribution becomes part of our codebase, so we need your
+permission to use and distribute your code. We also need to be sure of
+various other things — for instance that you'll tell us if you know that
+your code infringes on other people's patents. You don't have to sign
+the CLA until after you've submitted your code for review and a member has
+approved it, but you must do it before we can put your code into our codebase.
+
+### The small print
+Contributions made by corporations are covered by a different agreement than
+the one above, the
+[Software Grant and Corporate Contributor License Agreement](https://cla.developers.google.com/about/google-corporate).
+
+### Contribution process
+
+1. Explain your idea and discuss your plan with members of the team. The best
+ way to do this is to create
+ an [issue](https://github.com/bazelbuild/rules_kotlin/issues) or comment on
+ an existing issue.
+1. Prepare a git commit with your change. Don't forget to
+ add [tests](https://github.com/bazelbuild/rules_kotlin/tree/main/tests).
+ Run the existing tests with `bazel test //...`. Update
+ [README.md](https://github.com/bazelbuild/rules_kotlin/blob/main/README.md)
+ 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.**
+1. You may be asked to make some changes. You'll also need to sign the CLA at
+ this point, if you haven't done so already. Our continuous integration bots
+ will test your change automatically on supported platforms. Once everything
+ looks good, your change will be merged.
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
new file mode 100644
index 0000000..de2c925
--- /dev/null
+++ b/CONTRIBUTORS
@@ -0,0 +1,31 @@
+# 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.
+
+# People who have agreed to one of the CLAs and can contribute patches.
+# The AUTHORS file lists the copyright holders; this file
+# lists people. For example, Google employees are listed here
+# but not in AUTHORS, because Google holds the copyright.
+#
+# https://developers.google.com/open-source/cla/individual
+# https://developers.google.com/open-source/cla/corporate
+#
+# Names should be added to this file as:
+# Name <email address>
+Beth Cutler <bcutler@google.com>
+Daniel Whang <djwhang@google.com>
+Kevin Bierhoff <kmb@google.com>
+Stefan Ramsauer <str@google.com>
+Tim Peut <timpeut@google.com>
+Thomas Knych <thomaswk@google.com>
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..5d59256
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,18 @@
+name: "bazelbuild-kotlin-rules"
+description:
+ "A repository of [Bazel](https://bazel.build) starlark rules and tooling "
+ "for Kotlin. "
+ " "
+ "These rules are maintained and published by Google as-is, with limited to "
+ "no support available at the moment."
+
+third_party {
+ url {
+ type: GIT
+ value: "https://team.googlesource.com/kotlin-rules/rules"
+ }
+ version: "aebca278376b63c9c07296c9aa052845e0c1fe2a"
+ last_upgrade_date { year: 2022 month: 9 day: 7 }
+ license_type: NOTICE
+}
+
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_APACHE2
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..5bb7176
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,2 @@
+include platform/build/bazel:/OWNERS
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1310a62
--- /dev/null
+++ b/README.md
@@ -0,0 +1,21 @@
+<!--
+ 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.
+-->
+
+A repository of [Bazel](https://bazel.build) starlark rules and tooling for
+Kotlin.
+
+These rules are maintained and published by Google as-is, with limited to no
+support available at the moment. \ No newline at end of file
diff --git a/WORKSPACE b/WORKSPACE
new file mode 100644
index 0000000..12281f1
--- /dev/null
+++ b/WORKSPACE
@@ -0,0 +1,108 @@
+# 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.
+
+workspace(name = "rules_kotlin")
+
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+http_archive(
+ name = "rules_jvm_external",
+ strip_prefix = "rules_jvm_external-4.2",
+ sha256 = "cd1a77b7b02e8e008439ca76fd34f5b07aecb8c752961f9640dea15e9e5ba1ca",
+ url = "https://github.com/bazelbuild/rules_jvm_external/archive/4.2.zip",
+)
+load("@rules_jvm_external//:repositories.bzl", "rules_jvm_external_deps")
+rules_jvm_external_deps()
+load("@rules_jvm_external//:setup.bzl", "rules_jvm_external_setup")
+rules_jvm_external_setup()
+load("@rules_jvm_external//:defs.bzl", "maven_install")
+
+http_archive(
+ name = "bazel_skylib",
+ sha256 = "f7be3474d42aae265405a592bb7da8e171919d74c16f082a5457840f06054728",
+ urls = [
+ "https://github.com/bazelbuild/bazel-skylib/releases/download/1.2.1/bazel-skylib-1.2.1.tar.gz",
+ ],
+)
+load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
+bazel_skylib_workspace()
+
+http_archive(
+ name = "bazel_platforms",
+ sha256 = "379113459b0feaf6bfbb584a91874c065078aa673222846ac765f86661c27407",
+ urls = [
+ "https://github.com/bazelbuild/platforms/releases/download/0.0.5/platforms-0.0.5.tar.gz",
+ ],
+)
+
+http_archive(
+ name = "rules_java",
+ urls = [
+ "https://mirror.bazel.build/github.com/bazelbuild/rules_java/releases/download/5.0.0/rules_java-5.0.0.tar.gz",
+ "https://github.com/bazelbuild/rules_java/releases/download/5.0.0/rules_java-5.0.0.tar.gz",
+ ],
+ sha256 = "8c376f1e4ab7d7d8b1880e4ef8fc170862be91b7c683af97ca2768df546bb073",
+)
+load("@rules_java//java:repositories.bzl", "java_tools_repos")
+java_tools_repos()
+
+http_archive(
+ name = "dagger",
+ strip_prefix = "dagger-dagger-2.28.1",
+ build_file = "@//bazel:dagger.BUILD",
+ sha256 = "9e69ab2f9a47e0f74e71fe49098bea908c528aa02fa0c5995334447b310d0cdd",
+ urls = ["https://github.com/google/dagger/archive/dagger-2.28.1.zip"],
+)
+load("@dagger//:workspace_defs.bzl", "DAGGER_ARTIFACTS", "DAGGER_REPOSITORIES")
+
+load("@//toolchains/kotlin_jvm:kt_jvm_toolchains.bzl", "KT_VERSION")
+http_archive(
+ name = "kotlinc",
+ build_file = "@//bazel:kotlinc.BUILD",
+ sha256 = "7683f5451ef308eb773a686ee7779a76a95ed8b143c69ac247937619d7ca3a09",
+ strip_prefix = "kotlinc",
+ urls = [
+ "https://github.com/JetBrains/kotlin/releases/download/v{0}/kotlin-compiler-{0}.zip".format(KT_VERSION[1:].replace("_", ".")),
+ ],
+)
+
+register_toolchains("@//toolchains/kotlin_jvm:all")
+
+maven_install(
+ artifacts = DAGGER_ARTIFACTS + [
+ "com.google.auto.service:auto-service-annotations:1.0.1",
+ "com.google.auto.service:auto-service:1.0.1",
+ "com.google.auto.value:auto-value:1.9",
+ "com.google.testing.compile:compile-testing:0.19",
+ "com.google.truth:truth:1.1.3",
+ "javax.inject:jsr330-api:0.9",
+ "junit:junit:4.13.2",
+ "org.jacoco:org.jacoco.agent:0.8.8",
+ "org.jacoco:org.jacoco.cli:0.8.8",
+ "org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.4.2",
+ "org.mockito:mockito-core:4.5.1",
+ ],
+ repositories = DAGGER_REPOSITORIES + [
+ "https://repository.mulesoft.org/nexus/content/repositories/public",
+ ],
+ override_targets = {
+ "org.jetbrains.kotlin:annotations": "@kotlinc//:annotations",
+ "org.jetbrains.kotlin:kotlin-reflect": "@kotlinc//:kotlin_reflect",
+ "org.jetbrains.kotlin:kotlin-stdlib": "@kotlinc//:kotlin_stdlib",
+ "org.jetbrains.kotlin:kotlin-stdlib-jdk7": "@kotlinc//:kotlin_stdlib_jdk7",
+ "org.jetbrains.kotlin:kotlin-stdlib-jdk8": "@kotlinc//:kotlin_stdlib_jdk8",
+ "org.jetbrains.kotlin:kotlin-test": "@kotlinc//:kotlin_test",
+ },
+)
+
diff --git a/bazel/BUILD b/bazel/BUILD
new file mode 100644
index 0000000..e10757f
--- /dev/null
+++ b/bazel/BUILD
@@ -0,0 +1,42 @@
+# 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"]) # Apache 2.0
+
+package(default_visibility = ["//:internal"])
+
+java_library(
+ name = "auto_service",
+ exported_plugins = [":auto_service_plugin"],
+ exports = ["@maven//:com_google_auto_service_auto_service_annotations"],
+)
+
+java_plugin(
+ name = "auto_service_plugin",
+ processor_class = "com.google.auto.service.processor.AutoServiceProcessor",
+ visibility = ["//visibility:private"],
+ deps = ["@maven//:com_google_auto_service_auto_service"],
+)
+
+java_plugin(
+ name = "auto_value_plugin",
+ processor_class = "com.google.auto.value.processor.AutoValueProcessor",
+ deps = ["@maven//:com_google_auto_value_auto_value"],
+)
+
+java_binary(
+ name = "jacoco_cli",
+ main_class = "org.jacoco.cli.internal.Main",
+ runtime_deps = ["@maven//:org_jacoco_org_jacoco_cli"],
+)
diff --git a/bazel/clang_llvm_darwin_macos.BUILD b/bazel/clang_llvm_darwin_macos.BUILD
new file mode 100644
index 0000000..10a2a72
--- /dev/null
+++ b/bazel/clang_llvm_darwin_macos.BUILD
@@ -0,0 +1,19 @@
+# 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.
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+exports_files(["bin/llvm-lto"])
diff --git a/bazel/clang_llvm_linux_x86_64.BUILD b/bazel/clang_llvm_linux_x86_64.BUILD
new file mode 100644
index 0000000..588c047
--- /dev/null
+++ b/bazel/clang_llvm_linux_x86_64.BUILD
@@ -0,0 +1,31 @@
+# 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.
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+exports_files([
+ "bin/clang",
+ "bin/clang++",
+ "bin/llvm-lto",
+ "lib/libclang.so",
+])
+
+filegroup(
+ name = "libs",
+ srcs = glob([
+ "lib/*.a",
+ ]),
+)
diff --git a/bazel/dagger.BUILD b/bazel/dagger.BUILD
new file mode 100644
index 0000000..76c0738
--- /dev/null
+++ b/bazel/dagger.BUILD
@@ -0,0 +1,17 @@
+# 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("@dagger//:workspace_defs.bzl", "dagger_rules")
+
+dagger_rules()
diff --git a/bazel/gcc_toolchain_linux_x86_64.BUILD b/bazel/gcc_toolchain_linux_x86_64.BUILD
new file mode 100644
index 0000000..f1d1734
--- /dev/null
+++ b/bazel/gcc_toolchain_linux_x86_64.BUILD
@@ -0,0 +1,45 @@
+# 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.
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+filegroup(
+ name = "sysroot_crt_files",
+ srcs = [
+ "x86_64-unknown-linux-gnu/sysroot/usr/lib/crt1.o",
+ "x86_64-unknown-linux-gnu/sysroot/usr/lib/crti.o",
+ "x86_64-unknown-linux-gnu/sysroot/usr/lib/crtn.o",
+ ],
+)
+
+filegroup(
+ name = "libgcc_crt_files",
+ srcs = [
+ "lib/gcc/x86_64-unknown-linux-gnu/4.8.5/crtbegin.o",
+ "lib/gcc/x86_64-unknown-linux-gnu/4.8.5/crtend.o",
+ ],
+)
+
+filegroup(
+ name = "libs",
+ srcs = glob([
+ "lib/gcc/x86_64-unknown-linux-gnu/4.8.5/*.a",
+ "x86_64-unknown-linux-gnu/sysroot/lib/*.a",
+ "x86_64-unknown-linux-gnu/sysroot/usr/lib/*.a",
+ "x86_64-unknown-linux-gnu/sysroot/lib/*.so*",
+ "x86_64-unknown-linux-gnu/sysroot/usr/lib/*.so*",
+ ]),
+)
diff --git a/bazel/kotlin_native_linux_x86_64.BUILD b/bazel/kotlin_native_linux_x86_64.BUILD
new file mode 100644
index 0000000..1c249ac
--- /dev/null
+++ b/bazel/kotlin_native_linux_x86_64.BUILD
@@ -0,0 +1,35 @@
+# 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.
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+java_import(
+ name = "konan_import",
+ jars = glob(
+ ["konan/lib/*.jar"],
+ ),
+)
+
+filegroup(
+ name = "konan_runfiles",
+ srcs = glob(
+ [
+ "klib/common/**/*",
+ "konan/**",
+ ],
+ exclude = ["konan/lib/*.jar"],
+ ),
+)
diff --git a/bazel/kotlin_native_macos.BUILD b/bazel/kotlin_native_macos.BUILD
new file mode 100644
index 0000000..1c249ac
--- /dev/null
+++ b/bazel/kotlin_native_macos.BUILD
@@ -0,0 +1,35 @@
+# 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.
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+java_import(
+ name = "konan_import",
+ jars = glob(
+ ["konan/lib/*.jar"],
+ ),
+)
+
+filegroup(
+ name = "konan_runfiles",
+ srcs = glob(
+ [
+ "klib/common/**/*",
+ "konan/**",
+ ],
+ exclude = ["konan/lib/*.jar"],
+ ),
+)
diff --git a/bazel/kotlinc.BUILD b/bazel/kotlinc.BUILD
new file mode 100644
index 0000000..822d876
--- /dev/null
+++ b/bazel/kotlinc.BUILD
@@ -0,0 +1,83 @@
+# 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.
+
+package(default_visibility = ["//visibility:public"])
+
+java_import(
+ name = "annotations",
+ jars = ["lib/annotations-13.0.jar"],
+)
+
+java_import(
+ name = "jvm_abi_gen_plugin",
+ jars = ["lib/jvm-abi-gen.jar"],
+)
+
+java_import(
+ name = "kotlin_annotation_processing",
+ jars = ["lib/kotlin-annotation-processing.jar"],
+)
+
+sh_binary(
+ name = "kotlin_compiler",
+ srcs = ["bin/kotlinc"],
+ data = glob(["lib/**"]),
+)
+
+# java_binary(
+# name = "kotlin_compiler",
+# main_class = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler",
+# runtime_deps = [":kotlin_compiler_lib"],
+# )
+
+# java_import(
+# name = "kotlin_compiler_lib",
+# jars = ["lib/kotlin-compiler.jar"]
+# srcjar = "lib/kotlin-compiler-sources.jar",
+# )
+
+java_import(
+ name = "kotlin_reflect",
+ jars = ["lib/kotlin-reflect.jar"],
+ srcjar = "lib/kotlin-reflect-sources.jar",
+)
+
+java_import(
+ name = "kotlin_stdlib",
+ jars = ["lib/kotlin-stdlib.jar"],
+ srcjar = "lib/kotlin-stdlib-sources.jar",
+)
+
+java_import(
+ name = "kotlin_stdlib_jdk7",
+ jars = ["lib/kotlin-stdlib-jdk7.jar"],
+ srcjar = "lib/kotlin-stdlib-jdk7-sources.jar",
+)
+
+java_import(
+ name = "kotlin_stdlib_jdk8",
+ jars = ["lib/kotlin-stdlib-jdk8.jar"],
+ srcjar = "lib/kotlin-stdlib-jdk8-sources.jar",
+)
+
+java_import(
+ name = "kotlin_test",
+ jars = ["lib/kotlin-test.jar"],
+ srcjar = "lib/kotlin-test-sources.jar",
+)
+
+alias(
+ name = "kotlin_test_not_testonly",
+ actual = ":kotlin_test",
+)
diff --git a/bazel/stubs.bzl b/bazel/stubs.bzl
new file mode 100644
index 0000000..d948cc8
--- /dev/null
+++ b/bazel/stubs.bzl
@@ -0,0 +1,34 @@
+# 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.
+
+"""Stubs"""
+
+load("@bazel_skylib//lib:sets.bzl", "sets")
+
+def register_extension_info(**_kwargs):
+ pass
+
+FORBIDDEN_DEP_PACKAGES = sets.make([])
+
+EXEMPT_DEPS = sets.make([])
+
+DEFAULT_BUILTIN_PROCESSORS = [
+ "com.google.android.apps.play.store.plugins.injectionentrypoint.InjectionEntryPointProcessor",
+ "com.google.android.apps.play.store.plugins.interfaceaggregator.InterfaceAggregationProcessor",
+ "com.google.auto.factory.processor.AutoFactoryProcessor",
+ "dagger.android.processor.AndroidProcessor",
+ "dagger.internal.codegen.ComponentProcessor",
+]
+
+BASE_JVMOPTS = []
diff --git a/kokoro/presubmit.cfg b/kokoro/presubmit.cfg
new file mode 100644
index 0000000..07e57e4
--- /dev/null
+++ b/kokoro/presubmit.cfg
@@ -0,0 +1,32 @@
+# 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.
+
+# -*- protobuffer -*-
+# proto-message: BuildConfig
+
+# The version of bazel to use to test the rules_kotlin.
+# Update this as newer versions of bazel are released.
+build_params {
+ key: "bazel_version"
+ value: "5.1.0"
+}
+
+env_vars {
+ key: "bazel_version"
+ value: "$[bazel_version]"
+}
+
+gfile_resources: "/x20/teams/bazel/releases/bazel-$[bazel_version]-linux-x86_64"
+
+build_file: "presubmit/kokoro/presubmit.sh"
diff --git a/kokoro/presubmit.sh b/kokoro/presubmit.sh
new file mode 100755
index 0000000..716cb86
--- /dev/null
+++ b/kokoro/presubmit.sh
@@ -0,0 +1,54 @@
+#!/bin/bash -e
+# 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.
+
+# DO NOT SET -x. It will leak any secret credentials into logs.
+
+kokoro_scm_name="presubmit"
+workspace_root="${KOKORO_ARTIFACTS_DIR}/git/${kokoro_scm_name}"
+
+bazel="${KOKORO_GFILE_DIR}/bazel-${bazel_version}-linux-x86_64"
+chmod +x "$bazel"
+
+# Default JDK on GCP_UBUNTU is JDK8
+sudo update-java-alternatives --set java-1.11.0-openjdk-amd64
+# Bazel reads JAVA_HOME
+export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64/
+
+# Create a tmpfs in the sandbox at "/tmp/hsperfdata_$USERNAME" to avoid the
+# problems described in https://github.com/bazelbuild/bazel/issues/3236
+# Basically, the JVM creates a file at /tmp/hsperfdata_$USERNAME/$PID, but
+# processes all get a PID of 2 in the sandbox, so concurrent Java build actions
+# could crash because they're trying to modify the same file. So, tell the
+# sandbox to mount a tmpfs at /tmp/hsperfdata_$(whoami) so that each JVM gets
+# its own version of that directory.
+hsperfdata_dir="/tmp/hsperfdata_$(whoami)_rules_kotlin"
+mkdir -p "$hsperfdata_dir"
+
+cd "${workspace_root}"
+"$bazel" test \
+ --sandbox_tmpfs_path="$hsperfdata_dir" \
+ --verbose_failures \
+ --experimental_google_legacy_api \
+ //tests/...
+
+# Testing with code coverage
+"$bazel" test \
+ --sandbox_tmpfs_path="$hsperfdata_dir" \
+ --verbose_failures \
+ --experimental_google_legacy_api \
+ --collect_code_coverage=1 \
+ //tests/analysis:kt_jvm_compile_using_kt_jvm_compile_with_r_java_test \
+ //tests/analysis:kt_jvm_compile_with_r_java_as_first_dep_test \
+ //tests/analysis:kt_jvm_compile_without_srcs_and_with_exports_test \ No newline at end of file
diff --git a/kotlin/BUILD b/kotlin/BUILD
new file mode 100644
index 0000000..5cc7a19
--- /dev/null
+++ b/kotlin/BUILD
@@ -0,0 +1,15 @@
+# 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"]) # Apache 2.0
diff --git a/kotlin/common.bzl b/kotlin/common.bzl
new file mode 100644
index 0000000..3ffc660
--- /dev/null
+++ b/kotlin/common.bzl
@@ -0,0 +1,1169 @@
+# 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.
+
+"""Common Kotlin definitions."""
+
+load("@bazel_skylib//lib:sets.bzl", "sets")
+load("@bazel_skylib//lib:structs.bzl", "structs")
+load("//bazel:stubs.bzl", "BASE_JVMOPTS")
+load("//bazel:stubs.bzl", "DEFAULT_BUILTIN_PROCESSORS")
+
+# TODO: Remove the _ALLOWED_*_RULES lists to determine which rules
+# are accepted dependencies to Kotlin rules as the approach does not scale
+# because it will require a cl + release for every new rule.
+
+_ALLOWED_ANDROID_RULES = [
+ "aar_import",
+ "android_library",
+ "kt_android_library_helper",
+]
+
+_ALLOWED_JVM_RULES = [
+ "_java_grpc_library",
+ "_java_lite_grpc_library",
+ "af_internal_guice_module", # b/142743220
+ "af_internal_jbcsrc_library", # added with b/143872075
+ "af_internal_soyinfo_generator", # b/143872075
+ "java_import",
+ "java_library",
+ "java_lite_proto_library",
+ "java_mutable_proto_library",
+ "java_proto_library",
+ "java_wrap_cc", # b/152799927
+ "jvm_import",
+ "kt_grpc_library_helper",
+ "kt_jvm_library_helper",
+ "kt_jvm_import",
+ "kt_proto_library_helper",
+ "_j2kt_jvm_library_rule", # b/233055549
+]
+
+_EXT = struct(
+ KT = ".kt",
+ JAVA = ".java",
+ JAR = ".jar",
+ SRCJAR = ".srcjar",
+)
+
+_KT_FILE_TYPES = [_EXT.KT]
+
+_KT_JVM_FILE_TYPES = [
+ _EXT.JAVA,
+ _EXT.KT,
+ _EXT.SRCJAR,
+]
+
+_JAR_FILE_TYPE = [_EXT.JAR]
+
+_SRCJAR_FILE_TYPES = [_EXT.JAR, _EXT.SRCJAR]
+
+_RULE_FAMILY = struct(
+ UNKNOWN = 0,
+ JVM_LIBRARY = 1,
+ ANDROID_LIBRARY = 2,
+)
+
+def _is_dir(file, basename):
+ return file.is_directory and file.basename == basename
+
+def _is_kt_src(src):
+ """Decides if `src` Kotlin code.
+
+ Either:
+ - a Kotlin source file
+ - a tree-artifact expected to contain only Kotlin source files
+ """
+
+ return src.path.endswith(_EXT.KT) or _is_dir(src, "kotlin")
+
+# Compute module name based on target (b/139403883), similar to Swift
+def _derive_module_name(ctx):
+ label = _get_original_kt_target_label(ctx)
+ package_part = label.package.replace("/", ".") # .package has no leading '//'
+ name_part = label.name
+ if package_part:
+ return package_part + "_" + name_part
+ return name_part
+
+def _common_kapt_and_kotlinc_args(ctx, toolchain):
+ return toolchain.kotlinc_cli_flags + [
+ # Set module name so module-level metadata is preserved when merging Jars (b/139403883)
+ "-module-name",
+ _derive_module_name(ctx),
+ ]
+
+# Runs KAPT in two separate actions so annotation processors only rerun when Kotlin stubs changed.
+def _kapt(
+ ctx,
+ kt_srcs = [],
+ common_srcs = [],
+ java_srcs = [],
+ kotlincopts = [],
+ plugin_processors = [],
+ plugin_classpaths = None,
+ plugin_data = None,
+ javacopts = [],
+ toolchain = None,
+ classpath = []):
+ """Runs annotation processors, returns directory containing generated sources."""
+ if not plugin_processors: # shouldn't get here
+ fail("Kapt cannot work without processors")
+
+ # Kapt fails with "no source files" if only given Java sources (b/110473479), so skip ahead to
+ # just run turbine if there are no .kt sources.
+ stub_srcjars = []
+ if kt_srcs or common_srcs:
+ stubs_dir = ctx.actions.declare_directory(ctx.label.name + "/kapt/gen/stubs")
+ _kapt_stubs(
+ ctx,
+ stubs_dir,
+ kt_srcs,
+ common_srcs,
+ java_srcs,
+ kotlincopts,
+ plugin_processors,
+ plugin_classpaths,
+ toolchain,
+ classpath,
+ )
+
+ # Create a srcjar for the .java stubs generated by kapt,
+ # mostly to filter out non-.java stub outputs, e.g. .kapt_metadata.
+ stub_srcjars.append(_create_jar(
+ ctx,
+ toolchain.jar_tool,
+ ctx.actions.declare_file("stubs-srcjar.jar", sibling = stubs_dir),
+ [stubs_dir],
+ file_extensions = ["java"],
+ ))
+
+ output_jar = ctx.actions.declare_file(ctx.label.name + "-kapt.jar")
+ output_srcjar = ctx.actions.declare_file(ctx.label.name + "-kapt.srcjar")
+ output_manifest = ctx.actions.declare_file(ctx.label.name + "-kapt.jar_manifest_proto")
+ _run_turbine(
+ ctx,
+ toolchain,
+ plugin_processors,
+ plugin_classpaths,
+ plugin_data,
+ classpath,
+ javacopts,
+ java_srcs,
+ output_jar,
+ output_srcjar,
+ output_manifest,
+ stub_srcjars,
+ )
+
+ return struct(
+ jar = output_jar,
+ manifest = output_manifest,
+ srcjar = output_srcjar,
+ )
+
+def _kapt_stubs(
+ ctx,
+ stubs_dir,
+ kt_srcs = [],
+ common_srcs = [],
+ java_srcs = [],
+ kotlincopts = [],
+ plugin_processors = [],
+ plugin_classpaths = None,
+ toolchain = None,
+ classpath = []):
+ """Runs kapt3's "stubs" mode to generate .java stubs from given .kt sources."""
+
+ # Use params file to handle long classpaths (b/76185759).
+ kaptargs = ctx.actions.args()
+ kaptargs.use_param_file("@%s", use_always = True)
+ kaptargs.set_param_file_format("multiline") # avoid shell-quoting which breaks workers
+
+ kaptargs.add(toolchain.kotlin_annotation_processing, format = "-Xplugin=%s")
+ kaptargs.add("-P", "plugin:org.jetbrains.kotlin.kapt3:aptMode=stubs")
+
+ # List processor classes one by one (comma-separated list doesn't work even though documentation
+ # seems to say that it should: http://kotlinlang.org/docs/reference/kapt.html#using-in-cli)
+ kaptargs.add_all(
+ plugin_processors,
+ before_each = "-P",
+ format_each = "plugin:org.jetbrains.kotlin.kapt3:processors=%s",
+ uniquify = True, # multiple plugins can define the same processor, theoretically
+ )
+ kaptargs.add_all(
+ plugin_classpaths, # no need to uniquify depsets
+ before_each = "-P",
+ format_each = "plugin:org.jetbrains.kotlin.kapt3:apclasspath=%s",
+ )
+ kaptargs.add("-P", "plugin:org.jetbrains.kotlin.kapt3:sources=/tmp")
+ kaptargs.add("-P", "plugin:org.jetbrains.kotlin.kapt3:classes=/tmp")
+ kaptargs.add("-P", stubs_dir.path, format = "plugin:org.jetbrains.kotlin.kapt3:stubs=%s")
+ kaptargs.add("-P", "plugin:org.jetbrains.kotlin.kapt3:correctErrorTypes=true")
+
+ # kapt requires javac options to be base64-encoded,
+ # see: http://kotlinlang.org/docs/reference/kapt.html#apjavac-options-encoding
+ # The string below is the encoding of "-source 8 -target 8".
+ # TODO: use the full google3 defaults instead of hard-coding.
+ kaptargs.add("-P", "plugin:org.jetbrains.kotlin.kapt3:javacArguments=rO0ABXccAAAAAgAHLXNvdXJjZQABOAAHLXRhcmdldAABOA")
+ kaptargs.add_all(_common_kapt_and_kotlinc_args(ctx, toolchain))
+ kaptargs.add_joined("-cp", classpath, join_with = ":")
+ kaptargs.add_all(kotlincopts)
+
+ kaptargs.add_all(kt_srcs)
+ kaptargs.add_all(common_srcs)
+ if java_srcs:
+ kaptargs.add_all(java_srcs)
+
+ tool_inputs = [toolchain.kotlin_annotation_processing]
+
+ ctx.actions.run(
+ executable = toolchain.kotlin_compiler,
+ arguments = [kaptargs],
+ inputs = depset(
+ direct = (
+ kt_srcs +
+ common_srcs +
+ java_srcs +
+ tool_inputs
+ ),
+ transitive = [
+ classpath,
+ plugin_classpaths,
+ ],
+ ),
+ outputs = [stubs_dir],
+ mnemonic = "KtKaptStubs",
+ progress_message = "Kapt stubs generation: %s" % _get_original_kt_target_label(ctx),
+ execution_requirements = {
+ "worker-key-mnemonic": "Kt2JavaCompile", # share workers with Kt2JavaCompile (b/179578322)
+ },
+ )
+
+def _run_turbine(
+ ctx,
+ toolchain,
+ plugin_processors,
+ plugin_classpaths,
+ plugin_data,
+ classpath,
+ javacopts,
+ java_srcs,
+ output_jar,
+ output_srcjar,
+ output_manifest,
+ stub_srcjar = []):
+ turbineargs = ctx.actions.args()
+ turbineargs.use_param_file("@%s")
+ turbineargs.add_all("--processors", plugin_processors)
+ turbineargs.add_all("--processorpath", plugin_classpaths)
+
+ # --define=header_compiler_builtin_processors_setting=false should disable built-in processors,
+ # see: http://google3/tools/jdk/BUILD?l=338&rcl=269833772
+ enable_builtin_processors = ctx.var.get("header_compiler_builtin_processors_setting", default = "true") != "false"
+ if enable_builtin_processors:
+ turbineargs.add_all("--builtin_processors", DEFAULT_BUILTIN_PROCESSORS)
+
+ turbineargs.add_all("--javacopts", javacopts)
+ turbineargs.add("--")
+
+ turbineargs.add_all("--classpath", classpath)
+
+ turbineargs.add("--gensrc_output", output_srcjar)
+ turbineargs.add("--resource_output", output_jar)
+ turbineargs.add("--output_manifest_proto", output_manifest)
+
+ turbineargs.add_all("--source_jars", stub_srcjar)
+
+ if java_srcs:
+ turbineargs.add("--sources")
+ turbineargs.add_all(java_srcs)
+
+ outputs = [output_srcjar, output_jar, output_manifest]
+ progress_message = "Kotlin annotation processing: %s %s" % (_get_original_kt_target_label(ctx), ", ".join(plugin_processors))
+ inputs = depset(direct = java_srcs + stub_srcjar, transitive = [classpath, plugin_classpaths, plugin_data])
+
+ if enable_builtin_processors and toolchain.turbine_direct and all([p in DEFAULT_BUILTIN_PROCESSORS for p in plugin_processors]):
+ ctx.actions.run(
+ executable = toolchain.turbine_direct,
+ arguments = [turbineargs],
+ inputs = inputs,
+ outputs = outputs,
+ mnemonic = "KtKaptAptDirect",
+ progress_message = progress_message,
+ )
+ else:
+ _actions_run_deploy_jar(
+ ctx = ctx,
+ java_runtime = toolchain.java_runtime,
+ deploy_jar = toolchain.turbine,
+ deploy_jsa = toolchain.turbine_jsa,
+ inputs = inputs,
+ outputs = outputs,
+ args = [turbineargs],
+ mnemonic = "KtKaptApt",
+ progress_message = progress_message,
+ )
+
+def _derive_gen_class_jar(
+ ctx,
+ toolchain,
+ manifest_proto,
+ javac_jar,
+ java_srcs = []):
+ """Returns the annotation processor-generated classes contained in given Jar."""
+ if not manifest_proto:
+ return None
+ if not javac_jar:
+ fail("There must be a javac Jar if there was annotation processing")
+ if not java_srcs:
+ # If there weren't any hand-written .java srcs, just use Javac's output
+ return javac_jar
+
+ # Run GenClass tool to derive gen_class_jar by filtering hand-written sources.
+ # cf. Bazel's JavaCompilationHelper#createGenJarAction
+ result = ctx.actions.declare_file(ctx.label.name + "-gen.jar")
+
+ genclass_args = ctx.actions.args()
+ genclass_args.add("--manifest_proto", manifest_proto)
+ genclass_args.add("--class_jar", javac_jar)
+ genclass_args.add("--output_jar", result)
+
+ _actions_run_deploy_jar(
+ ctx = ctx,
+ java_runtime = toolchain.java_runtime,
+ deploy_jar = toolchain.genclass,
+ inputs = [manifest_proto, javac_jar],
+ outputs = [result],
+ args = [genclass_args],
+ mnemonic = "KtGenClassJar",
+ progress_message = "Deriving %{output}",
+ )
+
+ return result
+
+def _kt_plugins_map(
+ java_plugin_infos = [],
+ kt_compiler_plugin_infos = []):
+ """A struct containing all the plugin types understood by rules_kotlin.
+
+ Args:
+ java_plugin_infos: (list[JavaPluginInfo])
+ kt_compiler_plugin_infos: (list[KtCompilerPluginInfo])
+ """
+ return struct(
+ java_plugin_infos = java_plugin_infos,
+ kt_compiler_plugin_infos = kt_compiler_plugin_infos,
+ )
+
+def _run_kotlinc(
+ ctx,
+ output,
+ kt_srcs = [],
+ common_srcs = [],
+ java_srcs_and_dirs = [],
+ kotlincopts = [],
+ compile_jdeps = depset(),
+ toolchain = None,
+ classpath = [],
+ directdep_jars = depset(),
+ plugins = _kt_plugins_map(),
+ friend_jars = depset(),
+ enforce_strict_deps = False,
+ enforce_complete_jdeps = False):
+ if output.extension != "jar":
+ fail("Expect to output a Jar but got %s" % output)
+
+ direct_inputs = []
+ transitive_inputs = []
+ outputs = []
+
+ # Args to kotlinc.
+ #
+ # These go at the end of the commandline. They should be passed through all wrapper
+ # layers without post-processing, except to unpack param files.
+ kotlinc_args = ctx.actions.args()
+ kotlinc_args.use_param_file("@%s", use_always = True) # Use params file to handle long classpaths (b/76185759)
+ kotlinc_args.set_param_file_format("multiline") # kotlinc only supports double-quotes ("): https://youtrack.jetbrains.com/issue/KT-24472
+
+ kotlinc_args.add_all(_common_kapt_and_kotlinc_args(ctx, toolchain))
+ kotlinc_args.add_joined("-cp", classpath, join_with = ":")
+ transitive_inputs.append(classpath)
+ kotlinc_args.add_all(kotlincopts)
+
+ kotlinc_args.add(toolchain.jvm_abi_gen_plugin, format = "-Xplugin=%s")
+ direct_inputs.append(toolchain.jvm_abi_gen_plugin)
+ kt_ijar = ctx.actions.declare_file(output.basename[:-4] + "-ijar.jar", sibling = output)
+ kotlinc_args.add("-P", kt_ijar, format = "plugin:org.jetbrains.kotlin.jvm.abi:outputDir=%s")
+ outputs.append(kt_ijar)
+
+ for p in plugins.kt_compiler_plugin_infos:
+ kotlinc_args.add(p.jar, format = "-Xplugin=%s")
+ direct_inputs.append(p.jar)
+ kotlinc_args.add_all(p.args, before_each = "-P")
+
+ # Common sources must also be specified as -Xcommon-sources= in addition to appearing in the
+ # source list.
+ if common_srcs:
+ kotlinc_args.add("-Xmulti-platform=true")
+ kotlinc_args.add_all(common_srcs, format_each = "-Xcommon-sources=%s")
+ direct_inputs.extend(common_srcs)
+
+ kotlinc_args.add("-d", output)
+ outputs.append(output)
+ kotlinc_args.add_all(kt_srcs)
+ direct_inputs.extend(kt_srcs)
+ kotlinc_args.add_all(common_srcs)
+ direct_inputs.extend(common_srcs)
+
+ if java_srcs_and_dirs:
+ # This expands any directories into their contained files
+ kotlinc_args.add_all(java_srcs_and_dirs)
+ direct_inputs.extend(java_srcs_and_dirs)
+
+ kotlinc_args.add_joined(friend_jars, format_joined = "-Xfriend-paths=%s", join_with = ",")
+ transitive_inputs.append(friend_jars)
+
+ # Do not change the "shape" or mnemonic of this action without consulting Kythe team
+ # (kythe-eng@), to avoid breaking the Kotlin Kythe extractor which "shadows" this action. In
+ # particular, the extractor expects this to be a vanilla "spawn" (ctx.actions.run) so don't
+ # change this to ctx.actions.run_shell or something else without considering Kythe implications
+ # (b/112439843).
+ ctx.actions.run(
+ executable = toolchain.kotlin_compiler,
+ arguments = [kotlinc_args],
+ inputs = depset(direct = direct_inputs, transitive = transitive_inputs),
+ outputs = outputs,
+ mnemonic = "Kt2JavaCompile",
+ progress_message = "Compiling Kotlin For Java Runtime: %s" % _get_original_kt_target_label(ctx),
+ execution_requirements = {
+ "worker-key-mnemonic": "Kt2JavaCompile",
+ },
+ )
+
+ # TODO: Normalize paths to match package declarations in source files.
+ srcjar = _create_jar(
+ ctx,
+ toolchain.jar_tool,
+ ctx.actions.declare_file(ctx.label.name + "-kt-src.jar"),
+ kt_srcs + common_srcs,
+ )
+
+ return struct(
+ output_jar = output,
+ compile_jar = kt_ijar,
+ source_jar = srcjar,
+ )
+
+def _get_original_kt_target_label(ctx):
+ label = ctx.label
+ if label.name.find("_DO_NOT_DEPEND") > 0:
+ # Remove rule suffix added by kt_android_library
+ label = label.relative(":%s" % label.name[0:label.name.find("_DO_NOT_DEPEND")])
+
+ return label
+
+def _check_deps(
+ ctx,
+ jars_to_check = [],
+ merged_deps = None,
+ enforce_strict_deps = True,
+ jdeps_output = None,
+ deps_checker = None,
+ java_toolchain = None):
+ # Direct compile_jars before transitive not to confuse strict_deps (b/149107867)
+ full_classpath = depset(
+ order = "preorder",
+ transitive = [merged_deps.compile_jars, merged_deps.transitive_compile_time_jars],
+ )
+ label = _get_original_kt_target_label(ctx)
+ bootclasspath = java_toolchain.bootclasspath
+
+ args = ctx.actions.args()
+ args.add("--jdeps_output", jdeps_output)
+ args.add_all(jars_to_check, before_each = "--input")
+ args.add_all(bootclasspath, before_each = "--bootclasspath_entry")
+ args.add_all(full_classpath, before_each = "--classpath_entry")
+ if enforce_strict_deps:
+ args.add_all(merged_deps.compile_jars, before_each = "--directdep")
+ args.add("--checking_mode=%s" % ("error" if enforce_strict_deps else "silence"))
+ args.add("--nocheck_missing_members") # compiler was happy so no need
+ args.add("--rule_label")
+ args.add(label)
+
+ ctx.actions.run(
+ executable = deps_checker,
+ arguments = [args],
+ inputs = depset(
+ jars_to_check,
+ transitive = [bootclasspath, full_classpath],
+ ),
+ outputs = [jdeps_output],
+ mnemonic = "KtCheckStrictDeps" if enforce_strict_deps else "KtJdeps",
+ progress_message = "%s deps for %s" % (
+ "Checking strict" if enforce_strict_deps else "Computing",
+ label,
+ ),
+ )
+
+def _offline_instrument_jar(ctx, toolchain, jar, srcs = []):
+ paths_for_coverage_file = ctx.actions.declare_file(ctx.label.name + "-kt-paths-for-coverage.txt")
+ paths = ctx.actions.args()
+ paths.set_param_file_format("multiline") # don't shell-quote, just list file names
+ paths.add_all([src for src in srcs if src.is_source])
+ ctx.actions.write(paths_for_coverage_file, paths)
+
+ result = ctx.actions.declare_file(ctx.label.name + "-instrumented.jar")
+ args = ctx.actions.args()
+ args.add(jar)
+ args.add(result)
+ args.add(paths_for_coverage_file)
+ ctx.actions.run(
+ executable = toolchain.coverage_instrumenter,
+ arguments = [args],
+ inputs = [jar, paths_for_coverage_file],
+ outputs = [result],
+ mnemonic = "KtJaCoCoInstrument",
+ progress_message = "Instrumenting Kotlin for coverage collection: %s" % _get_original_kt_target_label(ctx),
+ )
+
+ return result
+
+def _singlejar(
+ ctx,
+ inputs,
+ output,
+ singlejar,
+ mnemonic = "KtMergeJar",
+ content = "final Jar",
+ preserve_compression = False,
+ pseudo_inputs = []):
+ label = _get_original_kt_target_label(ctx)
+ args = ctx.actions.args()
+ args.add("--normalize")
+ args.add("--add_missing_directories") # make output more similar to jar tool (b/114414678)
+ args.add("--exclude_build_data")
+ args.add("--no_duplicates") # No Kt/Java classname collisions (b/216841985)
+ args.add("--output")
+ args.add(output)
+ args.add("--sources")
+ args.add_all(inputs)
+ args.add("--deploy_manifest_lines")
+ args.add("Target-Label: %s" % label)
+ if preserve_compression:
+ args.add("--dont_change_compression")
+
+ ctx.actions.run(
+ executable = singlejar,
+ arguments = [args],
+ inputs = inputs + pseudo_inputs,
+ outputs = [output],
+ mnemonic = mnemonic,
+ progress_message = "Merging %s: %s" % (content, label),
+ )
+
+def _merge_jdeps(ctx, kt_jvm_toolchain, jdeps_files, output_suffix = ""):
+ merged_jdeps_file = ctx.actions.declare_file(ctx.label.name + output_suffix + ".jdeps")
+
+ args = ctx.actions.args()
+ args.add("--kind=jdeps")
+ args.add(merged_jdeps_file, format = "--output=%s")
+ args.add(_get_original_kt_target_label(ctx), format = "--rule_label=%s")
+ args.add_all(jdeps_files)
+
+ ctx.actions.run(
+ executable = kt_jvm_toolchain.jdeps_merger,
+ inputs = jdeps_files,
+ outputs = [merged_jdeps_file],
+ arguments = [args],
+ mnemonic = "KtMergeJdeps",
+ progress_message = "Merging jdeps files %{output}",
+ )
+
+ return merged_jdeps_file
+
+def _expand_zip(ctx, dir, input, extra_args = []):
+ ctx.actions.run_shell(
+ outputs = [dir],
+ inputs = [input],
+ command = "unzip -q {input} -d {dir} {args} 2> /dev/null || mkdir -p {dir}".format(
+ input = input.path,
+ dir = dir.path,
+ args = " ".join(extra_args),
+ ),
+ )
+ return dir
+
+def _create_jar(ctx, jar_tool, out_jar, inputs, file_extensions = None):
+ def file_filter(file):
+ return file.path if (
+ file_extensions == None or (file.extension in file_extensions)
+ ) else None
+
+ args = ctx.actions.args()
+ args.add("cf", out_jar)
+ args.add_all(inputs, map_each = file_filter, allow_closure = True)
+
+ ctx.actions.run(
+ executable = jar_tool,
+ inputs = inputs,
+ outputs = [out_jar],
+ arguments = [args],
+ mnemonic = "KtJar",
+ progress_message = "Create Jar (kotlin/common.bzl): %{output}",
+ )
+
+ return out_jar
+
+def _create_jar_from_tree_artifacts(ctx, jar_tool, output_jar, input_dirs):
+ """Packs a sequence of tree artifacts into a single jar.
+
+ Given the following file directory structure,
+ /usr/home/a/x/1.txt
+ /usr/home/b/y/1.txt
+ with an input_dirs as [
+ "/usr/home/a",
+ "/usr/home/b",
+ ],
+ The tool produces a jar with in-archive structure of,
+ x/1.txt
+ y/1.txt
+
+ The function fails on the duplicate jar entry case. e.g. if we pass an
+ input_dirs as [
+ "/usr/home/a/x",
+ "/usr/home/b/y",
+ ],
+ then the blaze action would fail with an error message.
+ "java.util.zip.ZipException: duplicate entry: 1.txt"
+
+ Args:
+ ctx: The build rule context.
+ jar_tool: A Unix-API-compatible jar tool.
+ output_jar: The jar to be produced by this action.
+ input_dirs: A sequence of tree artifacts to be zipped.
+
+ Returns:
+ The generated output jar, i.e. output_jar
+ """
+
+ args = ctx.actions.args()
+
+ for in_dir in input_dirs:
+ if not in_dir.is_directory:
+ fail("Expected a directory input, but got {}.".format(in_dir))
+ args.add(in_dir.path)
+
+ ctx.actions.run_shell(
+ command = """
+ JAR_TOOL={}
+ OUT_JAR={}
+ OUT_DIR="$(dirname $OUT_JAR)"
+ RES_DIR=$OUT_DIR/META-INF
+ mkdir $RES_DIR
+ $JAR_TOOL cf $OUT_JAR -C $RES_DIR .
+ rmdir $RES_DIR
+ for INPUT_DIR in $@
+ do
+ if [ -d $INPUT_DIR ]
+ then
+ $JAR_TOOL uf $OUT_JAR -C $INPUT_DIR .
+ fi
+ done
+ """.format(jar_tool.executable.path, output_jar.path),
+ arguments = [args],
+ inputs = input_dirs,
+ outputs = [output_jar],
+ tools = [jar_tool],
+ mnemonic = "KtJarActionFromTreeArtifacts",
+ progress_message = "Create Jar %{output}",
+ )
+ return output_jar
+
+def _DirSrcjarSyncer(ctx, kt_toolchain, name):
+ _dirs = []
+ _srcjars = []
+
+ def add_dirs(dirs):
+ if not dirs:
+ return
+
+ _dirs.extend(dirs)
+ _srcjars.append(
+ _create_jar_from_tree_artifacts(
+ ctx,
+ kt_toolchain.jar_tool,
+ ctx.actions.declare_file(
+ "%s/%s%s.srcjar" % (ctx.label.name, name, len(_srcjars)),
+ ),
+ dirs,
+ ),
+ )
+
+ def add_srcjars(srcjars):
+ if not srcjars:
+ return
+
+ for srcjar in srcjars:
+ _dirs.append(
+ _expand_zip(
+ ctx,
+ ctx.actions.declare_directory(
+ "%s/%s%s.expand" % (ctx.label.name, name, len(_dirs)),
+ ),
+ srcjar,
+ extra_args = ["*.java", "*.kt"],
+ ),
+ )
+ _srcjars.extend(srcjars)
+
+ return struct(
+ add_dirs = add_dirs,
+ add_srcjars = add_srcjars,
+ dirs = _dirs,
+ srcjars = _srcjars,
+ )
+
+def _actions_run_deploy_jar(
+ ctx,
+ java_runtime,
+ deploy_jar,
+ inputs,
+ args = [],
+ deploy_jsa = None,
+ **kwargs):
+ java_args = ctx.actions.args()
+ java_inputs = []
+ if deploy_jsa:
+ java_args.add("-Xshare:auto")
+ java_args.add(deploy_jsa, format = "-XX:SharedArchiveFile=%s")
+ java_args.add("-XX:-VerifySharedSpaces")
+ java_args.add("-XX:-ValidateSharedClassPaths")
+ java_inputs.append(deploy_jsa)
+ java_args.add("-jar", deploy_jar)
+ java_inputs.append(deploy_jar)
+
+ java_depset = depset(direct = java_inputs, transitive = [java_runtime[DefaultInfo].files])
+ if type(inputs) == "depset":
+ all_inputs = depset(transitive = [java_depset, inputs])
+ else:
+ all_inputs = depset(direct = inputs, transitive = [java_depset])
+
+ ctx.actions.run(
+ executable = str(java_runtime[java_common.JavaRuntimeInfo].java_executable_exec_path),
+ inputs = all_inputs,
+ arguments = BASE_JVMOPTS + [java_args] + args,
+ **kwargs
+ )
+
+def _check_srcs_package(target_package, srcs, attr_name):
+ """Makes sure the given srcs live in the given package."""
+
+ # Analogous to RuleContext.checkSrcsSamePackage
+ for src in srcs:
+ if target_package != src.owner.package:
+ fail(("Please do not depend on %s directly in %s. Either move it to this package or " +
+ "depend on an appropriate rule in its package.") % (src.owner, attr_name))
+
+# TODO: Streamline API to generate less actions.
+def _kt_jvm_library(
+ ctx,
+ kt_toolchain,
+ srcs = [],
+ common_srcs = [],
+ coverage_srcs = [],
+ manifest = None, # set for Android libs, otherwise None.
+ merged_manifest = None, # set for Android libs, otherwise None.
+ resource_files = [], # set for Android libs, otherwise empty.
+ classpath_resources = [], # set for kt_jvm_library, otherwise empty.
+ output = None,
+ output_srcjar = None, # Will derive default filename if not set.
+ deps = [],
+ exports = [], # passthrough for JavaInfo constructor
+ runtime_deps = [], # passthrough for JavaInfo constructor
+ native_libraries = [], # passthrough of CcInfo for JavaInfo constructor
+ plugins = _kt_plugins_map(),
+ pre_processed_java_plugin_processors = sets.make([]),
+ exported_plugins = [],
+ android_lint_plugins = [],
+ android_lint_rules_jars = depset(), # Depset with standalone Android Lint rules Jars
+ javacopts = [],
+ kotlincopts = [],
+ compile_jdeps = depset(),
+ disable_lint_checks = [],
+ neverlink = False,
+ testonly = False, # used by Android Lint
+ enforce_strict_deps = True,
+ rule_family = _RULE_FAMILY.UNKNOWN,
+ enforce_complete_jdeps = False,
+ java_toolchain = None,
+ friend_jars = depset(),
+ annotation_processor_additional_outputs = [],
+ annotation_processor_additional_inputs = []):
+ if not java_toolchain:
+ fail("Missing or invalid java_toolchain")
+ if not kt_toolchain:
+ fail("Missing or invalid kt_toolchain")
+
+ merged_deps = java_common.merge(deps)
+
+ # Split sources, as java requires a separate compile step.
+ kt_srcs = [s for s in srcs if _is_kt_src(s)]
+ java_srcs = [s for s in srcs if s.path.endswith(_EXT.JAVA)]
+ java_syncer = _DirSrcjarSyncer(ctx, kt_toolchain, "java")
+ java_syncer.add_dirs([s for s in srcs if _is_dir(s, "java")])
+ java_syncer.add_srcjars([s for s in srcs if s.path.endswith(_EXT.SRCJAR)])
+
+ expected_srcs = sets.make(kt_srcs + java_srcs + java_syncer.dirs + java_syncer.srcjars)
+ unexpected_srcs = sets.difference(sets.make(srcs), expected_srcs)
+ if sets.length(unexpected_srcs) != 0:
+ fail("Unexpected srcs: %s" % sets.to_list(unexpected_srcs))
+
+ # Skip srcs package check for android_library targets with no kotlin sources: b/239725424
+ if rule_family != _RULE_FAMILY.ANDROID_LIBRARY or kt_srcs:
+ _check_srcs_package(ctx.label.package, srcs, "srcs")
+ _check_srcs_package(ctx.label.package, common_srcs, "common_srcs")
+ _check_srcs_package(ctx.label.package, coverage_srcs, "coverage_srcs")
+
+ # Complete classpath including bootclasspath. Like for Javac, explicitly place direct
+ # compile_jars before transitive not to confuse strict_deps (b/149107867).
+ full_classpath = depset(
+ order = "preorder",
+ transitive = [
+ java_toolchain.bootclasspath,
+ merged_deps.compile_jars,
+ merged_deps.transitive_compile_time_jars,
+ ],
+ )
+
+ # Collect all plugin data, including processors to run and all plugin classpaths,
+ # whether they have processors or not (b/120995492).
+ # This may include go/errorprone plugin classpaths that kapt will ignore.
+ java_plugin_datas = [info.plugins for info in plugins.java_plugin_infos] + [dep.plugins for dep in deps]
+ plugin_processors = [
+ cls
+ for p in java_plugin_datas
+ for cls in p.processor_classes.to_list()
+ if not sets.contains(pre_processed_java_plugin_processors, cls)
+ ]
+ plugin_classpaths = depset(transitive = [p.processor_jars for p in java_plugin_datas])
+
+ out_jars = []
+ out_srcjars = []
+ out_compilejars = []
+ kapt_outputs = struct(jar = None, manifest = None, srcjar = None)
+
+ # Kotlin compilation requires two passes when annotation processing is
+ # required. The initial pass processes the annotations and generates
+ # additional sources and the following pass compiles the Kotlin code.
+ # Skip kapt if no plugins have processors (can happen with only
+ # go/errorprone plugins, # b/110540324)
+ if kt_srcs and plugin_processors:
+ kapt_outputs = _kapt(
+ ctx,
+ kt_srcs = kt_srcs,
+ common_srcs = common_srcs,
+ java_srcs = java_srcs,
+ plugin_processors = plugin_processors,
+ plugin_classpaths = plugin_classpaths,
+ plugin_data = depset(transitive = [p.processor_data for p in java_plugin_datas]),
+ # Put contents of Bazel flag --javacopt before given javacopts as is Java rules.
+ # This still ignores package configurations, which aren't exposed to Starlark.
+ javacopts = (java_common.default_javac_opts(java_toolchain = java_toolchain) +
+ ctx.fragments.java.default_javac_flags +
+ javacopts),
+ kotlincopts = kotlincopts, # don't need strict_deps flags for kapt
+ toolchain = kt_toolchain,
+ classpath = full_classpath,
+ )
+
+ out_jars.append(kapt_outputs.jar)
+ java_syncer.add_srcjars([kapt_outputs.srcjar])
+
+ merged_deps = java_common.merge([merged_deps, JavaInfo(
+ output_jar = kapt_outputs.jar,
+ compile_jar = kapt_outputs.jar,
+ )])
+
+ kotlinc_result = None
+ if kt_srcs or common_srcs:
+ kotlinc_result = _run_kotlinc(
+ ctx,
+ kt_srcs = kt_srcs,
+ common_srcs = common_srcs,
+ java_srcs_and_dirs = java_srcs + java_syncer.dirs,
+ output = ctx.actions.declare_file(ctx.label.name + "-kt.jar"),
+ kotlincopts = kotlincopts,
+ compile_jdeps = compile_jdeps,
+ toolchain = kt_toolchain,
+ classpath = full_classpath,
+ plugins = plugins,
+ friend_jars = friend_jars,
+ enforce_strict_deps = enforce_strict_deps,
+ enforce_complete_jdeps = enforce_complete_jdeps,
+ )
+
+ # Use un-instrumented Jar at compile-time to avoid double-instrumenting inline functions
+ # (see b/110763361 for the comparable Gradle issue)
+ out_compilejars.append(kotlinc_result.compile_jar)
+ out_srcjars.append(kotlinc_result.source_jar)
+
+ # Apply coverage instrumentation if requested, and add dep on JaCoCo runtime to merged_deps.
+ # The latter helps jdeps computation (b/130747644) but could be runtime-only if we computed
+ # compile-time Jdeps based using the compile Jar (which doesn't contain instrumentation).
+ # See b/117897097 for why it's still useful to make the (runtime) dep explicit.
+ if ctx.coverage_instrumented():
+ out_jars.append(_offline_instrument_jar(
+ ctx,
+ kt_toolchain,
+ kotlinc_result.output_jar,
+ kt_srcs + common_srcs + coverage_srcs,
+ ))
+ merged_deps = java_common.merge([merged_deps, kt_toolchain.coverage_runtime])
+ else:
+ out_jars.append(kotlinc_result.output_jar)
+
+ classpath_resources_dirs, classpath_resources_non_dirs = _partition(
+ classpath_resources,
+ filter = lambda res: res.is_directory,
+ )
+ if classpath_resources_dirs:
+ out_jars.append(
+ _create_jar_from_tree_artifacts(
+ ctx,
+ kt_toolchain.jar_tool,
+ ctx.actions.declare_file(ctx.label.name + "-dir-res.jar"),
+ classpath_resources_dirs,
+ ),
+ )
+
+ javac_java_info = None
+ java_native_headers_jar = None
+ java_gensrcjar = None
+ java_genjar = None
+ if java_srcs or java_syncer.srcjars or classpath_resources:
+ javac_out = ctx.actions.declare_file(ctx.label.name + "-java.jar")
+ javac_java_info = java_common.compile(
+ ctx,
+ source_files = java_srcs,
+ source_jars = java_syncer.srcjars,
+ resources = classpath_resources_non_dirs,
+ output = javac_out,
+ deps = ([JavaInfo(**structs.to_dict(kotlinc_result))] if kotlinc_result else []) + [merged_deps],
+ # Include default_javac_flags, which reflect Blaze's --javacopt flag, so they win over
+ # all sources of default flags (for Ellipsis builds, see b/125452475).
+ # TODO: remove default_javac_flags here once java_common.compile is fixed.
+ javac_opts = ctx.fragments.java.default_javac_flags + javacopts,
+ plugins = plugins.java_plugin_infos,
+ strict_deps = "DEFAULT",
+ java_toolchain = java_toolchain,
+ neverlink = neverlink,
+ # Enable annotation processing for java-only sources to enable data binding
+ enable_annotation_processing = not kt_srcs,
+ annotation_processor_additional_outputs = annotation_processor_additional_outputs,
+ annotation_processor_additional_inputs = annotation_processor_additional_inputs,
+ )
+ out_jars.append(javac_out)
+ out_srcjars.extend(javac_java_info.source_jars)
+ out_compilejars.extend(javac_java_info.compile_jars.to_list()) # unpack singleton depset
+ java_native_headers_jar = javac_java_info.outputs.native_headers
+
+ if kt_srcs:
+ java_gensrcjar = kapt_outputs.srcjar
+ java_genjar = _derive_gen_class_jar(ctx, kt_toolchain, kapt_outputs.manifest, javac_out, java_srcs)
+ else:
+ java_gensrcjar = javac_java_info.annotation_processing.source_jar
+ java_genjar = javac_java_info.annotation_processing.class_jar
+ if java_gensrcjar:
+ java_syncer.add_srcjars([java_gensrcjar])
+
+ jdeps_output = None
+ compile_jdeps_output = None
+ manifest_proto = None
+
+ # TODO: Move severity overrides to config file when possible again
+ blocking_action_outs = []
+
+ if output_srcjar == None:
+ output_srcjar = ctx.actions.declare_file("lib%s-src.jar" % ctx.label.name)
+ compile_jar = ctx.actions.declare_file(ctx.label.name + "-compile.jar")
+ single_jar = java_toolchain.single_jar
+ _singlejar(ctx, out_srcjars, output_srcjar, single_jar, mnemonic = "KtMergeSrcjar", content = "srcjar", preserve_compression = True)
+
+ # Don't block compile-time Jar on Android Lint and other validations (b/117991324).
+ _singlejar(ctx, out_compilejars, compile_jar, single_jar, mnemonic = "KtMergeCompileJar", content = "compile-time Jar")
+
+ # Disable validation for Guitar BUILD targets (b/144326858).
+ # TODO Remove use of RUN_ANALYSIS_TIME_VALIDATION once Guitar disables validations
+ use_validation = ctx.var.get("RUN_ANALYSIS_TIME_VALIDATION", "true") # will be "0" if set by Guitar
+ use_validation = ctx.var.get("kt_use_validations", use_validation)
+
+ # Include marker file in runtime Jar so we can reliably identify 1P Kotlin code
+ # TODO: consider only doing this for kt_android_library
+ _singlejar(
+ ctx,
+ out_jars + ([kt_toolchain.build_marker] if kt_srcs and ctx.label.package.startswith("java/") else []),
+ output,
+ single_jar,
+ preserve_compression = True,
+ pseudo_inputs = ([] if use_validation == "true" else blocking_action_outs),
+ )
+ result_java_info = JavaInfo(
+ output_jar = output,
+ compile_jar = compile_jar,
+ source_jar = output_srcjar,
+ deps = deps,
+ exports = exports,
+ exported_plugins = exported_plugins,
+ runtime_deps = runtime_deps,
+ manifest_proto = manifest_proto,
+ neverlink = neverlink,
+ jdeps = jdeps_output,
+ compile_jdeps = compile_jdeps_output,
+ native_libraries = native_libraries,
+ native_headers_jar = java_native_headers_jar,
+ generated_source_jar = java_gensrcjar,
+ generated_class_jar = java_genjar,
+ )
+
+ return struct(
+ java_info = result_java_info,
+ validations = (blocking_action_outs if use_validation == "true" else []),
+ )
+
+def _kt_jvm_import(
+ ctx,
+ jars = [],
+ srcjar = None,
+ deps = [],
+ runtime_deps = [],
+ neverlink = False,
+ java_toolchain = None,
+ deps_checker = None):
+ if not java_toolchain:
+ fail("Missing or invalid java_toolchain")
+ merged_deps = java_common.merge(deps)
+
+ # Check that any needed deps are declared unless neverlink, in which case Jars won't be used
+ # at runtime so we skip the check, though we'll populate jdeps either way.
+ jdeps_output = ctx.actions.declare_file(ctx.label.name + ".jdeps")
+ _check_deps(
+ ctx,
+ jars_to_check = jars,
+ merged_deps = merged_deps,
+ enforce_strict_deps = not neverlink,
+ jdeps_output = jdeps_output,
+ deps_checker = deps_checker,
+ java_toolchain = java_toolchain,
+ )
+
+ if not jars:
+ fail("Must provide a Jar to use kt_jvm_import")
+
+ java_info = java_common.merge([
+ JavaInfo(
+ output_jar = jar,
+ compile_jar = jar,
+ source_jar = srcjar,
+ deps = deps,
+ runtime_deps = runtime_deps,
+ neverlink = neverlink,
+ # TODO: Set compile-time jdeps to help reduce Javac classpaths downstream
+ jdeps = jdeps_output, # not clear this is useful but let's populate since we have it
+ )
+ for jar in jars
+ ])
+
+ # TODO Remove use of RUN_ANALYSIS_TIME_VALIDATION once Guitar disables validations
+ use_validation = ctx.var.get("RUN_ANALYSIS_TIME_VALIDATION", "true") # will be "0" if set by Guitar
+
+ return struct(
+ java_info = java_info,
+ validations = [jdeps_output] if use_validation == "true" and not neverlink else [],
+ )
+
+def _validate_proguard_specs(
+ ctx,
+ proguard_specs,
+ proguard_allowlister):
+ validated_proguard_specs = []
+ for proguard_spec in proguard_specs:
+ validated_proguard_spec = ctx.actions.declare_file(
+ "validated_proguard/%s/%s_valid" % (ctx.label.name, proguard_spec.path),
+ )
+ validated_proguard_specs.append(validated_proguard_spec)
+
+ args = ctx.actions.args()
+ args.add("--path", proguard_spec)
+ args.add("--output", validated_proguard_spec)
+
+ ctx.actions.run(
+ executable = proguard_allowlister,
+ arguments = [args],
+ inputs = [proguard_spec],
+ outputs = [validated_proguard_spec],
+ mnemonic = "ValidateProguard",
+ progress_message = (
+ "Validating proguard configuration %s" % proguard_spec
+ ),
+ )
+ return validated_proguard_specs
+
+def _collect_proguard_specs(
+ ctx,
+ proguard_specs,
+ propagated_deps,
+ proguard_allowlister):
+ validated_proguard_specs = _validate_proguard_specs(
+ ctx,
+ proguard_specs,
+ proguard_allowlister,
+ )
+
+ return depset(
+ validated_proguard_specs,
+ transitive = [p.specs for p in _collect_providers(ProguardSpecProvider, propagated_deps)],
+ order = "preorder",
+ )
+
+def _collect_providers(provider, deps):
+ """Collects the requested provider from the given list of deps."""
+ return [dep[provider] for dep in deps if provider in dep]
+
+def _partition(sequence, filter):
+ pos, neg = [], []
+ for element in sequence:
+ if filter(element):
+ pos.append(element)
+ else:
+ neg.append(element)
+ return pos, neg
+
+common = struct(
+ ALLOWED_ANDROID_RULES = _ALLOWED_ANDROID_RULES,
+ ALLOWED_JVM_RULES = _ALLOWED_JVM_RULES,
+ JAR_FILE_TYPE = _JAR_FILE_TYPE,
+ JVM_FLAGS = BASE_JVMOPTS,
+ KT_FILE_TYPES = _KT_FILE_TYPES,
+ KT_JVM_FILE_TYPES = _KT_JVM_FILE_TYPES,
+ RULE_FAMILY = _RULE_FAMILY,
+ SRCJAR_FILE_TYPES = _SRCJAR_FILE_TYPES,
+ collect_proguard_specs = _collect_proguard_specs,
+ collect_providers = _collect_providers,
+ create_jar_from_tree_artifacts = _create_jar_from_tree_artifacts,
+ is_kt_src = _is_kt_src,
+ kt_jvm_import = _kt_jvm_import,
+ kt_jvm_library = _kt_jvm_library,
+ kt_plugins_map = _kt_plugins_map,
+ partition = _partition,
+)
diff --git a/kotlin/compiler_opt.bzl b/kotlin/compiler_opt.bzl
new file mode 100644
index 0000000..e7a89d5
--- /dev/null
+++ b/kotlin/compiler_opt.bzl
@@ -0,0 +1,83 @@
+# 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.
+
+"""A rule for declaring and passing kotlinc opts in a restricted way.
+
+It is a goal for rules_kotlin that Kotlin libraries use consistent default compiler
+options across as much of the repo as possible. Doing so makes Kotlin easier to
+maintain at scale.
+
+If an exception needs to be made for some library, `kt_compiler_opt` can be used to
+declare a set of additional options with restricted visibility. That target can then
+be passed to the `custom_kotlincopts` attribute. The set of directories that allow
+`kt_compiler_opt` targets is also limited, to prevent misuse.
+"""
+
+# Intentionally private to prevent misuse.
+_KtCompilerOptInfo = provider(
+ doc = "A restricted set of kotlinc opts",
+ fields = {"opts": "list[string]"},
+)
+
+_ALLOWED_ROOTS = [
+]
+
+_ALLOWED_VISIBILITY_NAMES = [
+ "__pkg__",
+ "__subpackages__",
+]
+
+def _kt_compiler_opt_impl(ctx):
+ if not any([ctx.label.package.startswith(p) for p in _ALLOWED_ROOTS]):
+ fail("kt_compiler_opt is only allowed under " + str(_ALLOWED_ROOTS))
+
+ visibility_groups = [v for v in ctx.attr.visibility if not v.name in _ALLOWED_VISIBILITY_NAMES]
+ if len(visibility_groups) > 0:
+ fail("Using package groups for visibility may expose custom options too broadly: " + str(visibility_groups))
+
+ return [_KtCompilerOptInfo(opts = ctx.attr.opts)]
+
+kt_compiler_opt = rule(
+ implementation = _kt_compiler_opt_impl,
+ attrs = {
+ "opts": attr.string_list(
+ doc = "The opt(s) this target represents.",
+ mandatory = True,
+ ),
+ },
+)
+
+def kotlincopts_attrs():
+ return dict(
+ custom_kotlincopts = attr.label_list(
+ doc = "kt_compiler_opt targets to pass to Kotlin compiler. Most users should not need this attr.",
+ providers = [[_KtCompilerOptInfo]],
+ cfg = "exec",
+ ),
+ )
+
+def merge_kotlincopts(ctx):
+ """Returns the complete list of opts behind custom_kotlincopts
+
+ Args:
+ ctx: A ctx matching kotlincopts_attrs
+
+ Returns:
+ The list of opts
+ """
+ custom_opts = []
+ for target in ctx.attr.custom_kotlincopts:
+ custom_opts.extend(target[_KtCompilerOptInfo].opts)
+
+ return custom_opts
diff --git a/kotlin/compiler_plugin.bzl b/kotlin/compiler_plugin.bzl
new file mode 100644
index 0000000..3527aee
--- /dev/null
+++ b/kotlin/compiler_plugin.bzl
@@ -0,0 +1,82 @@
+# 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.
+
+"""A rule for declaring and passing kotlinc plugins."""
+
+_KtCompilerPluginInfo = provider(
+ doc = "Info for running a plugin that directly registers itself to kotlinc extension points",
+ fields = dict(
+ plugin_id = "string",
+ jar = "File",
+ args = "list[string]",
+ ),
+)
+
+KtCompilerPluginInfo, _make_kt_compiler_plugin_info = (_KtCompilerPluginInfo, _KtCompilerPluginInfo)
+
+def _kt_compiler_plugin_impl(ctx):
+
+ return [
+ JavaPluginInfo(
+ runtime_deps = [],
+ processor_class = None,
+ ),
+ _make_kt_compiler_plugin_info(
+ plugin_id = ctx.attr.plugin_id,
+ jar = ctx.file.jar or ctx.attr.jar[JavaInfo].output_jar,
+ args = [
+ "plugin:%s:%s=%s" % (ctx.attr.plugin_id, k, v)
+ for (k, v) in ctx.attr.args.items()
+ ],
+ ),
+ ]
+
+kt_compiler_plugin = rule(
+ implementation = _kt_compiler_plugin_impl,
+ attrs = dict(
+ plugin_id = attr.string(
+ doc = "ID used to register this plugin with kotlinc",
+ mandatory = True,
+ ),
+ jar = attr.label(
+ doc = "JAR that provides the plugin implementation",
+ mandatory = True,
+ allow_single_file = [".jar"],
+ cfg = "exec",
+ ),
+ args = attr.string_dict(
+ doc = """Args to pass to the plugin
+
+ The rule impl will format key-value pairs for the koltinc
+ CLI. All plugin invocations will receive the same args.
+ """,
+ default = {},
+ ),
+ ),
+ provides = [
+ JavaPluginInfo, # Allow this rule to be passed to java rules
+ KtCompilerPluginInfo,
+ ],
+)
+
+def _get_exported_plugins(_target, ctx_rule):
+ return [t[KtCompilerPluginInfo] for t in getattr(ctx_rule.attr, "exported_plugins", []) if (KtCompilerPluginInfo in t)]
+
+kt_compiler_plugin_visitor = struct(
+ name = "compiler_plugins",
+ visit_target = _get_exported_plugins,
+ filter_edge = None,
+ finish_expansion = None,
+ process_unvisited_target = None,
+)
diff --git a/kotlin/compiler_plugin_export.bzl b/kotlin/compiler_plugin_export.bzl
new file mode 100644
index 0000000..d0ff426
--- /dev/null
+++ b/kotlin/compiler_plugin_export.bzl
@@ -0,0 +1,62 @@
+# 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.
+
+"""Convenience macro for getting `kt_compiler_plugin` into uncooperative rules.
+
+Some targets (Z), where we would like to export a plugin (Y), use rules that don't
+support `exported_plugins` (e.g android_library). To solve this, we create a dummy
+target (X) that has `X.exported_plugins = [Y]`, and then set `Z.exports = [Y]`.
+This creates a chain of exports for `kt_traverse_exports` to follow when discovering
+`kt_compiler_plugin`s.
+"""
+
+load(":compiler_plugin.bzl", "kt_compiler_plugin")
+load(":jvm_import.bzl", "kt_jvm_import")
+
+def _kt_compiler_plugin_export(
+ name,
+ visibility = [],
+ compatible_with = [],
+ **kwargs):
+ if not name.endswith("_plugin_export"):
+ fail()
+
+ basename = name.replace("_plugin_export", "")
+
+ kt_jvm_import(
+ name = name,
+ exported_plugins = [basename + "_plugin"],
+ jars = [basename + "_empty_jar"],
+ compatible_with = compatible_with,
+ visibility = visibility,
+ neverlink = True, # Don't link kotlin stdlib into Java users
+ )
+
+ kt_compiler_plugin(
+ name = basename + "_plugin",
+ visibility = visibility,
+ compatible_with = compatible_with,
+ **kwargs
+ )
+
+ native.genrule(
+ name = basename + "_empty_jar",
+ visibility = visibility,
+ outs = [name + "_empty.jar"],
+ cmd = """$(location @bazel_tools//tools/zip:zipper) c $@ "assets/_empty=" """,
+ compatible_with = compatible_with,
+ tools = ["@bazel_tools//tools/zip:zipper"],
+ )
+
+kt_compiler_plugin_export = _kt_compiler_plugin_export
diff --git a/kotlin/direct_jdeps.bzl b/kotlin/direct_jdeps.bzl
new file mode 100644
index 0000000..f242989
--- /dev/null
+++ b/kotlin/direct_jdeps.bzl
@@ -0,0 +1,26 @@
+# 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.
+
+"""kt_traverse_exports visitor for exposing jdeps files from direct deps."""
+
+def _get_jdeps(target, _ctx_rule):
+ return [out.compile_jdeps for out in target[JavaInfo].java_outputs if out.compile_jdeps]
+
+kt_direct_jdeps_visitor = struct(
+ name = "direct_jdeps",
+ visit_target = _get_jdeps,
+ filter_edge = None,
+ process_unvisited_target = None,
+ finish_expansion = None,
+)
diff --git a/kotlin/forbidden_deps.bzl b/kotlin/forbidden_deps.bzl
new file mode 100644
index 0000000..67a04fb
--- /dev/null
+++ b/kotlin/forbidden_deps.bzl
@@ -0,0 +1,65 @@
+# 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.
+
+"""kt_traverse_exports visitor for identifying forbidden deps of Kotlin rules.
+
+Currently this system recognizes:
+ - nano protos
+ - targets in forbidden packages
+ - targets exporting other forbidden targets
+"""
+
+load("@bazel_skylib//lib:sets.bzl", "sets")
+load("//bazel:stubs.bzl", "EXEMPT_DEPS", "FORBIDDEN_DEP_PACKAGES")
+
+def _error(target, msg):
+ return (str(target.label), msg)
+
+def _is_exempt(target):
+ return sets.contains(EXEMPT_DEPS, str(target.label))
+
+def _check_forbidden(target, ctx_rule):
+ if _is_exempt(target):
+ return []
+
+ if sets.contains(FORBIDDEN_DEP_PACKAGES, target.label.package):
+ return [_error(target, "Forbidden package")]
+
+ # Identify nano protos using tag (b/122083175)
+ for tag in ctx_rule.attr.tags:
+ if "nano_proto_library" == tag:
+ return [_error(target, "nano_proto_library")]
+
+ return []
+
+def _if_not_checked(target):
+ return [] if _is_exempt(target) else [_error(target, "Not checked")]
+
+def _validate_deps(error_set):
+ if not error_set:
+ return
+
+ error_lines = [
+ " " + name + " : " + msg
+ for (name, msg) in error_set.to_list()
+ ]
+ fail("Forbidden deps, see go/kotlin/build-rules#restrictions:\n" + "\n".join(error_lines))
+
+kt_forbidden_deps_visitor = struct(
+ name = "forbidden_deps",
+ visit_target = _check_forbidden,
+ filter_edge = None,
+ process_unvisited_target = _if_not_checked,
+ finish_expansion = _validate_deps,
+)
diff --git a/kotlin/friend_jars.bzl b/kotlin/friend_jars.bzl
new file mode 100644
index 0000000..4efb435
--- /dev/null
+++ b/kotlin/friend_jars.bzl
@@ -0,0 +1,66 @@
+# 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.
+
+"""TODO: Write module docstring."""
+
+def _is_eligible_friend(target, friend):
+ """
+ Determines if `target` is allowed to call `friend` a friend (and use its `internal` members).
+
+ To be eligible, `target` must be one of:
+ - in the parallel `java/` package from a `javatests/` package
+ - in the parallel `main/java` package from a `test/java` package
+ - another target in the same `BUILD` file
+
+ Args:
+ target: (target) The current target
+ friend: (Target) A potential friend of `target`
+ """
+
+ target_pkg = target.label.package + "/"
+ friend_pkg = friend.label.package + "/"
+
+ if target_pkg == friend_pkg:
+ # Allow friends on targets in the same package
+ return True
+
+ if "javatests/" in target_pkg and "java/" in friend_pkg:
+ # Allow friends from javatests/ on the parallel java/ package
+ target_java_pkg = target_pkg.rsplit("javatests/", 1)[1]
+ friend_java_pkg = friend_pkg.rsplit("java/", 1)[1]
+ if target_java_pkg == friend_java_pkg:
+ return True
+
+ if ("test/java/" in target_pkg and "main/java/" in friend_pkg and
+ True):
+ # Allow friends from test/java on the parallel main/java package
+ target_split = target_pkg.rsplit("test/java/", 1)
+ friend_split = friend_pkg.rsplit("main/java/", 1)
+ if target_split == friend_split:
+ return True
+
+ return False
+
+def _get_output_jars(target, _ctx_rule):
+ # We can't simply use `JavaInfo.compile_jars` because we only want the JARs directly created by
+ # `target`, and not JARs from its `exports`
+ return [output.compile_jar for output in target[JavaInfo].java_outputs if output.compile_jar]
+
+kt_friend_jars_visitor = struct(
+ name = "friend_jars",
+ visit_target = _get_output_jars,
+ filter_edge = _is_eligible_friend,
+ finish_expansion = None,
+ process_unvisited_target = None,
+)
diff --git a/kotlin/java_plugin.internal.bzl b/kotlin/java_plugin.internal.bzl
new file mode 100644
index 0000000..08f5463
--- /dev/null
+++ b/kotlin/java_plugin.internal.bzl
@@ -0,0 +1,36 @@
+# 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.
+
+"""Utilities related to java_plugin and JavaPluginInfo.
+
+kt_codegen_plugin is using this visitor to extract java_plugin information.
+Due to cross plugin type processing, the plugin info search processor differs
+from the way that java targets handles plugins.
+"""
+
+def _get_java_plugins(_target, ctx_rule):
+ exported_plugins = getattr(ctx_rule.attr, "exported_plugins", [])
+ return [
+ t[JavaPluginInfo]
+ for t in exported_plugins
+ if JavaPluginInfo in t
+ ]
+
+java_plugin_visitor = struct(
+ name = "java_plugins",
+ visit_target = _get_java_plugins,
+ filter_edge = None,
+ finish_expansion = None,
+ process_unvisited_target = None,
+)
diff --git a/kotlin/jvm_compile.bzl b/kotlin/jvm_compile.bzl
new file mode 100644
index 0000000..694a8a4
--- /dev/null
+++ b/kotlin/jvm_compile.bzl
@@ -0,0 +1,207 @@
+# 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.
+
+"""Compile method that can compile kotlin or java sources"""
+
+load(":common.bzl", "common")
+load(":traverse_exports.bzl", "kt_traverse_exports")
+load(":compiler_plugin.bzl", "KtCompilerPluginInfo")
+load("@bazel_skylib//lib:sets.bzl", "sets")
+
+_RULE_FAMILY = common.RULE_FAMILY
+
+def kt_jvm_compile(
+ ctx,
+ output,
+ srcs,
+ common_srcs,
+ deps,
+ plugins,
+ runtime_deps,
+ exports,
+ javacopts,
+ kotlincopts,
+ neverlink,
+ testonly,
+ android_lint_plugins,
+ resource_files,
+ exported_plugins,
+ manifest = None,
+ merged_manifest = None,
+ classpath_resources = [],
+ kt_toolchain = None,
+ java_toolchain = None,
+ android_lint_rules_jars = depset(),
+ disable_lint_checks = [],
+ r_java = None,
+ output_srcjar = None,
+ flogger_runtime = None,
+ rule_family = _RULE_FAMILY.UNKNOWN,
+ annotation_processor_additional_outputs = [],
+ annotation_processor_additional_inputs = [],
+ coverage_srcs = [],
+ **_kwargs):
+ """
+ The Kotlin JVM Compile method.
+
+ Args:
+ ctx: The context.
+ output: A File. The output jar.
+ srcs: List of Files. The Kotlin and Java sources.
+ common_srcs: List of common source files.
+ deps: List of targets. A list of dependencies.
+ plugins: List of targets. A list of jvm plugins.
+ runtime_deps: List of targets. A list of runtime deps.
+ exports: List of targets. A list of exports.
+ javacopts: List of strings. A list of Java compile options.
+ kotlincopts: List of strings. A list of Kotlin compile options.
+ neverlink: A bool. Signifies whether the target is only used for compile-time.
+ testonly: A bool. Signifies whether the target is only used for testing only.
+ android_lint_plugins: List of targets. An list of android lint plugins to
+ execute as a part of linting.
+ resource_files: List of Files. The list of Android Resource files.
+ exported_plugins: List of exported javac/kotlinc plugins
+ manifest: A File. The raw Android manifest. Optional.
+ merged_manifest: A File. The merged Android manifest. Optional.
+ classpath_resources: List of Files. The list of classpath resources (kt_jvm_library only).
+ kt_toolchain: The Kotlin toolchain.
+ java_toolchain: The Java toolchain.
+ android_lint_rules_jars: Depset of Files. Standalone Android Lint rule Jar artifacts.
+ disable_lint_checks: Whether to disable link checks.
+ NOTE: This field should only be used when the provider is not produced
+ by a target. For example, the JavaInfo created for the Android R.java
+ within an android_library rule.
+ r_java: A JavaInfo provider. The JavaInfo provider for the Android R.java
+ which is both depended on and propagated as an export.
+ NOTE: This field accepts a JavaInfo, but should only be used for the
+ Android R.java within an android_library rule.
+ output_srcjar: Target output file for generated source jar. Default filename used if None.
+ flogger_runtime: JavaInfo, Flogger runtime. Optional
+ rule_family: The family of the rule calling this function. Element of common.RULE_FAMILY.
+ May be used to enable/disable some features.
+ annotation_processor_additional_outputs: sequence of Files. A list of
+ files produced by an annotation processor.
+ annotation_processor_additional_inputs: sequence of Files. A list of
+ files consumed by an annotation processor.
+ coverage_srcs: Files to use as the basis when computing code coverage. These are typically
+ handwritten files that were inputs to generated `srcs`. Should be disjoint with `srcs`.
+ **_kwargs: Unused kwargs so that parameters are easy to add and remove.
+
+ Returns:
+ A struct that carries the following fields: java_info and validations.
+ """
+ if rule_family != _RULE_FAMILY.ANDROID_LIBRARY and not (srcs + common_srcs + exports):
+ # Demands either of the following to be present.
+ # - Source-type artifacts, srcs or common_srcs, including an empty
+ # tree-artifact (a directory) or a srcjar without jar entries.
+ # - Exporting targets, exports. It is typically used by a library author
+ # to publish one user-facing target with direct exposure to its
+ # dependent libraries.
+ fail("Expected one of (srcs, common_srcs, exports) is not empty for kotlin/jvm_compile on target: {}".format(ctx.label))
+
+ if type(java_toolchain) != "JavaToolchainInfo":
+ # Allow passing either a target or a provider until all callers are updated
+ java_toolchain = java_toolchain[java_common.JavaToolchainInfo]
+
+ srcs = list(srcs)
+ classpath_resources = list(classpath_resources)
+ java_infos = []
+ pre_processed_java_plugin_processors = sets.make([])
+ use_flogger = False
+
+ # Skip deps validation check for any android_library target with no kotlin sources: b/239721906
+ has_kt_srcs = any([common.is_kt_src(src) for src in srcs])
+ if rule_family != _RULE_FAMILY.ANDROID_LIBRARY or has_kt_srcs:
+ kt_traverse_exports.expand_forbidden_deps(deps + runtime_deps + exports)
+
+ for dep in deps:
+ # Collect JavaInfo providers and info about plugins (JavaPluginData).
+ if JavaInfo in dep:
+ java_infos.append(dep[JavaInfo])
+
+ else:
+ fail("Unexpected dependency (must provide JavaInfo): %s" % dep.label)
+
+ if rule_family != _RULE_FAMILY.ANDROID_LIBRARY or srcs or common_srcs:
+ java_infos.extend(kt_toolchain.kotlin_libs)
+
+ # TODO: Inject the runtime library from the flogger API target
+ if use_flogger:
+ if not flogger_runtime:
+ fail("Dependency on flogger exists, but flogger_runtime not passed")
+ java_infos.append(flogger_runtime)
+
+ if kotlincopts != None and "-Werror" in kotlincopts:
+ fail("Flag -Werror is not permitted")
+
+ if classpath_resources and rule_family != _RULE_FAMILY.JVM_LIBRARY:
+ fail("resources attribute only allowed for jvm libraries")
+
+ # The r_java field only support Android resources Jar files. For now, verify
+ # that the name of the jar matches "_resources.jar". This check does not to
+ # prevent malicious use, the intent is to prevent accidental usage.
+ r_java_info = []
+ if r_java:
+ for jar in r_java.outputs.jars:
+ if not jar.class_jar.path.endswith("_resources.jar"):
+ fail("Error, illegal dependency provided for r_java. This " +
+ "only supports Android resource Jar files, " +
+ "'*_resources.jar'.")
+ r_java_info.append(r_java)
+
+ return common.kt_jvm_library(
+ ctx,
+ android_lint_plugins = android_lint_plugins, # List of JavaInfo
+ android_lint_rules_jars = android_lint_rules_jars,
+ classpath_resources = classpath_resources,
+ common_srcs = common_srcs,
+ coverage_srcs = coverage_srcs,
+ deps = r_java_info + java_infos,
+ disable_lint_checks = disable_lint_checks,
+ exported_plugins = [e[JavaPluginInfo] for e in exported_plugins if (JavaPluginInfo in e)],
+ # Not all exported targets contain a JavaInfo (e.g. some only have CcInfo)
+ exports = r_java_info + [e[JavaInfo] for e in exports if JavaInfo in e],
+ friend_jars = kt_traverse_exports.expand_friend_jars(deps, root = ctx),
+ java_toolchain = java_toolchain,
+ javacopts = javacopts,
+ kotlincopts = kotlincopts,
+ compile_jdeps = kt_traverse_exports.expand_direct_jdeps(deps),
+ kt_toolchain = kt_toolchain,
+ manifest = manifest,
+ merged_manifest = merged_manifest,
+ native_libraries = [p[CcInfo] for p in deps + runtime_deps + exports if CcInfo in p],
+ neverlink = neverlink,
+ output = output,
+ output_srcjar = output_srcjar,
+ plugins = common.kt_plugins_map(
+ java_plugin_infos = [plugin[JavaPluginInfo] for plugin in plugins if (JavaPluginInfo in plugin)],
+ kt_compiler_plugin_infos =
+ kt_traverse_exports.expand_compiler_plugins(deps).to_list() + [
+ plugin[KtCompilerPluginInfo]
+ for plugin in plugins
+ if (KtCompilerPluginInfo in plugin)
+ ],
+ ),
+ pre_processed_java_plugin_processors = pre_processed_java_plugin_processors,
+ resource_files = resource_files,
+ runtime_deps = [d[JavaInfo] for d in runtime_deps if JavaInfo in d],
+ srcs = srcs,
+ testonly = testonly,
+ rule_family = rule_family,
+ annotation_processor_additional_outputs = annotation_processor_additional_outputs,
+ annotation_processor_additional_inputs = annotation_processor_additional_inputs,
+ )
+
+# TODO Delete this
+compile = kt_jvm_compile
diff --git a/kotlin/jvm_import.bzl b/kotlin/jvm_import.bzl
new file mode 100644
index 0000000..ed740ca
--- /dev/null
+++ b/kotlin/jvm_import.bzl
@@ -0,0 +1,164 @@
+# 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.
+
+"""Kotlin kt_jvm_import rule."""
+
+load(":common.bzl", "common")
+load(":traverse_exports.bzl", "kt_traverse_exports")
+load("//toolchains/kotlin_jvm:kt_jvm_toolchains.bzl", "kt_jvm_toolchains")
+load("//toolchains/kotlin_jvm:java_toolchains.bzl", "java_toolchains")
+load("@bazel_skylib//lib:dicts.bzl", "dicts")
+load(":compiler_plugin.bzl", "KtCompilerPluginInfo")
+
+def _kt_jvm_import_impl(ctx):
+ kt_jvm_toolchain = kt_jvm_toolchains.get(ctx)
+
+ if not ctx.files.jars:
+ fail("List of jars cannot be empty")
+
+ deps_java_infos = []
+ for dep in ctx.attr.deps:
+ deps_java_infos.append(dep[JavaInfo])
+
+ # Put Kotlin's standard libs last to match what kotlinc would do without -no-stdlib
+ deps_java_infos.extend(kt_jvm_toolchain.kotlin_libs)
+
+ runtime_deps_java_infos = []
+ for runtime_dep in ctx.attr.runtime_deps:
+ # Collect JavaInfo providers
+ if JavaInfo in runtime_dep:
+ runtime_deps_java_infos.append(runtime_dep[JavaInfo])
+ elif CcInfo not in runtime_dep:
+ fail("Unexpected runtime dependency (must provide JavaInfo or CcInfo): %" % runtime_dep.label)
+
+ result = common.kt_jvm_import(
+ ctx,
+ jars = ctx.files.jars,
+ srcjar = ctx.file.srcjar,
+ deps = deps_java_infos,
+ runtime_deps = runtime_deps_java_infos,
+ neverlink = ctx.attr.neverlink,
+ java_toolchain = java_toolchains.get(ctx),
+ deps_checker = ctx.executable._deps_checker,
+ )
+ result_java_info = result.java_info
+
+ # Collect runfiles from deps unless neverlink
+ runfiles = None
+ if not ctx.attr.neverlink:
+ transitive_runfiles = []
+ for p in common.collect_providers(DefaultInfo, ctx.attr.deps):
+ transitive_runfiles.append(p.data_runfiles.files)
+ transitive_runfiles.append(p.default_runfiles.files)
+ runfiles = ctx.runfiles(
+ files = ctx.files.jars,
+ transitive_files = depset(transitive = transitive_runfiles),
+ collect_default = True, # handles data attribute
+ )
+
+ return [
+ result_java_info,
+ ProguardSpecProvider(common.collect_proguard_specs(
+ ctx,
+ ctx.files.proguard_specs,
+ ctx.attr.deps,
+ kt_jvm_toolchain.proguard_whitelister,
+ )),
+ OutputGroupInfo(_validation = depset(result.validations)),
+ DefaultInfo(runfiles = runfiles), # rule doesn't build any files
+ ]
+
+_KT_JVM_IMPORT_ATTRS = dicts.add(
+ java_toolchains.attrs,
+ kt_jvm_toolchains.attrs,
+ deps = attr.label_list(
+ # We allow android rule deps to make importing android JARs easier.
+ allow_rules = common.ALLOWED_JVM_RULES + common.ALLOWED_ANDROID_RULES,
+ aspects = [kt_traverse_exports.aspect],
+ providers = [
+ # Each provider-set expands on allow_rules
+ [JavaInfo],
+ ],
+ doc = """The list of libraries this library directly depends on at compile-time. For Java
+ and Kotlin libraries listed, the Jars they build as well as the transitive closure
+ of their `deps` and `exports` will be on the compile-time classpath for this rule;
+ also, the transitive closure of their `deps`, `runtime_deps`, and `exports` will be
+ on the runtime classpath (excluding dependencies only depended on as `neverlink`).
+
+ Note on strict_deps: any Java type explicitly or implicitly referred to in `srcs`
+ must be included here. This is a stronger requirement than what is enforced for
+ `java_library`. Any build failures resulting from this requirement will include the
+ missing dependencies and a command to fix the rule.""",
+ ),
+ exported_plugins = attr.label_list(
+ providers = [[KtCompilerPluginInfo]],
+ cfg = "exec",
+ doc = """JVM plugins to export to users.
+
+
+ Every plugin listed will run during compliations that depend on this target, as
+ if it were listed directly in that target's `plugins` attribute. `java_*` targets
+ will not run kotlinc plugins""",
+ ),
+ jars = attr.label_list(
+ allow_files = common.JAR_FILE_TYPE,
+ allow_empty = False,
+ doc = """The list of Java and/or Kotlin JAR files provided to targets that depend on this
+ target (required). Currently only a single Jar is supported.""",
+ ),
+ neverlink = attr.bool(
+ default = False,
+ doc = """Only use this library for compilation and not at runtime.""",
+ ),
+ proguard_specs = attr.label_list(
+ allow_files = True,
+ doc = """Proguard specifications to go along with this library.""",
+ ),
+ runtime_deps = attr.label_list(
+ # TODO: Delete common.ALLOWED_ANDROID_RULES
+ allow_rules = common.ALLOWED_JVM_RULES + common.ALLOWED_ANDROID_RULES,
+ providers = [
+ # Each provider-set expands on allow_rules
+ [CcInfo], # for JNI / native dependencies
+ ],
+ aspects = [kt_traverse_exports.aspect],
+ doc = """Runtime-only dependencies.""",
+ ),
+ srcjar = attr.label(
+ allow_single_file = common.SRCJAR_FILE_TYPES,
+ doc = """A JAR file that contains source code for the compiled JAR files.""",
+ ),
+ _deps_checker = attr.label(
+ default = "@bazel_tools//tools/android:aar_import_deps_checker",
+ executable = True,
+ cfg = "exec",
+ ),
+)
+
+kt_jvm_import = rule(
+ attrs = _KT_JVM_IMPORT_ATTRS,
+ fragments = ["java"],
+ provides = [JavaInfo],
+ implementation = _kt_jvm_import_impl,
+ toolchains = [kt_jvm_toolchains.type],
+ doc = """Allows the use of precompiled Kotlin `.jar` files as deps of `kt_*` targets.
+
+ Prefer this rule to `java_import` for Kotlin Jars. Most Java-like libraries
+ and binaries can depend on this rule, and this rule can in turn depend on Kotlin and
+ Java libraries. This rule supports a subset of attributes supported by `java_import`.
+
+ In addition to documentation provided as part of this rule, please also refer to their
+ documentation as part of `java_import`.
+ """,
+)
diff --git a/kotlin/jvm_library.bzl b/kotlin/jvm_library.bzl
new file mode 100644
index 0000000..f2ffe09
--- /dev/null
+++ b/kotlin/jvm_library.bzl
@@ -0,0 +1,126 @@
+# 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.
+
+"""Kotlin kt_jvm_library rule."""
+
+load(":jvm_library.internal.bzl", "kt_jvm_library_helper")
+load("//bazel:stubs.bzl", "register_extension_info")
+
+def kt_jvm_library(
+ name,
+ srcs = None,
+ common_srcs = None,
+ data = None,
+ exports = None,
+ deps = None,
+ runtime_deps = None,
+ proguard_specs = None,
+ plugins = None,
+ exported_plugins = None,
+ resources = None,
+ tags = None,
+ testonly = None, # None to preserve Blaze's defaults, b/112708042
+ javacopts = None,
+ custom_kotlincopts = None,
+ disable_lint_checks = None,
+ compatible_with = None,
+ restricted_to = None,
+ transitive_configs = None,
+ visibility = None,
+ deprecation = None,
+ features = []):
+ """This rule compiles Kotlin (and Java) sources into a Jar file.
+
+ Most Java-like libraries
+ and binaries can depend on this rule, and this rule can in turn depend on Kotlin and
+ Java libraries. This rule supports a subset of attributes supported by `java_library`.
+ In addition to documentation provided as part of this rule, please also refer to their
+ documentation as part of `java_library`.
+
+ Args:
+ name: Name of the target.
+ srcs: A list of sources to compile.
+ common_srcs: A list of common sources to compile for multi-platform projects.
+ data: A list of data dependencies.
+ exports: A list of targets to export to rules that depend on this one.
+ deps: A list of dependencies. NOTE: kt_library targets cannot be added here (yet).
+ runtime_deps: Libraries to make available to the final binary or test at runtime only.
+ proguard_specs: Proguard specifications to go along with this library.
+ plugins: Java annotation processors to run at compile-time.
+ exported_plugins: https://bazel.build/reference/be/java#java_plugin rules to export to direct
+ dependencies.
+ resources: A list of data files to include in the Jar, see
+ https://bazel.build/reference/be/java#java_library.resources.
+ tags: A list of string tags passed to generated targets.
+ testonly: Whether this target is intended only for tests.
+ javacopts: Additional flags to pass to javac if used.
+ custom_kotlincopts: Additional flags to pass to Kotlin compiler.
+ disable_lint_checks: A list of AndroidLint checks to be skipped.
+ compatible_with: Standard attribute, see
+ https://bazel.build/reference/be/common-definitions#common.compatible_with.
+ restricted_to: Standard attribute, see
+ https://bazel.build/reference/be/common-definitions#common.restricted_to.
+ transitive_configs: Blaze feature flags (if any) on which this target depends.
+ visibility: A list of targets allowed to depend on this rule.
+ deprecation: Standard attribute, see
+ https://bazel.build/reference/be/common-definitions#common.deprecation.
+ features: Features enabled.
+ """
+ srcs = srcs or []
+ common_srcs = common_srcs or []
+ data = data or []
+ exports = exports or []
+ deps = deps or []
+ runtime_deps = runtime_deps or []
+ plugins = plugins or []
+ exported_plugins = exported_plugins or []
+ proguard_specs = proguard_specs or []
+ resources = resources or []
+
+ # Helps go/build_cleaner to identify the targets generated by the macro.
+ tags = (tags or []) + ["kt_jvm_library"]
+
+ # Ask go/build_cleaner to avoid all generated targets.
+ javacopts = javacopts or []
+ disable_lint_checks = disable_lint_checks or []
+
+ kt_jvm_library_helper(
+ name = name,
+ srcs = srcs,
+ common_srcs = common_srcs,
+ deps = deps,
+ exports = exports,
+ runtime_deps = runtime_deps,
+ plugins = plugins,
+ exported_plugins = exported_plugins,
+ resources = resources,
+ javacopts = javacopts,
+ custom_kotlincopts = custom_kotlincopts,
+ proguard_specs = proguard_specs,
+ data = data,
+ disable_lint_checks = disable_lint_checks,
+ tags = tags,
+ testonly = testonly,
+ compatible_with = compatible_with,
+ restricted_to = restricted_to,
+ transitive_configs = transitive_configs,
+ visibility = visibility,
+ deprecation = deprecation,
+ features = features,
+ )
+
+register_extension_info(
+ extension = kt_jvm_library,
+ label_regex_for_dep = "{extension_name}",
+)
diff --git a/kotlin/jvm_library.internal.bzl b/kotlin/jvm_library.internal.bzl
new file mode 100644
index 0000000..7334f95
--- /dev/null
+++ b/kotlin/jvm_library.internal.bzl
@@ -0,0 +1,253 @@
+# 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.
+
+"""Kotlin kt_jvm_library rule."""
+
+load("//kotlin:compiler_opt.bzl", "kotlincopts_attrs", "merge_kotlincopts")
+load("//toolchains/kotlin_jvm:java_toolchains.bzl", "java_toolchains")
+load("//toolchains/kotlin_jvm:kt_jvm_toolchains.bzl", "kt_jvm_toolchains")
+load("@bazel_skylib//lib:dicts.bzl", "dicts")
+load(":common.bzl", "common")
+load(":compiler_plugin.bzl", "KtCompilerPluginInfo")
+load(":traverse_exports.bzl", "kt_traverse_exports")
+load(":jvm_compile.bzl", "kt_jvm_compile")
+
+# TODO: Use this function in all Kotlin rules
+def _make_default_info(ctx, direct_files, propagated_attrs):
+ # Collect runfiles from deps
+ transitive_runfiles = []
+ for p in common.collect_providers(DefaultInfo, propagated_attrs):
+ transitive_runfiles.append(p.data_runfiles.files)
+ transitive_runfiles.append(p.default_runfiles.files)
+ runfiles = ctx.runfiles(
+ files = direct_files,
+ transitive_files = depset(transitive = transitive_runfiles),
+ collect_default = True, # handles data attribute
+ )
+
+ return DefaultInfo(
+ files = depset(direct_files),
+ runfiles = runfiles,
+ )
+
+def _jvm_library_impl(ctx):
+ kt_jvm_toolchain = kt_jvm_toolchains.get(ctx)
+
+ for target in ctx.attr.runtime_deps:
+ if JavaInfo in target:
+ pass
+ elif CcInfo not in target:
+ fail("Unexpected runtime dependency (must provide JavaInfo or CcInfo): " + str(target.label))
+
+ if not ctx.files.srcs and not ctx.files.common_srcs and not ctx.attr.exports and not ctx.attr.exported_plugins:
+ fail("Expected a source-bearing or an export-oriented target:\n" +
+ "One of {srcs, common_srcs, exports, exported_plugins} of target %s must be non empty" % ctx.label)
+
+ compile_result = kt_jvm_compile(
+ ctx,
+ output = ctx.outputs.jar,
+ srcs = ctx.files.srcs,
+ common_srcs = ctx.files.common_srcs,
+ deps = ctx.attr.deps,
+ plugins = ctx.attr.plugins,
+ exported_plugins = ctx.attr.exported_plugins,
+ runtime_deps = ctx.attr.runtime_deps,
+ exports = ctx.attr.exports,
+ javacopts = ctx.attr.javacopts,
+ kotlincopts = merge_kotlincopts(ctx),
+ neverlink = False,
+ testonly = ctx.attr.testonly,
+ android_lint_plugins = [p[JavaInfo] for p in ctx.attr._android_lint_plugins],
+ manifest = None,
+ merged_manifest = None,
+ resource_files = [],
+ classpath_resources = ctx.files.resources,
+ kt_toolchain = kt_jvm_toolchain,
+ java_toolchain = java_toolchains.get(ctx),
+ disable_lint_checks = ctx.attr.disable_lint_checks,
+ rule_family = common.RULE_FAMILY.JVM_LIBRARY,
+ )
+
+ java_info = compile_result.java_info
+
+ # Collect and validate proguard_specs
+ # TODO should also propagate IDL proguard_specs when there's idl_srcs
+ transitive_proguard_configs = common.collect_proguard_specs(
+ ctx,
+ ctx.files.proguard_specs,
+ ctx.attr.deps + ctx.attr.exports,
+ kt_jvm_toolchain.proguard_whitelister,
+ )
+
+ # Create OutputGroupInfo
+ output_groups = dict(
+ _validation = depset(compile_result.validations),
+ _source_jars = depset(
+ java_info.source_jars,
+ transitive = [java_info.transitive_source_jars],
+ ),
+ _direct_source_jars = depset(java_info.source_jars),
+ _hidden_top_level_INTERNAL_ = depset(
+ transitive = [
+ info._hidden_top_level_INTERNAL_
+ for info in common.collect_providers(
+ OutputGroupInfo,
+ ctx.attr.deps + ctx.attr.exports,
+ )
+ ] + [transitive_proguard_configs],
+ ),
+ )
+
+ return [
+ java_info,
+ ProguardSpecProvider(transitive_proguard_configs),
+ _make_default_info(
+ ctx,
+ [ctx.outputs.jar],
+ propagated_attrs = ctx.attr.deps + ctx.attr.runtime_deps + ctx.attr.exports,
+ ),
+ OutputGroupInfo(**output_groups),
+ coverage_common.instrumented_files_info(
+ ctx,
+ source_attributes = ["srcs", "common_srcs"],
+ dependency_attributes = ["data", "deps", "resources", "runtime_deps"],
+ ),
+ ]
+
+_KT_JVM_LIBRARY_ATTRS = dicts.add(
+ java_toolchains.attrs,
+ kotlincopts_attrs(),
+ kt_jvm_toolchains.attrs,
+ common_srcs = attr.label_list(
+ allow_files = common.KT_FILE_TYPES,
+ allow_empty = True,
+ doc = """The list of common multi-platform source files that are processed to create
+ the target.""",
+ ),
+ data = attr.label_list(
+ allow_files = True,
+ ),
+ deps = attr.label_list(
+ allow_rules = common.ALLOWED_JVM_RULES,
+ providers = [
+ # Each provider-set expands on allow_rules
+ ],
+ aspects = [
+ kt_traverse_exports.aspect,
+ ],
+ doc = """The list of libraries this library directly depends on at compile-time. For Java
+ and Kotlin libraries listed, the Jars they build as well as the transitive closure
+ of their `deps` and `exports` will be on the compile-time classpath for this rule;
+ also, the transitive closure of their `deps`, `runtime_deps`, and `exports` will be
+ on the runtime classpath (excluding dependencies only depended on as `neverlink`).
+
+ Note on strict_deps: any Java type explicitly or implicitly referred to in `srcs`
+ must be included here. This is a stronger requirement than what is enforced for
+ `java_library`. Any build failures resulting from this requirement will include the
+ missing dependencies and a command to fix the rule.""",
+ ),
+ disable_lint_checks = attr.string_list(
+ doc = """A list of lint checks to be skipped for this target.""",
+ ),
+ exported_plugins = attr.label_list(
+ providers = [
+ [JavaPluginInfo],
+ [KtCompilerPluginInfo],
+ ],
+ cfg = "exec",
+ doc = """JVM plugins to export to users.
+
+ Every plugin listed will run during compliations that depend on this target, as
+ if it were listed directly in that target's `plugins` attribute. `java_*` targets
+ will not run kotlinc plugins""",
+ ),
+ exports = attr.label_list(
+ allow_rules = common.ALLOWED_JVM_RULES,
+ providers = [
+ # Each provider-set expands on allow_rules
+ ],
+ aspects = [
+ kt_traverse_exports.aspect,
+ ],
+ doc = """List of libraries treated as if they were part of this library by upstream
+ Java/Kotlin dependencies, see go/be-java#java_library.exports. These libraries
+ are **not** automatically also dependencies of this library.""",
+ ),
+ javacopts = attr.string_list(
+ doc = """Additional flags to pass to javac if used as part of this rule, which is the case
+ if `.java` `srcs` are provided or annotation processors generate sources for this
+ rule.""",
+ ),
+ plugins = attr.label_list(
+ providers = [
+ [JavaPluginInfo],
+ [KtCompilerPluginInfo],
+ ],
+ cfg = "exec",
+ doc = """JVM plugins to run during compilation.
+
+ Every plugin listed will run whenever this library is built. Resources generated by the
+ plugin will be included in the output JAR. A library may also inherit plugins from
+ dependencies that use `exported_plugins`.""",
+ ),
+ proguard_specs = attr.label_list(
+ allow_files = True,
+ doc = """Proguard specifications to go along with this library.""",
+ ),
+ resources = attr.label_list(
+ allow_files = True,
+ doc = """A list of data files to include in the Jar, see
+ go/be#java_library.resources.""",
+ ),
+ runtime_deps = attr.label_list(
+ allow_rules = common.ALLOWED_JVM_RULES,
+ providers = [
+ # Each provider-set expands on allow_rules
+ [CcInfo], # for JNI / native dependencies
+ ],
+ aspects = [
+ kt_traverse_exports.aspect,
+ ],
+ doc = """Runtime-only dependencies.""",
+ ),
+ srcs = attr.label_list(
+ allow_files = common.KT_JVM_FILE_TYPES,
+ allow_empty = True,
+ doc = """The list of source files that are processed to create the target.
+ To support circular dependencies, this can include `.kt` and `.java` files.""",
+ ),
+ _android_lint_plugins = attr.label_list(
+ providers = [
+ [JavaInfo],
+ ],
+ cfg = "exec",
+ ),
+)
+
+kt_jvm_library_helper = rule(
+ attrs = _KT_JVM_LIBRARY_ATTRS,
+ fragments = ["java"],
+ outputs = dict(
+ jar = "lib%{name}.jar",
+ srcjar = "lib%{name}-src.jar", # implicit declared output for consistency with java_library
+ ),
+ provides = [JavaInfo],
+ implementation = _jvm_library_impl,
+ toolchains = [kt_jvm_toolchains.type],
+ doc = """This rule compiles Kotlin (and Java) sources into a Jar file. Most Java-like libraries
+ and binaries can depend on this rule, and this rule can in turn depend on Kotlin and
+ Java libraries. This rule supports a subset of attributes supported by `java_library`.
+ In addition to documentation provided as part of this rule, please also refer to their
+ documentation as part of `java_library`.""",
+)
diff --git a/kotlin/jvm_test.bzl b/kotlin/jvm_test.bzl
new file mode 100644
index 0000000..b7270e2
--- /dev/null
+++ b/kotlin/jvm_test.bzl
@@ -0,0 +1,85 @@
+# 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.
+
+"""Kotlin macro for building and running tests on a JVM."""
+
+load(":jvm_library.bzl", "kt_jvm_library")
+load("//bazel:stubs.bzl", "register_extension_info")
+
+def _lib_name(name):
+ return "%s_DO_NOT_DEPEND_LIB" % name
+
+def kt_jvm_test(
+ name,
+ custom_kotlincopts = None,
+ deps = None,
+ disable_lint_checks = None,
+ features = None,
+ javacopts = None,
+ plugins = None,
+ runtime_deps = None,
+ srcs = None,
+ resources = None,
+ tags = None,
+ **kwargs):
+ """Wrapper around kt_jvm_library and java_test to conveniently declare tests written in Kotlin.
+
+ Use of this rule is discouraged for simple unit tests, which should instead use
+ go/junit-test-suites or other, more efficient ways of compiling and running unit tests.
+
+ Args:
+ name: Name of the target.
+ custom_kotlincopts: Additional flags to pass to Kotlin compiler defined by kt_compiler_opt.
+ deps: A list of dependencies.
+ disable_lint_checks: A list of AndroidLint checks to be skipped.
+ features: A list of enabled features, see go/be#common.features.
+ javacopts: Additional flags to pass to javac if used.
+ plugins: Java annotation processors to run at compile-time.
+ runtime_deps: A list of runtime dependencies.
+ srcs: A list of sources to compile.
+ tags: A list of string tags passed to generated targets.
+ **kwargs: Additional parameters to pass on to generated java_test, see go/be-java#java_test.
+ """
+ if srcs:
+ runtime_deps = [_lib_name(name)] + (runtime_deps or [])
+
+ kt_jvm_library(
+ name = _lib_name(name),
+ srcs = srcs,
+ resources = resources,
+ deps = deps,
+ plugins = plugins,
+ javacopts = javacopts,
+ custom_kotlincopts = custom_kotlincopts,
+ disable_lint_checks = disable_lint_checks,
+ tags = tags,
+ features = features,
+ testonly = 1,
+ visibility = ["//visibility:private"],
+ )
+ elif deps:
+ fail("deps specified without sources. Use runtime_deps instead to specify any dependencies needed to run this test.")
+
+ native.java_test(
+ name = name,
+ runtime_deps = runtime_deps,
+ tags = tags,
+ features = features,
+ **kwargs
+ )
+
+register_extension_info(
+ extension = kt_jvm_test,
+ label_regex_for_dep = "{extension_name}_DO_NOT_DEPEND_LIB",
+)
diff --git a/kotlin/rules.bzl b/kotlin/rules.bzl
new file mode 100644
index 0000000..8d0188b
--- /dev/null
+++ b/kotlin/rules.bzl
@@ -0,0 +1,25 @@
+# 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.
+
+"""Kotlin rules."""
+
+load("//kotlin:jvm_import.bzl", _kt_jvm_import = "kt_jvm_import")
+load("//kotlin:jvm_library.bzl", _kt_jvm_library = "kt_jvm_library")
+load("//kotlin:jvm_test.bzl", _kt_jvm_test = "kt_jvm_test")
+
+kt_jvm_import = _kt_jvm_import
+
+kt_jvm_library = _kt_jvm_library
+
+kt_jvm_test = _kt_jvm_test
diff --git a/kotlin/traverse_exports.bzl b/kotlin/traverse_exports.bzl
new file mode 100644
index 0000000..e579080
--- /dev/null
+++ b/kotlin/traverse_exports.bzl
@@ -0,0 +1,121 @@
+# 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.
+
+"""Combined aspect for all rules_kotlin behaviours that need to traverse exports."""
+
+load(":compiler_plugin.bzl", "kt_compiler_plugin_visitor")
+load(":direct_jdeps.bzl", "kt_direct_jdeps_visitor")
+load(":forbidden_deps.bzl", "kt_forbidden_deps_visitor")
+load(":friend_jars.bzl", "kt_friend_jars_visitor")
+load(":java_plugin.internal.bzl", "java_plugin_visitor")
+
+# java_xxx_proto_library don't populate java_outputs but we can get them through
+# required_aspect_providers from their proto_library deps.
+_DEPS_AS_EXPORTS_RULES = [
+ "java_proto_library",
+ "java_lite_proto_library",
+ "java_mutable_proto_library",
+]
+
+_NO_SRCS_DEPS_AS_EXPORTS_RULES = [
+ "android_library",
+ "proto_library",
+]
+
+# visitor = struct[T](
+# name = string,
+# visit_target = function(Target, ctx.rule): list[T],
+# filter_edge = None|(function(src: ?, dest: Target): bool),
+# process_unvisited_target = None|(function(Target): list[T]),
+# finish_expansion = None|(function(depset[T]): depset[T]),
+# )
+_VISITORS = [
+ kt_forbidden_deps_visitor,
+ kt_direct_jdeps_visitor,
+ kt_compiler_plugin_visitor,
+ kt_friend_jars_visitor,
+ java_plugin_visitor,
+]
+
+_KtTraverseExportsInfo = provider(
+ doc = "depsets for transitive info about exports",
+ fields = {
+ v.name: ("depset[%s]" % v.name)
+ for v in _VISITORS
+ },
+)
+
+_EMPTY_KT_TRAVERSE_EXPORTS_INFO = _KtTraverseExportsInfo(**{
+ v.name: depset()
+ for v in _VISITORS
+})
+
+def _aspect_impl(target, ctx):
+ if not (JavaInfo in target):
+ # Ignore non-JVM targets. This also chops-up the
+ # traversal domain at these targets.
+ # TODO: Supoprt non-JVM targets for KMP
+ return _EMPTY_KT_TRAVERSE_EXPORTS_INFO
+
+ exports = []
+ exports.extend(getattr(ctx.rule.attr, "exports", [])) # exports list is frozen
+ if ctx.rule.kind in _DEPS_AS_EXPORTS_RULES:
+ exports.extend(ctx.rule.attr.deps)
+ elif ctx.rule.kind in _NO_SRCS_DEPS_AS_EXPORTS_RULES and not ctx.rule.attr.srcs:
+ exports.extend(ctx.rule.attr.deps)
+
+ return _KtTraverseExportsInfo(**{
+ v.name: depset(
+ direct = v.visit_target(target, ctx.rule),
+ transitive = [
+ getattr(e[_KtTraverseExportsInfo], v.name)
+ for e in exports
+ if (not v.filter_edge or v.filter_edge(target, e))
+ ],
+ )
+ for v in _VISITORS
+ })
+
+_aspect = aspect(
+ implementation = _aspect_impl,
+ provides = [_KtTraverseExportsInfo],
+ # Transitively check exports, since they are effectively directly depended on.
+ # "deps" needed for rules that treat deps as exports (usually absent srcs).
+ attr_aspects = ["exports", "deps"],
+ required_aspect_providers = [JavaInfo], # to get at JavaXxxProtoAspects' JavaInfos
+)
+
+def _create_visitor_expand(visitor):
+ def _visitor_expand(targets, root = None):
+ direct = []
+ transitive = []
+ for t in targets:
+ if (not visitor.filter_edge or visitor.filter_edge(root, t)):
+ if _KtTraverseExportsInfo in t:
+ transitive.append(getattr(t[_KtTraverseExportsInfo], visitor.name))
+ elif visitor.process_unvisited_target:
+ direct.extend(visitor.process_unvisited_target(t))
+
+ expanded_set = depset(direct = direct, transitive = transitive)
+ return visitor.finish_expansion(expanded_set) if visitor.finish_expansion else expanded_set
+
+ return _visitor_expand
+
+kt_traverse_exports = struct(
+ aspect = _aspect,
+ **{
+ "expand_" + v.name: _create_visitor_expand(v)
+ for v in _VISITORS
+ }
+)
diff --git a/tests/BUILD b/tests/BUILD
new file mode 100644
index 0000000..414af7d
--- /dev/null
+++ b/tests/BUILD
@@ -0,0 +1,13 @@
+# 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.
diff --git a/tests/analysis/BUILD b/tests/analysis/BUILD
new file mode 100644
index 0000000..b927805
--- /dev/null
+++ b/tests/analysis/BUILD
@@ -0,0 +1,27 @@
+# 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.
+
+# Analysis Tests
+
+load("//tests/analysis:jvm_compile_test.bzl", jvm_compile_test_suite = "test_suite")
+load("//tests/analysis:jvm_import_test.bzl", jvm_import_test_suite = "test_suite")
+load("//tests/analysis:jvm_library_test.bzl", jvm_library_test_suite = "test_suite")
+
+licenses(["notice"])
+
+jvm_compile_test_suite(name = "jvm_compile_tests")
+
+jvm_library_test_suite(name = "jvm_library_tests")
+
+jvm_import_test_suite(name = "jvm_import_tests")
diff --git a/tests/analysis/assert_failure_test.bzl b/tests/analysis/assert_failure_test.bzl
new file mode 100644
index 0000000..b266c2a
--- /dev/null
+++ b/tests/analysis/assert_failure_test.bzl
@@ -0,0 +1,30 @@
+# 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.
+
+"""An assertion for analysis failure."""
+
+load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
+
+def _assert_failure_test_impl(ctx):
+ env = analysistest.begin(ctx)
+ asserts.expect_failure(env, ctx.attr.msg_contains)
+ return analysistest.end(env)
+
+assert_failure_test = analysistest.make(
+ _assert_failure_test_impl,
+ expect_failure = True,
+ attrs = dict(
+ msg_contains = attr.string(mandatory = True),
+ ),
+)
diff --git a/tests/analysis/compiler_plugin/BUILD b/tests/analysis/compiler_plugin/BUILD
new file mode 100644
index 0000000..0c1f9b6
--- /dev/null
+++ b/tests/analysis/compiler_plugin/BUILD
@@ -0,0 +1,23 @@
+# 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 = "empty_jar",
+ outs = ["empty.jar"],
+ cmd = """$(location @bazel_tools//tools/zip:zipper) c $@ "assets/_empty=" """,
+ tools = ["@bazel_tools//tools/zip:zipper"],
+ visibility = ["//tests/analysis/compiler_plugin:__subpackages__"],
+)
diff --git a/tests/analysis/compiler_plugin/forbidden_target/BUILD b/tests/analysis/compiler_plugin/forbidden_target/BUILD
new file mode 100644
index 0000000..9f751fa
--- /dev/null
+++ b/tests/analysis/compiler_plugin/forbidden_target/BUILD
@@ -0,0 +1,19 @@
+# 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("//kotlin:compiler_plugin.bzl", "kt_compiler_plugin")
+load("//tests/analysis:assert_failure_test.bzl", "assert_failure_test")
+load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS")
+
+licenses(["notice"])
diff --git a/tests/analysis/compiler_plugin/propagation/BUILD b/tests/analysis/compiler_plugin/propagation/BUILD
new file mode 100644
index 0000000..0c6fe19
--- /dev/null
+++ b/tests/analysis/compiler_plugin/propagation/BUILD
@@ -0,0 +1,79 @@
+# 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("//kotlin:compiler_plugin.bzl", "kt_compiler_plugin")
+load(":assert_propagation_test.bzl", "assert_propagation_test")
+
+licenses(["notice"])
+
+assert_propagation_test(
+ name = "f",
+ expected_plugin_ids = ["1"],
+ deps = [":e"],
+)
+
+assert_propagation_test(
+ name = "e",
+ expected_plugin_ids = [],
+ exports = [":a"],
+)
+
+assert_propagation_test(
+ name = "d",
+ expected_plugin_ids = [
+ "1",
+ "2",
+ ],
+ deps = [
+ ":a",
+ ":b",
+ ],
+)
+
+assert_propagation_test(
+ name = "c",
+ expected_plugin_ids = ["2"],
+ deps = [":b"],
+)
+
+assert_propagation_test(
+ name = "b",
+ expected_plugin_ids = ["1"],
+ exported_plugins = [":2"],
+ deps = [":a"],
+)
+
+assert_propagation_test(
+ name = "a",
+ expected_plugin_ids = [],
+ exported_plugins = [":1"],
+)
+
+kt_compiler_plugin(
+ name = "1",
+ jar = "//tests/analysis/compiler_plugin:empty_jar",
+ plugin_id = "1",
+)
+
+kt_compiler_plugin(
+ name = "2",
+ jar = "//tests/analysis/compiler_plugin:empty_jar",
+ plugin_id = "2",
+)
+
+kt_compiler_plugin(
+ name = "3",
+ jar = "//tests/analysis/compiler_plugin:empty_jar",
+ plugin_id = "3",
+)
diff --git a/tests/analysis/compiler_plugin/propagation/assert_propagation_test.bzl b/tests/analysis/compiler_plugin/propagation/assert_propagation_test.bzl
new file mode 100644
index 0000000..fe8c9dc
--- /dev/null
+++ b/tests/analysis/compiler_plugin/propagation/assert_propagation_test.bzl
@@ -0,0 +1,56 @@
+# 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.
+
+"""Rule for asserting plugin propagation."""
+
+load("@bazel_skylib//lib:sets.bzl", "sets")
+load("@bazel_skylib//rules:build_test.bzl", "build_test")
+load("//kotlin:traverse_exports.bzl", "kt_traverse_exports")
+
+def _assert_propagation_impl(ctx):
+ expected_ids = sets.make(ctx.attr.expected_plugin_ids)
+ actual_ids = sets.make([
+ p.plugin_id
+ for p in kt_traverse_exports.expand_compiler_plugins(ctx.attr.deps).to_list()
+ ])
+
+ if not sets.is_equal(expected_ids, actual_ids):
+ fail("Expected IDs %s, actual IDs %s" % (sets.to_list(expected_ids), sets.to_list(actual_ids)))
+
+ return [
+ # Needed for kt_traverse_exports.aspect
+ JavaInfo(
+ compile_jar = ctx.file._empty_jar,
+ output_jar = ctx.file._empty_jar,
+ ),
+ ]
+
+_assert_propagation = rule(
+ implementation = _assert_propagation_impl,
+ attrs = dict(
+ exports = attr.label_list(),
+ exported_plugins = attr.label_list(),
+ expected_plugin_ids = attr.string_list(),
+ deps = attr.label_list(aspects = [kt_traverse_exports.aspect]),
+ _empty_jar = attr.label(
+ allow_single_file = True,
+ default = "//tests/analysis/compiler_plugin:empty_jar",
+ ),
+ ),
+)
+
+def assert_propagation_test(name, **kwargs):
+ _assert_propagation(name = name, **kwargs)
+
+ build_test(name = name + "_build", targets = [name])
diff --git a/tests/analysis/compiler_plugin/provider_ctor/BUILD b/tests/analysis/compiler_plugin/provider_ctor/BUILD
new file mode 100644
index 0000000..fb5acbc
--- /dev/null
+++ b/tests/analysis/compiler_plugin/provider_ctor/BUILD
@@ -0,0 +1,19 @@
+# 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("//tests/analysis:assert_failure_test.bzl", "assert_failure_test")
+load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS")
+load(":fake_compiler_plugin.bzl", "kt_fake_compiler_plugin")
+
+licenses(["notice"])
diff --git a/tests/analysis/compiler_plugin/provider_ctor/fake_compiler_plugin.bzl b/tests/analysis/compiler_plugin/provider_ctor/fake_compiler_plugin.bzl
new file mode 100644
index 0000000..d4a6bac
--- /dev/null
+++ b/tests/analysis/compiler_plugin/provider_ctor/fake_compiler_plugin.bzl
@@ -0,0 +1,37 @@
+# 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.
+
+"""A fake impl of kt_compiler_plugin."""
+
+load("//kotlin:compiler_plugin.bzl", "KtCompilerPluginInfo")
+
+def _kt_fake_compiler_plugin_impl(ctx):
+ return [
+ KtCompilerPluginInfo(
+ plugin_id = "fake",
+ jar = ctx.file._jar,
+ args = [],
+ ),
+ ]
+
+kt_fake_compiler_plugin = rule(
+ implementation = _kt_fake_compiler_plugin_impl,
+ attrs = dict(
+ _jar = attr.label(
+ allow_single_file = True,
+ default = "//tests/analysis/compiler_plugin:empty_jar",
+ ),
+ ),
+ provides = [KtCompilerPluginInfo],
+)
diff --git a/tests/analysis/compiler_plugin/provider_output/BUILD b/tests/analysis/compiler_plugin/provider_output/BUILD
new file mode 100644
index 0000000..4769965
--- /dev/null
+++ b/tests/analysis/compiler_plugin/provider_output/BUILD
@@ -0,0 +1,58 @@
+# 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("//kotlin:compiler_plugin.bzl", "kt_compiler_plugin")
+load("//tests/analysis:util.bzl", "create_file")
+load("@bazel_skylib//rules:build_test.bzl", "build_test")
+load(":assert_compiler_plugin_test.bzl", "assert_compiler_plugin_test")
+
+licenses(["notice"])
+
+assert_compiler_plugin_test(
+ name = "example_plugin_test",
+ expected_args = [
+ "plugin:com.google.example:key=value",
+ ],
+ expected_id = "com.google.example",
+ expected_jar = "//tests/analysis/compiler_plugin:empty_jar",
+ target_under_test = ":example_plugin",
+)
+
+build_test(
+ name = "example_plugin_in_java_library_build_test",
+ targets = [
+ ":example_plugin_in_java_library",
+ ],
+)
+
+java_library(
+ name = "example_plugin_in_java_library",
+ srcs = [create_file(
+ name = "Tmp.java",
+ content = """
+ @SuppressWarnings("DefaultPackage")
+ class Tmp { }
+ """,
+ )],
+ plugins = [":example_plugin"],
+)
+
+kt_compiler_plugin(
+ name = "example_plugin",
+ args = {
+ "key": "value",
+ },
+ jar = "//tests/analysis/compiler_plugin:empty_jar",
+ plugin_id = "com.google.example",
+)
diff --git a/tests/analysis/compiler_plugin/provider_output/assert_compiler_plugin_test.bzl b/tests/analysis/compiler_plugin/provider_output/assert_compiler_plugin_test.bzl
new file mode 100644
index 0000000..9b2951e
--- /dev/null
+++ b/tests/analysis/compiler_plugin/provider_output/assert_compiler_plugin_test.bzl
@@ -0,0 +1,37 @@
+# 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.
+
+"""An assertion on kt_compiler_plugin analysis."""
+
+load("//kotlin:compiler_plugin.bzl", "KtCompilerPluginInfo")
+load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
+
+def _test_impl(ctx):
+ env = analysistest.begin(ctx)
+ info = ctx.attr.target_under_test[KtCompilerPluginInfo]
+
+ asserts.equals(env, info.plugin_id, ctx.attr.expected_id)
+ asserts.equals(env, info.jar, ctx.file.expected_jar)
+ asserts.equals(env, info.args, ctx.attr.expected_args)
+
+ return analysistest.end(env)
+
+assert_compiler_plugin_test = analysistest.make(
+ impl = _test_impl,
+ attrs = dict(
+ expected_id = attr.string(),
+ expected_jar = attr.label(allow_single_file = True, cfg = "exec"),
+ expected_args = attr.string_list(),
+ ),
+)
diff --git a/tests/analysis/jvm_compile_test.bzl b/tests/analysis/jvm_compile_test.bzl
new file mode 100644
index 0000000..b361f5a
--- /dev/null
+++ b/tests/analysis/jvm_compile_test.bzl
@@ -0,0 +1,390 @@
+# 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.
+
+"""Kotlin kt_jvm_compile API test."""
+
+load("//kotlin:traverse_exports.bzl", "kt_traverse_exports")
+load("//kotlin:jvm_compile.bzl", "kt_jvm_compile")
+load("//kotlin:common.bzl", "common")
+load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS", "create_dir", "create_file")
+load("//toolchains/kotlin_jvm:java_toolchains.bzl", "java_toolchains")
+load("//toolchains/kotlin_jvm:kt_jvm_toolchains.bzl", "kt_jvm_toolchains")
+load("@bazel_skylib//rules:build_test.bzl", "build_test")
+load(":assert_failure_test.bzl", "assert_failure_test")
+
+def _impl(ctx):
+ # As additional capabilites need to be tested, this rule should support
+ # additional fields/attributes.
+ result = kt_jvm_compile(
+ ctx,
+ output = ctx.outputs.jar,
+ srcs = ctx.files.srcs,
+ common_srcs = ctx.files.common_srcs,
+ deps = ctx.attr.deps,
+ plugins = [],
+ exported_plugins = [],
+ runtime_deps = [],
+ exports = ctx.attr.exports,
+ javacopts = [],
+ kotlincopts = [],
+ neverlink = False,
+ testonly = False,
+ android_lint_plugins = [],
+ manifest = None,
+ merged_manifest = None,
+ resource_files = [],
+ rule_family = ctx.attr.rule_family,
+ kt_toolchain = kt_jvm_toolchains.get(ctx),
+ java_toolchain = java_toolchains.get(ctx),
+ disable_lint_checks = [],
+ r_java = ctx.attr.r_java[JavaInfo] if ctx.attr.r_java else None,
+ )
+ return [result.java_info]
+
+_kt_jvm_compile = rule(
+ implementation = _impl,
+ attrs = dict(
+ srcs = attr.label_list(
+ allow_files = True,
+ ),
+ common_srcs = attr.label_list(
+ allow_files = True,
+ ),
+ deps = attr.label_list(
+ aspects = [kt_traverse_exports.aspect],
+ providers = [JavaInfo],
+ ),
+ exports = attr.label_list(
+ aspects = [kt_traverse_exports.aspect],
+ providers = [JavaInfo],
+ ),
+ rule_family = attr.int(
+ default = common.RULE_FAMILY.UNKNOWN,
+ ),
+ r_java = attr.label(
+ providers = [JavaInfo],
+ ),
+ _java_toolchain = attr.label(
+ default = Label(
+ "@bazel_tools//tools/jdk:current_java_toolchain",
+ ),
+ ),
+ ),
+ fragments = ["java"],
+ outputs = dict(
+ jar = "lib%{name}.jar",
+ ),
+ toolchains = [kt_jvm_toolchains.type],
+)
+
+def _test_kt_jvm_compile_using_kt_jvm_compile_with_r_java():
+ test_name = "kt_jvm_compile_using_kt_jvm_compile_with_r_java_test"
+
+ native.java_library(
+ name = "foo_resources",
+ srcs = [create_file(
+ name = test_name + "/java/com/foo/R.java",
+ content = """
+package com.foo;
+
+public final class R {
+ public static final class string {
+ public static int a_string=0x00000001;
+ public static int b_string=0x00000002;
+ }
+}
+""",
+ )],
+ )
+
+ _kt_jvm_compile(
+ name = "kt_jvm_compile_with_r_java",
+ srcs = [create_file(
+ name = test_name + "/AString.kt",
+ content = """
+package test
+
+import com.foo.R.string.a_string
+
+fun aString(): String = "a_string=" + a_string
+""",
+ )],
+ r_java = ":foo_resources",
+ )
+
+ _kt_jvm_compile(
+ name = "kt_jvm_compile_using_kt_jvm_compile_with_r_java",
+ srcs = [create_file(
+ name = test_name + "/ABString.kt",
+ content = """
+package test
+
+import com.foo.R.string.b_string
+
+fun bString(): String = "b_string=" + b_string
+
+fun abString(): String = aString() + bString()
+""",
+ )],
+ deps = [":kt_jvm_compile_with_r_java"],
+ )
+
+ # If a failure occurs, it will be at build time.
+ build_test(
+ name = test_name,
+ targets = [":kt_jvm_compile_using_kt_jvm_compile_with_r_java"],
+ )
+ return test_name
+
+def _test_kt_jvm_compile_with_illegal_r_java():
+ test_name = "kt_jvm_compile_with_illegal_r_java_test"
+
+ native.java_library(
+ name = "foo",
+ srcs = [create_file(
+ name = test_name + "/java/com/foo/Foo.java",
+ content = """
+package com.foo;
+
+public class Foo {}
+""",
+ )],
+ )
+ _kt_jvm_compile(
+ name = "kt_jvm_compile_with_illegal_r_java",
+ srcs = [create_file(
+ name = test_name + "/AString.kt",
+ content = """
+package test
+
+import com.foo.Foo
+
+fun bar(): String = "Bar"
+""",
+ )],
+ tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
+ r_java = ":foo",
+ )
+ assert_failure_test(
+ name = test_name,
+ target_under_test = ":kt_jvm_compile_with_illegal_r_java",
+ msg_contains = "illegal dependency provided for r_java",
+ )
+ return test_name
+
+def _test_kt_jvm_compile_with_r_java_as_first_dep():
+ test_name = "kt_jvm_compile_with_r_java_as_first_dep_test"
+
+ # Note: The R from an android_library must be the first dependency in
+ # the classpath to prevent another libraries R from being used for
+ # compilation. If the ordering is incorrect, compiletime failures will
+ # occur as the depot relies on this ordering.
+
+ native.java_library(
+ name = "foo_with_symbol_resources",
+ srcs = [create_file(
+ name = test_name + "/with_symbol/java/com/foo/R.java",
+ content = """
+package com.foo;
+
+public final class R {
+ public static final class string {
+ public static int a_string=0x00000001;
+ }
+}
+""",
+ )],
+ )
+
+ native.java_library(
+ name = "foo_without_symbol_resources",
+ srcs = [create_file(
+ name = test_name + "/without_symbol/java/com/foo/R.java",
+ content = """
+package com.foo;
+
+public final class R {
+ public static final class string {
+ }
+}
+""",
+ )],
+ )
+
+ _kt_jvm_compile(
+ name = "kt_jvm_compile_with_r_java_as_first_dep",
+ srcs = [create_file(
+ name = test_name + "/AString.kt",
+ content = """
+package test
+
+import com.foo.R.string.a_string
+
+fun aString(): String = "a_string=" + a_string
+""",
+ )],
+ r_java = ":foo_with_symbol_resources",
+ deps = [":foo_without_symbol_resources"],
+ )
+
+ # If a failure occurs, it will be at build time.
+ build_test(
+ name = test_name,
+ targets = [":kt_jvm_compile_with_r_java_as_first_dep"],
+ )
+ return test_name
+
+def _test_kt_jvm_compile_without_srcs_for_android():
+ test_name = "kt_jvm_compile_without_srcs_for_android_test"
+
+ # This is a common case for rules like android_library where Kotlin sources
+ # could be empty, due to the rule being used for resource processing. For
+ # this scenario, historically, rules continue to produce empty Jars.
+ _kt_jvm_compile(
+ name = "kt_jvm_compile_without_srcs_for_android",
+ rule_family = common.RULE_FAMILY.ANDROID_LIBRARY,
+ )
+
+ # If a failure occurs, it will be at build time.
+ build_test(
+ name = test_name,
+ targets = [":kt_jvm_compile_without_srcs_for_android"],
+ )
+ return test_name
+
+def _test_kt_jvm_compile_without_srcs_for_jvm():
+ test_name = "kt_jvm_compile_without_srcs_for_jvm_test"
+
+ _kt_jvm_compile(
+ name = "kt_jvm_compile_without_srcs_for_jvm",
+ srcs = [],
+ common_srcs = [],
+ exports = [],
+ tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
+ )
+ assert_failure_test(
+ name = test_name,
+ target_under_test = ":kt_jvm_compile_without_srcs_for_jvm",
+ msg_contains = "Expected one of (srcs, common_srcs, exports) is not empty",
+ )
+ return test_name
+
+def _test_kt_jvm_compile_without_srcs_and_with_exports():
+ test_name = "kt_jvm_compile_without_srcs_and_with_exports_test"
+
+ _kt_jvm_compile(
+ name = "bar_lib",
+ srcs = [create_file(
+ name = test_name + "/Bar.kt",
+ content = """
+package test
+
+fun bar(): String = "Bar"
+""",
+ )],
+ )
+
+ _kt_jvm_compile(
+ name = "kt_jvm_compile_without_srcs_and_with_exports",
+ exports = [":bar_lib"],
+ )
+
+ _kt_jvm_compile(
+ name = "foo_bar_lib",
+ srcs = [create_file(
+ name = test_name + "/FooBar.kt",
+ content = """
+package test
+
+fun fooBar(): String = "Foo" + bar()
+""",
+ )],
+ deps = [":kt_jvm_compile_without_srcs_and_with_exports"],
+ )
+
+ # If a failure occurs, it will be at build time.
+ build_test(
+ name = test_name,
+ targets = [":foo_bar_lib"],
+ )
+ return test_name
+
+def _test_kt_jvm_compile_unsupported_src_artifacts():
+ test_name = "kt_jvm_compile_unsupported_src_artifacts_test"
+
+ kt_src = create_file(
+ name = test_name + "/src.kt",
+ content = "",
+ )
+ kt_dir = create_dir(
+ name = test_name + "/kotlin",
+ subdir = "",
+ srcs = [create_file(
+ name = test_name + "/dir.kt",
+ content = "",
+ )],
+ )
+ java_src = create_file(
+ name = test_name + "/src.java",
+ content = "",
+ )
+ java_dir = create_dir(
+ name = test_name + "/java",
+ subdir = "",
+ srcs = [create_file(
+ name = test_name + "/dir.java",
+ content = "",
+ )],
+ )
+ java_srcjar = create_file(
+ name = test_name + "/java.srcjar",
+ content = "",
+ )
+ _kt_jvm_compile(
+ name = test_name + "_expected_lib",
+ srcs = [kt_src, kt_dir, java_src, java_dir, java_srcjar],
+ tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
+ )
+
+ unexpected_file = create_file(
+ name = test_name + "/src.unexpected",
+ content = "",
+ )
+ _kt_jvm_compile(
+ name = test_name + "_unexpected_lib",
+ srcs = [unexpected_file],
+ deps = [test_name + "_expected_lib"],
+ tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
+ )
+
+ assert_failure_test(
+ name = test_name,
+ target_under_test = test_name + "_unexpected_lib",
+ msg_contains = "/src.unexpected",
+ )
+ return test_name
+
+def test_suite(name = None):
+ native.test_suite(
+ name = name,
+ tests = [
+ _test_kt_jvm_compile_unsupported_src_artifacts(),
+ _test_kt_jvm_compile_using_kt_jvm_compile_with_r_java(),
+ _test_kt_jvm_compile_with_illegal_r_java(),
+ _test_kt_jvm_compile_with_r_java_as_first_dep(),
+ _test_kt_jvm_compile_without_srcs_for_android(),
+ _test_kt_jvm_compile_without_srcs_for_jvm(),
+ _test_kt_jvm_compile_without_srcs_and_with_exports(),
+ ],
+ )
diff --git a/tests/analysis/jvm_import_test.bzl b/tests/analysis/jvm_import_test.bzl
new file mode 100644
index 0000000..a3bfd19
--- /dev/null
+++ b/tests/analysis/jvm_import_test.bzl
@@ -0,0 +1,168 @@
+# 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.
+
+"""Kotlin kt_jvm_import rule tests."""
+
+load("//kotlin:jvm_import.bzl", "kt_jvm_import")
+load("//kotlin:jvm_library.bzl", "kt_jvm_library")
+load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
+load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS", "create_file")
+load(":assert_failure_test.bzl", "assert_failure_test")
+
+def _impl(ctx):
+ env = analysistest.begin(ctx)
+ asserts.true(
+ env,
+ JavaInfo in ctx.attr.target_under_test,
+ "kt_jvm_import did not produce JavaInfo provider.",
+ )
+ asserts.true(
+ env,
+ ProguardSpecProvider in ctx.attr.target_under_test,
+ "kt_jvm_import did not produce ProguardSpecProvider provider.",
+ )
+ return analysistest.end(env)
+
+_test = analysistest.make(_impl)
+
+def _test_kt_jvm_import():
+ test_name = "kt_jvm_import_test"
+ native.java_library(
+ name = "jar1",
+ srcs = [],
+ )
+ kt_jvm_import(
+ name = test_name + "_tut",
+ jars = [
+ "libjar1.jar",
+ ],
+ srcjar = "libjar1-src.jar",
+ )
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ )
+ return test_name
+
+def _test_kt_jvm_import_no_srcjar():
+ test_name = "kt_jvm_import_no_srcjar_test"
+ native.java_library(
+ name = "jar3",
+ srcs = [],
+ )
+ kt_jvm_import(
+ name = test_name + "_tut",
+ jars = [
+ "libjar3.jar",
+ ],
+ )
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ )
+ return test_name
+
+def _test_kt_jvm_import_with_srcjar_ext():
+ test_name = "kt_jvm_import_test_with_srcjar_ext"
+ native.java_library(
+ name = "jar2",
+ srcs = [],
+ )
+ native.genrule(
+ name = "gen_jar2_srcjar",
+ cmd = "touch $@",
+ outs = ["libjar2.srcjar"],
+ )
+ kt_jvm_import(
+ name = test_name + "_tut",
+ jars = [
+ "libjar2.jar",
+ ],
+ srcjar = ":libjar2.srcjar",
+ )
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ )
+ return test_name
+
+def _test_kt_jvm_import_with_runtime_deps():
+ test_name = "kt_jvm_import_with_runtime_deps"
+ native.java_library(
+ name = test_name + "_dep",
+ srcs = [],
+ )
+ kt_jvm_import(
+ name = test_name + "_tut",
+ jars = [
+ "lib%s_dep.jar" % test_name,
+ ],
+ runtime_deps = [
+ test_name + "_dep",
+ ],
+ )
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ )
+ return test_name
+
+def _test_kt_jvm_import_with_proguard_specs():
+ test_name = "kt_jvm_import_with_proguard_specs"
+ native.java_library(
+ name = test_name + "_jar",
+ srcs = [],
+ )
+
+ kt_jvm_import(
+ name = test_name + "_tut",
+ jars = [
+ "lib%s_jar.jar" % test_name,
+ ],
+ proguard_specs = [
+ create_file(
+ name = test_name + "/salutations.pgcfg",
+ content = """
+-keep class * {
+ *** greeting();
+}
+""",
+ ),
+ ],
+ )
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ )
+ return test_name
+
+def _mock_jar(test_name, i):
+ """Creates a Jar named after the given inputs and returns its name."""
+ native.java_library(
+ name = "%s_mock%s" % (test_name, i),
+ srcs = [],
+ )
+ return "lib%s_mock%s.jar" % (test_name, i)
+
+def test_suite(name = None):
+ native.test_suite(
+ name = name,
+ tests = [
+ _test_kt_jvm_import(),
+ _test_kt_jvm_import_with_srcjar_ext(),
+ _test_kt_jvm_import_no_srcjar(),
+ _test_kt_jvm_import_with_runtime_deps(),
+ _test_kt_jvm_import_with_proguard_specs(),
+ ],
+ )
diff --git a/tests/analysis/jvm_library/friends/BUILD b/tests/analysis/jvm_library/friends/BUILD
new file mode 100644
index 0000000..3c4a7db
--- /dev/null
+++ b/tests/analysis/jvm_library/friends/BUILD
@@ -0,0 +1,105 @@
+# 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("//kotlin:rules.bzl", "kt_jvm_library")
+load("//tests/analysis:jvm_library_test.bzl", "jvm_library_test")
+load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS")
+
+package(
+ default_testonly = True,
+ default_visibility = ["//tests/analysis/jvm_library/friends:__subpackages__"],
+)
+
+licenses(["notice"])
+
+jvm_library_test(
+ name = "no_kt_exported_friend_trans_package_test",
+ expected_friend_jar_names = [],
+ target_under_test = ":no_kt_exported_friend_trans_package",
+)
+
+kt_jvm_library(
+ name = "no_kt_exported_friend_trans_package",
+ srcs = ["Input.kt"],
+ tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
+ deps = [
+ # Exports :friend from this package
+ "//tests/analysis/jvm_library/friends/sub:kt_exports_friend",
+ ],
+)
+
+jvm_library_test(
+ name = "has_java_exported_friend_in_package_test",
+ expected_friend_jar_names = [
+ "libjava_exports_friend-hjar.jar",
+ "friend-compile.jar",
+ ],
+ target_under_test = ":has_java_exported_friend_in_package",
+)
+
+kt_jvm_library(
+ name = "has_java_exported_friend_in_package",
+ srcs = ["Input.kt"],
+ tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
+ deps = [":java_exports_friend"],
+)
+
+java_library(
+ name = "java_exports_friend",
+ srcs = ["Input.java"],
+ tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
+ exports = [":friend"],
+)
+
+jvm_library_test(
+ name = "has_kt_exported_friend_in_package_test",
+ expected_friend_jar_names = [
+ "kt_exports_friend-compile.jar",
+ "friend-compile.jar",
+ ],
+ target_under_test = ":has_kt_exported_friend_in_package",
+)
+
+kt_jvm_library(
+ name = "has_kt_exported_friend_in_package",
+ srcs = ["Input.kt"],
+ tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
+ deps = [":kt_exports_friend"],
+)
+
+kt_jvm_library(
+ name = "kt_exports_friend",
+ srcs = ["Input.kt"],
+ tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
+ exports = [":friend"],
+)
+
+jvm_library_test(
+ name = "has_direct_friend_in_package_test",
+ expected_friend_jar_names = ["friend-compile.jar"],
+ target_under_test = ":has_direct_friend_in_package",
+)
+
+kt_jvm_library(
+ name = "has_direct_friend_in_package",
+ srcs = ["Input.kt"],
+ tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
+ deps = [":friend"],
+)
+
+kt_jvm_library(
+ name = "friend",
+ srcs = ["Input.kt"],
+ tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
+)
diff --git a/tests/analysis/jvm_library/friends/Input.java b/tests/analysis/jvm_library/friends/Input.java
new file mode 100644
index 0000000..5bf1d18
--- /dev/null
+++ b/tests/analysis/jvm_library/friends/Input.java
@@ -0,0 +1,19 @@
+/*
+ * * 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.
+ */
+
+package test;
+
+final class Input {}
diff --git a/tests/analysis/jvm_library/friends/Input.kt b/tests/analysis/jvm_library/friends/Input.kt
new file mode 100644
index 0000000..b1a99cb
--- /dev/null
+++ b/tests/analysis/jvm_library/friends/Input.kt
@@ -0,0 +1,17 @@
+/*
+ * * 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.
+ */
+
+package test
diff --git a/tests/analysis/jvm_library/friends/sub/BUILD b/tests/analysis/jvm_library/friends/sub/BUILD
new file mode 100644
index 0000000..7c26e59
--- /dev/null
+++ b/tests/analysis/jvm_library/friends/sub/BUILD
@@ -0,0 +1,60 @@
+# 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("//kotlin:rules.bzl", "kt_jvm_library")
+load("//tests/analysis:jvm_library_test.bzl", "jvm_library_test")
+load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS")
+
+package(
+ default_testonly = True,
+ default_visibility = ["//tests/analysis/jvm_library/friends:__subpackages__"],
+)
+
+licenses(["notice"])
+
+jvm_library_test(
+ name = "no_kt_exported_friend_cross_package_test",
+ expected_friend_jar_names = [
+ "kt_exports_friend-compile.jar",
+ # Absent # "friend-compile.jar"
+ ],
+ target_under_test = ":no_kt_exported_friend_cross_package",
+)
+
+kt_jvm_library(
+ name = "no_kt_exported_friend_cross_package",
+ srcs = ["Input.kt"],
+ tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
+ deps = [":kt_exports_friend"],
+)
+
+kt_jvm_library(
+ name = "kt_exports_friend",
+ srcs = ["Input.kt"],
+ tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
+ exports = ["//tests/analysis/jvm_library/friends:friend"],
+)
+
+jvm_library_test(
+ name = "no_direct_friend_cross_package_test",
+ expected_friend_jar_names = [],
+ target_under_test = ":no_direct_friend_cross_package",
+)
+
+kt_jvm_library(
+ name = "no_direct_friend_cross_package",
+ srcs = ["Input.kt"],
+ tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
+ deps = ["//tests/analysis/jvm_library/friends:friend"],
+)
diff --git a/tests/analysis/jvm_library/friends/sub/Input.kt b/tests/analysis/jvm_library/friends/sub/Input.kt
new file mode 100644
index 0000000..4c87a1e
--- /dev/null
+++ b/tests/analysis/jvm_library/friends/sub/Input.kt
@@ -0,0 +1,17 @@
+/*
+ * * 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.
+ */
+
+package test.sub
diff --git a/tests/analysis/jvm_library_test.bzl b/tests/analysis/jvm_library_test.bzl
new file mode 100644
index 0000000..a73bbbc
--- /dev/null
+++ b/tests/analysis/jvm_library_test.bzl
@@ -0,0 +1,838 @@
+# 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.
+
+"""Kotlin kt_jvm_library rule tests."""
+
+load("//kotlin:jvm_library.bzl", "kt_jvm_library")
+load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS", "create_file", "get_action_arg")
+load("@bazel_skylib//lib:sets.bzl", "sets")
+load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
+load(":assert_failure_test.bzl", "assert_failure_test")
+
+_DEFAULT_LIST = ["__default__"]
+
+def _test_impl(ctx):
+ env = analysistest.begin(ctx)
+ actions = analysistest.target_actions(env)
+ actual = ctx.attr.target_under_test
+ expected = ctx.attr.expected
+
+ asserts.true(
+ env,
+ JavaInfo in actual,
+ "kt_jvm_library did not produce JavaInfo provider.",
+ )
+ asserts.true(
+ env,
+ ProguardSpecProvider in actual,
+ "Expected a ProguardSpecProvider provider.",
+ )
+
+ if "data" in expected:
+ expected_data = expected["data"]
+ actual_data = _extract_data_runfiles(actual)
+
+ asserts.new_set_equals(
+ env,
+ sets.make(expected_data),
+ sets.make(actual_data),
+ """
+ FAIL: kt_jvm_library did not produce the expected data dependencies.
+ EXPECTED: %s
+ ACTUAL: %s
+ """ % (expected_data, actual_data),
+ )
+
+ expected_exports = []
+ for target in ctx.attr.expected_exports:
+ asserts.equals(
+ env,
+ 1,
+ len(target[JavaInfo].full_compile_jars.to_list()),
+ "Not a single compile-time Jar: %s" % target.label,
+ )
+ expected_exports.extend(target[JavaInfo].full_compile_jars.to_list())
+ actual_exports = actual[JavaInfo].full_compile_jars.to_list()
+
+ # TODO: fail if there are *un*expected exports, maybe by making sure
+ # that the actual exports are exactly the expected ones plus the Jar(s)
+ # produced by this JavaInfo.
+ for expected_export in expected_exports:
+ asserts.true(
+ env,
+ expected_export in actual_exports,
+ """
+ kt_jvm_library did not export %s
+ actual: %s
+ """ % (expected_export, actual_exports),
+ )
+
+ asserts.equals(
+ env,
+ ctx.attr.expected_exported_processor_classes,
+ actual[JavaInfo].plugins.processor_classes.to_list(),
+ )
+
+ if ctx.attr.expected_friend_jar_names != _DEFAULT_LIST:
+ friend_paths_arg = get_action_arg(actions, "Kt2JavaCompile", "-Xfriend-paths=")
+ friend_jar_names = [p.rsplit("/", 1)[1] for p in friend_paths_arg.split(",")] if friend_paths_arg else []
+ asserts.set_equals(env, sets.make(ctx.attr.expected_friend_jar_names), sets.make(friend_jar_names))
+
+ return analysistest.end(env)
+
+_test = analysistest.make(
+ impl = _test_impl,
+ attrs = dict(
+ expected = attr.string_list_dict(),
+ expected_exports = attr.label_list(),
+ expected_exported_processor_classes = attr.string_list(
+ doc = "Annotation processors reported as to be run on depending targets",
+ ),
+ expected_processor_classes = attr.string_list(
+ doc = "Annotation processors reported as run on the given target",
+ ),
+ expected_friend_jar_names = attr.string_list(
+ doc = "Names of all -Xfriend-paths= JARs",
+ default = _DEFAULT_LIST,
+ ),
+ expect_processor_classpath = attr.bool(),
+ ),
+)
+
+jvm_library_test = _test
+
+def _coverage_test_impl(ctx):
+ env = analysistest.begin(ctx)
+ target_under_test = analysistest.target_under_test(env)
+ instrumented_files_info = target_under_test[InstrumentedFilesInfo]
+ instrumented_files = instrumented_files_info.instrumented_files.to_list()
+ asserts.equals(
+ env,
+ ctx.attr.expected_instrumented_file_basenames,
+ [file.basename for file in instrumented_files],
+ )
+ return analysistest.end(env)
+
+_coverage_test = analysistest.make(
+ impl = _coverage_test_impl,
+ attrs = {
+ "expected_instrumented_file_basenames": attr.string_list(),
+ },
+ config_settings = {
+ "//command_line_option:collect_code_coverage": "1",
+ "//command_line_option:instrument_test_targets": "1",
+ "//command_line_option:instrumentation_filter": "+tests/analysis[:/]",
+ },
+)
+
+def _extract_data_runfiles(target):
+ return [f.basename for f in target[DefaultInfo].data_runfiles.files.to_list()]
+
+def _test_kt_jvm_library_with_deps():
+ test_name = "kt_jvm_library_with_deps_test"
+
+ kt_jvm_library(
+ name = test_name + "_kt_dep",
+ srcs = [create_file(
+ name = test_name + "/Hello.kt",
+ content = """
+package test
+
+fun hello(): String = "Hello!"
+""",
+ )],
+ )
+ native.java_library(
+ name = test_name + "_java_dep",
+ srcs = ["testinputs/Foo.java"],
+ )
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = [
+ create_file(
+ name = test_name + "/Hi.kt",
+ content = """
+package test
+
+fun hi(): String = "Hi!"
+""",
+ ),
+ "testinputs/Bar.java",
+ ],
+ deps = [
+ test_name + "_kt_dep",
+ test_name + "_java_dep",
+ ],
+ )
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ )
+ return test_name
+
+def _test_kt_jvm_library_no_deps():
+ test_name = "kt_jvm_library_no_deps_test"
+ create_file(
+ name = test_name + "/Salutations.kt",
+ content = """
+package test
+
+fun greeting(): String = "Hello World!"
+""",
+ )
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = [
+ "testinputs/Bar.java",
+ test_name + "/Salutations.kt",
+ ],
+ )
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ )
+ return test_name
+
+def _test_kt_jvm_library_with_only_common_srcs():
+ test_name = "kt_jvm_library_only_common_srcs_test"
+ create_file(
+ name = test_name + "/Salutations.kt",
+ content = """
+package test
+
+fun greeting(): String = "Hello World!"
+""",
+ )
+ kt_jvm_library(
+ name = test_name + "_tut",
+ common_srcs = [
+ test_name + "/Salutations.kt",
+ ],
+ )
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ )
+ return test_name
+
+def _test_kt_jvm_library_no_java_srcs():
+ test_name = "kt_jvm_library_no_java_srcs_test"
+ create_file(
+ name = test_name + "/Salutations.kt",
+ content = """
+package test
+
+fun greeting(): String = "Hello World!"
+""",
+ )
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = [
+ test_name + "/Salutations.kt",
+ ],
+ )
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ )
+ return test_name
+
+def _test_kt_jvm_library_no_kt_srcs():
+ test_name = "kt_jvm_library_no_kt_srcs_test"
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = [
+ "testinputs/Bar.java",
+ ],
+ )
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ )
+ return test_name
+
+def _test_kt_jvm_library_with_runtime_deps():
+ test_name = "kt_jvm_library_with_runtime_deps_test"
+ create_file(
+ name = test_name + "/Salutations.kt",
+ content = """
+package test
+
+fun greeting(): String = "Hello World!"
+""",
+ )
+ native.java_library(
+ name = test_name + "_dep",
+ srcs = [],
+ )
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = [
+ test_name + "/Salutations.kt",
+ ],
+ runtime_deps = [
+ test_name + "_dep",
+ ],
+ )
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ )
+ return test_name
+
+def _test_kt_jvm_library_with_proguard_specs():
+ test_name = "kt_jvm_library_with_proguard_specs_test"
+ create_file(
+ name = test_name + "/Salutations.kt",
+ content = """
+package test
+
+fun greeting(): String = "Hello World!"
+""",
+ )
+ create_file(
+ name = test_name + "/salutations.pgcfg",
+ content = """
+-keep class * {
+ *** greeting();
+}
+""",
+ )
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = [
+ test_name + "/Salutations.kt",
+ ],
+ proguard_specs = [
+ test_name + "/salutations.pgcfg",
+ ],
+ )
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ )
+ return test_name
+
+def _test_kt_jvm_library_with_resources():
+ test_name = "kt_jvm_library_with_resources_test"
+ create_file(
+ name = test_name + "/Salutations.kt",
+ content = """
+package test
+
+fun greeting(): String = "Hello World!"
+""",
+ )
+ create_file(
+ name = test_name + "/salutations.txt",
+ content = """
+Hi!
+""",
+ )
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = [
+ test_name + "/Salutations.kt",
+ "testinputs/Foo.java",
+ ],
+ resources = [
+ test_name + "/salutations.txt",
+ ],
+ )
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ )
+ return test_name
+
+def _test_kt_jvm_library_with_data():
+ test_name = "kt_jvm_library_with_data_test"
+ kt_jvm_lib_name = test_name + "_tut"
+
+ data_txt = create_file(
+ name = test_name + "data.txt",
+ content = """
+Hello World!
+""",
+ )
+
+ # Kotlin file
+ muchdata_kt = create_file(
+ name = test_name + "/MuchData.kt",
+ content = """
+package test
+
+import java.io.File
+
+fun greeting(): String = File("data.txt").readText()
+""",
+ )
+
+ kt_jvm_library(
+ name = kt_jvm_lib_name,
+ srcs = [muchdata_kt],
+ data = [data_txt],
+ )
+
+ _test(
+ name = test_name,
+ target_under_test = kt_jvm_lib_name,
+ expected = dict(
+ data = [
+ data_txt,
+ # libX.jar is always in data_runfiles as well - just append it.
+ "lib%s.jar" % kt_jvm_lib_name,
+ ],
+ ),
+ )
+ return test_name
+
+def _test_kt_jvm_library_with_plugin():
+ test_name = "kt_jvm_library_with_plugin_test"
+ create_file(
+ name = test_name + "/Salutations.kt",
+ content = """
+package test
+
+fun greeting(): String = "Hello World!"
+""",
+ )
+
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = [
+ test_name + "/Salutations.kt",
+ ],
+ # Need a working plugin so it can run for the test.
+ plugins = ["//bazel:auto_value_plugin"],
+ )
+
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ expected_processor_classes = ["com.google.auto.value.processor.AutoValueProcessor"],
+ expect_processor_classpath = True,
+ )
+ return test_name
+
+def _test_kt_jvm_library_no_kt_srcs_with_plugin():
+ test_name = "kt_jvm_library_no_kt_srcs_with_plugin_test"
+ native.java_plugin(
+ name = "%s_plugin" % test_name,
+ processor_class = test_name,
+ srcs = ["testinputs/Foo.java"], # induce processor_classpath
+ )
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = ["testinputs/Bar.java"],
+ plugins = [":%s_plugin" % test_name],
+ tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
+ )
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ expected_processor_classes = [test_name],
+ expect_processor_classpath = True,
+ )
+ return test_name
+
+def _test_kt_jvm_library_with_non_processor_plugin():
+ test_name = "kt_jvm_library_with_non_processor_plugin_test"
+ create_file(
+ name = test_name + "/Salutations.kt",
+ content = """
+package test
+
+fun greeting(): String = "Hello World!"
+""",
+ )
+
+ native.java_plugin(
+ # no processor_class
+ name = "%s_plugin" % test_name,
+ srcs = ["testinputs/Foo.java"],
+ )
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = [
+ test_name + "/Salutations.kt",
+ ],
+ plugins = [":%s_plugin" % test_name],
+ )
+
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ expected_processor_classes = [], # no processor class so no processing
+ expect_processor_classpath = True, # expect java_plugin's Jar
+ )
+ return test_name
+
+def _test_kt_jvm_library_with_exported_plugin():
+ test_name = "kt_jvm_library_with_exported_plugin_test"
+ create_file(
+ name = test_name + "/Salutations.kt",
+ content = """
+package test
+
+fun greeting(): String = "Hello World!"
+""",
+ )
+ native.java_plugin(
+ name = "%s_plugin" % test_name,
+ processor_class = test_name,
+ )
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = [
+ test_name + "/Salutations.kt",
+ ],
+ exported_plugins = [":%s_plugin" % test_name],
+ )
+
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ expected_exported_processor_classes = [test_name],
+ expected_processor_classes = [], # exported plugin should *not* run on _tut itself
+ )
+ return test_name
+
+def _test_kt_jvm_library_dep_on_exported_plugin():
+ test_name = "kt_jvm_library_dep_on_exported_plugin_test"
+ create_file(
+ name = test_name + "/Salutations.kt",
+ content = """
+package test
+
+fun greeting(): String = "Hello World!"
+""",
+ )
+
+ native.java_plugin(
+ name = "%s_plugin" % test_name,
+ processor_class = test_name,
+ srcs = ["testinputs/Foo.java"], # induce processor_classpath
+ )
+ kt_jvm_library(
+ name = "%s_exports_plugin" % test_name,
+ srcs = [test_name + "/Salutations.kt"],
+ exported_plugins = [":%s_plugin" % test_name],
+ )
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = [
+ test_name + "/Salutations.kt",
+ ],
+ deps = [":%s_exports_plugin" % test_name],
+ tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
+ )
+
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ expected_processor_classes = [test_name],
+ expect_processor_classpath = True,
+ )
+ return test_name
+
+def _test_kt_jvm_library_java_dep_on_exported_plugin():
+ test_name = "kt_jvm_library_java_dep_on_exported_plugin_test"
+ create_file(
+ name = test_name + "/Salutations.kt",
+ content = """
+package test
+
+fun greeting(): String = "Hello World!"
+""",
+ )
+ native.java_plugin(
+ name = "%s_plugin" % test_name,
+ processor_class = test_name,
+ srcs = ["testinputs/Foo.java"], # induce processor_classpath
+ )
+ native.java_library(
+ name = "%s_exports_plugin" % test_name,
+ exported_plugins = [":%s_plugin" % test_name],
+ )
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = [
+ test_name + "/Salutations.kt",
+ ],
+ deps = [":%s_exports_plugin" % test_name],
+ tags = ONLY_FOR_ANALYSIS_TEST_TAGS,
+ )
+
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ expected_processor_classes = [test_name],
+ expect_processor_classpath = True,
+ )
+ return test_name
+
+def _test_kt_jvm_library_with_exports():
+ test_name = "kt_jvm_library_with_exports_test"
+ create_file(
+ name = test_name + "/Salutations.kt",
+ content = """
+package test
+
+fun greeting(): String = "Hello World!"
+""",
+ )
+ kt_jvm_library(
+ name = test_name + "_exp",
+ srcs = [test_name + "/Salutations.kt"],
+ )
+ native.java_library(
+ name = test_name + "_javaexp",
+ srcs = ["testinputs/Foo.java"], # need file here so we get a Jar
+ )
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = [
+ test_name + "/Salutations.kt",
+ ],
+ exports = [
+ ":%s_exp" % test_name,
+ ":%s_javaexp" % test_name,
+ ],
+ )
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ expected_exports = [
+ ":%s_exp" % test_name,
+ ":%s_javaexp" % test_name,
+ ],
+ )
+ return test_name
+
+def _test_kt_jvm_library_with_export_that_exports_plugin():
+ test_name = "kt_jvm_library_with_export_that_exports_plugin_test"
+ create_file(
+ name = test_name + "/Salutations.kt",
+ content = """
+package test
+
+fun greeting(): String = "Hello World!"
+""",
+ )
+ native.java_plugin(
+ name = "%s_plugin" % test_name,
+ processor_class = test_name,
+ srcs = ["testinputs/Foo.java"], # induce processor_classpath
+ )
+ kt_jvm_library(
+ name = "%s_exports_plugin" % test_name,
+ exported_plugins = [":%s_plugin" % test_name],
+ srcs = [test_name + "/Salutations.kt"],
+ )
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = [
+ test_name + "/Salutations.kt",
+ ],
+ exports = [":%s_exports_plugin" % test_name],
+ )
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ expected_exports = [":%s_exports_plugin" % test_name],
+ expected_exported_processor_classes = [test_name],
+ )
+ return test_name
+
+def _test_kt_jvm_library_with_java_export_that_exports_plugin():
+ test_name = "kt_jvm_library_with_java_export_that_exports_plugin_test"
+ create_file(
+ name = test_name + "/Salutations.kt",
+ content = """
+package test
+
+fun greeting(): String = "Hello World!"
+""",
+ )
+ native.java_plugin(
+ name = "%s_plugin" % test_name,
+ processor_class = test_name,
+ srcs = ["testinputs/Foo.java"], # induce processor_classpath
+ )
+ native.java_library(
+ name = "%s_exports_plugin" % test_name,
+ exported_plugins = [":%s_plugin" % test_name],
+ )
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = [
+ test_name + "/Salutations.kt",
+ ],
+ exports = [":%s_exports_plugin" % test_name],
+ )
+ _test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ expected_exports = [], # _exports_plugin has no compile/runtime Jars
+ expected_exported_processor_classes = [test_name],
+ )
+ return test_name
+
+def _test_forbidden_nano_dep():
+ test_name = "kt_jvm_library_forbidden_nano_test"
+
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = [test_name + "/Ignored.kt"],
+ deps = [test_name + "_fake_nano_proto_lib"],
+ tags = [
+ "manual",
+ "nobuilder",
+ ],
+ )
+ native.java_library(
+ name = test_name + "_fake_nano_proto_lib",
+ srcs = [],
+ tags = ["nano_proto_library"],
+ )
+ assert_failure_test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ msg_contains = test_name + "_fake_nano_proto_lib : nano_proto_library",
+ )
+ return test_name
+
+def _test_forbidden_nano_export():
+ test_name = "kt_jvm_library_forbidden_nano_export_test"
+
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = [test_name + "/Ignored.kt"],
+ deps = [test_name + "_export"],
+ tags = [
+ "manual",
+ "nobuilder",
+ ],
+ )
+ native.java_library(
+ name = test_name + "_export",
+ exports = [test_name + "_fake_nano_proto_lib"],
+ )
+ native.java_library(
+ name = test_name + "_fake_nano_proto_lib",
+ srcs = [],
+ tags = ["nano_proto_library"],
+ )
+ assert_failure_test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ msg_contains = test_name + "_fake_nano_proto_lib : nano_proto_library",
+ )
+ return test_name
+
+def _test_kt_jvm_library_with_no_sources():
+ test_name = "kt_jvm_library_with_no_sources_test"
+
+ kt_jvm_library(
+ name = test_name + "_tut",
+ tags = [
+ "manual",
+ "nobuilder",
+ ],
+ )
+ tut_label = str(Label("//tests/analysis:kt_jvm_library_with_no_sources_test_tut"))
+ assert_failure_test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ msg_contains = "One of {srcs, common_srcs, exports, exported_plugins} of target " + tut_label + " must be non empty",
+ )
+ return test_name
+
+def _test_kt_jvm_library_coverage():
+ test_name = "kt_jvm_library_coverage"
+ kt_jvm_library(
+ name = test_name + "_tut",
+ srcs = ["testinputs/Srcs.kt"],
+ common_srcs = ["testinputs/CommonSrcs.kt"],
+ deps = [":{}_deps".format(test_name)],
+ runtime_deps = [":{}_runtime_deps".format(test_name)],
+ data = [":{}_data".format(test_name)],
+ resources = [":{}_resources".format(test_name)],
+ testonly = True,
+ )
+ native.java_library(
+ name = test_name + "_deps",
+ srcs = ["testinputs/Deps.java"],
+ testonly = True,
+ )
+ native.java_library(
+ name = test_name + "_runtime_deps",
+ srcs = ["testinputs/RuntimeDeps.java"],
+ testonly = True,
+ )
+ native.java_binary(
+ name = test_name + "_data",
+ main_class = "Data",
+ srcs = ["testinputs/Data.java"],
+ testonly = True,
+ )
+ native.java_binary(
+ name = test_name + "_resources",
+ main_class = "Resources",
+ srcs = ["testinputs/Resources.java"],
+ testonly = True,
+ )
+ _coverage_test(
+ name = test_name,
+ target_under_test = test_name + "_tut",
+ expected_instrumented_file_basenames = [
+ "Data.java",
+ "Deps.java",
+ "Resources.java",
+ "RuntimeDeps.java",
+ "Srcs.kt",
+ "CommonSrcs.kt",
+ ],
+ )
+ return test_name
+
+def test_suite(name):
+ native.test_suite(
+ name = name,
+ tests = [
+ _test_forbidden_nano_dep(),
+ _test_forbidden_nano_export(),
+ _test_kt_jvm_library_dep_on_exported_plugin(),
+ _test_kt_jvm_library_java_dep_on_exported_plugin(),
+ _test_kt_jvm_library_no_deps(),
+ _test_kt_jvm_library_no_java_srcs(),
+ _test_kt_jvm_library_no_kt_srcs(),
+ _test_kt_jvm_library_no_kt_srcs_with_plugin(),
+ _test_kt_jvm_library_with_data(),
+ _test_kt_jvm_library_with_deps(),
+ _test_kt_jvm_library_with_export_that_exports_plugin(),
+ _test_kt_jvm_library_with_exported_plugin(),
+ _test_kt_jvm_library_with_exports(),
+ _test_kt_jvm_library_with_java_export_that_exports_plugin(),
+ _test_kt_jvm_library_with_no_sources(),
+ _test_kt_jvm_library_with_non_processor_plugin(),
+ _test_kt_jvm_library_with_only_common_srcs(),
+ _test_kt_jvm_library_with_plugin(),
+ _test_kt_jvm_library_with_proguard_specs(),
+ _test_kt_jvm_library_with_resources(),
+ _test_kt_jvm_library_with_runtime_deps(),
+ _test_kt_jvm_library_coverage(),
+ ],
+ )
diff --git a/tests/analysis/testinputs/Bar.java b/tests/analysis/testinputs/Bar.java
new file mode 100644
index 0000000..c69a114
--- /dev/null
+++ b/tests/analysis/testinputs/Bar.java
@@ -0,0 +1,21 @@
+/*
+ * * 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.
+ */
+
+package testinputs;
+
+public class Bar {
+ public Bar() {}
+}
diff --git a/tests/analysis/testinputs/CommonSrcs.kt b/tests/analysis/testinputs/CommonSrcs.kt
new file mode 100644
index 0000000..932e704
--- /dev/null
+++ b/tests/analysis/testinputs/CommonSrcs.kt
@@ -0,0 +1,19 @@
+/*
+ * * 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.
+ */
+
+package testinputs
+
+class CommonSrcs
diff --git a/tests/analysis/testinputs/Data.java b/tests/analysis/testinputs/Data.java
new file mode 100644
index 0000000..d8e161f
--- /dev/null
+++ b/tests/analysis/testinputs/Data.java
@@ -0,0 +1,21 @@
+/*
+ * * 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.
+ */
+
+package testinputs;
+
+final class Data {
+ private Data() {}
+}
diff --git a/tests/analysis/testinputs/Deps.java b/tests/analysis/testinputs/Deps.java
new file mode 100644
index 0000000..7f5237f
--- /dev/null
+++ b/tests/analysis/testinputs/Deps.java
@@ -0,0 +1,21 @@
+/*
+ * * 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.
+ */
+
+package testinputs;
+
+final class Deps {
+ private Deps() {}
+}
diff --git a/tests/analysis/testinputs/Foo.java b/tests/analysis/testinputs/Foo.java
new file mode 100644
index 0000000..249811a
--- /dev/null
+++ b/tests/analysis/testinputs/Foo.java
@@ -0,0 +1,21 @@
+/*
+ * * 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.
+ */
+
+package testinputs;
+
+public class Foo {
+ public Foo() {}
+}
diff --git a/tests/analysis/testinputs/Resources.java b/tests/analysis/testinputs/Resources.java
new file mode 100644
index 0000000..cbf6e7c
--- /dev/null
+++ b/tests/analysis/testinputs/Resources.java
@@ -0,0 +1,21 @@
+/*
+ * * 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.
+ */
+
+package testinputs;
+
+final class Resources {
+ private Resources() {}
+}
diff --git a/tests/analysis/testinputs/RuntimeDeps.java b/tests/analysis/testinputs/RuntimeDeps.java
new file mode 100644
index 0000000..5515a7a
--- /dev/null
+++ b/tests/analysis/testinputs/RuntimeDeps.java
@@ -0,0 +1,21 @@
+/*
+ * * 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.
+ */
+
+package testinputs;
+
+final class RuntimeDeps {
+ private RuntimeDeps() {}
+}
diff --git a/tests/analysis/testinputs/Srcs.kt b/tests/analysis/testinputs/Srcs.kt
new file mode 100644
index 0000000..89ca40c
--- /dev/null
+++ b/tests/analysis/testinputs/Srcs.kt
@@ -0,0 +1,19 @@
+/*
+ * * 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.
+ */
+
+package testinputs
+
+class Srcs
diff --git a/tests/analysis/util.bzl b/tests/analysis/util.bzl
new file mode 100644
index 0000000..cec0cc3
--- /dev/null
+++ b/tests/analysis/util.bzl
@@ -0,0 +1,97 @@
+# 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.
+
+"""Some utils"""
+
+# Mark targets that's aren't expected to build, but are needed for analysis test assertions.
+ONLY_FOR_ANALYSIS_TEST_TAGS = ["manual", "nobuilder", "only_for_analysis_test"]
+
+def create_file(name, content):
+ if content.startswith("\n"):
+ content = content[1:-1]
+
+ native.genrule(
+ name = "gen_" + name,
+ outs = [name],
+ cmd = """
+cat > $@ <<EOF
+%s
+EOF
+""" % content,
+ )
+
+ return name
+
+def _create_dir_impl(ctx):
+ dir = ctx.actions.declare_directory(ctx.attr.name)
+ if ctx.files.srcs:
+ ctx.actions.run_shell(
+ command = "mkdir -p {0} && cp {1} {0}".format(
+ dir.path + "/" + ctx.attr.subdir,
+ " ".join([s.path for s in ctx.files.srcs]),
+ ),
+ inputs = ctx.files.srcs,
+ outputs = [dir],
+ )
+ else:
+ ctx.actions.run_shell(
+ command = "mkdir -p {0}".format(
+ dir.path + "/" + ctx.attr.subdir,
+ ),
+ inputs = ctx.files.srcs,
+ outputs = [dir],
+ )
+ return [DefaultInfo(files = depset([dir]))]
+
+_create_dir = rule(
+ implementation = _create_dir_impl,
+ attrs = dict(
+ subdir = attr.string(),
+ srcs = attr.label_list(allow_files = True),
+ ),
+)
+
+def create_dir(name, subdir, srcs):
+ _create_dir(
+ name = name,
+ subdir = subdir,
+ srcs = srcs,
+ )
+ return name
+
+def get_action_arg(actions, mnemonic, arg_name):
+ """Get a named arg from a specific action
+
+ Args:
+ actions: [List[Action]]
+ mnemonic: [string] Identify the action whose args to search
+ arg_name: [string]
+
+ Returns:
+ [Optional[string]] The arg value, or None if it couldn't be found
+ """
+ menmonic_actions = [a for a in actions if a.mnemonic == mnemonic]
+ if len(menmonic_actions) == 0:
+ return None
+ elif len(menmonic_actions) > 1:
+ fail("Expected a single '%s' action" % mnemonic)
+
+ mnemonic_action = menmonic_actions[0]
+ arg_values = [a for a in mnemonic_action.argv if a.startswith(arg_name)]
+ if len(arg_values) == 0:
+ return None
+ elif len(arg_values) > 1:
+ fail("Expected a single '%s' arg" % arg_name)
+
+ return arg_values[0][len(arg_name):]
diff --git a/tests/jvm/java/beer/BUILD b/tests/jvm/java/beer/BUILD
new file mode 100644
index 0000000..9a50474
--- /dev/null
+++ b/tests/jvm/java/beer/BUILD
@@ -0,0 +1,45 @@
+# 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("//kotlin:rules.bzl", "kt_jvm_library", "kt_jvm_test")
+
+licenses(["notice"])
+
+kt_jvm_library(
+ name = "beer_lib",
+ srcs = ["Beer.kt"],
+ deps = [
+ "@dagger",
+ "@maven//:javax_inject_jsr330_api",
+ ],
+)
+
+kt_jvm_test(
+ name = "beer",
+ main_class = "beer.BeerKt",
+ tags = ["darwin_x86_64_compatible"],
+ runtime_deps = [":beer_lib"],
+)
+
+# Regression test for b/123767247
+sh_test(
+ name = "build_data_test",
+ srcs = ["build_data_test.sh"],
+ data = [
+ ":libbeer_lib.jar",
+ ],
+ env = {
+ "TEST_JAR": "$(location :libbeer_lib.jar)",
+ },
+)
diff --git a/tests/jvm/java/beer/Beer.kt b/tests/jvm/java/beer/Beer.kt
new file mode 100644
index 0000000..5bac323
--- /dev/null
+++ b/tests/jvm/java/beer/Beer.kt
@@ -0,0 +1,186 @@
+/*
+ * * 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.
+ */
+
+package beer
+
+import dagger.Binds
+import dagger.Component
+import dagger.Lazy
+import dagger.Module
+import dagger.Provides
+import javax.inject.Inject
+import javax.inject.Singleton
+
+interface Grains {
+ val name: String
+}
+
+interface Hops {
+ val name: String
+}
+
+interface Yeast {
+ val name: String
+}
+
+interface Kettle {
+ fun steep()
+ fun heat()
+ fun boil()
+ fun cool()
+ fun ferment()
+ fun addGrains(grains: Grains)
+ fun addHops(hops: Hops)
+ fun addYeast(yeast: Yeast)
+ val isBoiling: Boolean
+ val hasCooled: Boolean
+ val isDone: Boolean
+}
+
+interface Storage {
+ fun store()
+}
+
+class PilsnerMalt
+@Inject constructor() : Grains {
+ override val name get() = "Pilsner Malt"
+}
+
+class Spalt
+@Inject constructor() : Hops {
+ override val name get() = "Spalt"
+}
+
+class Wyeast
+@Inject constructor() : Yeast {
+ override val name get() = "Wyeast 2565 Kölsch"
+}
+
+class BrewPot : Kettle {
+ var boiling: Boolean = false
+ var cool: Boolean = true
+ var done: Boolean = false
+
+ override fun addGrains(grains: Grains) {
+ println("Adding grains: " + grains.name)
+ }
+
+ override fun steep() {
+ println("=> Steeping")
+ }
+
+ override fun heat() {
+ println("=> Heating")
+ this.cool = false
+ }
+
+ override fun boil() {
+ println("=> Boiling")
+ this.boiling = true
+ }
+
+ override fun cool() {
+ println("=> Cooling")
+ this.boiling = false
+ this.cool = true
+ }
+
+ override fun addHops(hops: Hops) {
+ println("Adding hops: " + hops.name)
+ }
+
+ override fun ferment() {
+ println("=> Fermenting")
+ this.done = true
+ }
+
+ override fun addYeast(yeast: Yeast) {
+ println("Adding yeast: " + yeast.name)
+ }
+
+ override val isBoiling get() = boiling
+ override val hasCooled get() = cool
+ override val isDone get() = done
+}
+
+class Bottler
+@Inject constructor(
+ private val kettle: Kettle
+) : Storage {
+ override fun store() {
+ if (kettle.isDone) {
+ println("=> bottling")
+ }
+ }
+}
+
+class BeerBrewer
+@Inject constructor(
+ private val kettle: Lazy<Kettle>,
+ private val bottler: Bottler,
+ private val grains: Grains,
+ private val hops: Hops,
+ private val yeast: Yeast
+) {
+ fun brew() {
+ kettle.get().apply {
+ addGrains(grains)
+ steep()
+ heat()
+ boil()
+ if (isBoiling) addHops(hops)
+ cool()
+ if (hasCooled) addYeast(yeast)
+ ferment()
+ }
+ bottler.store()
+ }
+}
+
+@Module
+abstract class CommercialEquipmentModule {
+ @Binds
+ abstract fun provideStorage(storage: Bottler): Storage
+}
+
+@Module(includes = [CommercialEquipmentModule::class])
+class BrewingEquipmentModule {
+ @Provides @Singleton
+ fun provideKettle(): Kettle = BrewPot()
+}
+
+@Module
+interface KolschRecipeModule {
+ @Binds
+ fun bindGrains(grains: PilsnerMalt): Grains
+
+ @Binds
+ fun bindHops(hops: Spalt): Hops
+
+ @Binds
+ fun bindYeast(yeast: Wyeast): Yeast
+}
+
+@Singleton
+@Component(modules = [BrewingEquipmentModule::class, KolschRecipeModule::class])
+interface Brewery {
+ fun brewery(): BeerBrewer
+}
+
+fun main(args: Array<String>) {
+ val beer = DaggerBrewery.builder().build()
+ beer.brewery().brew()
+}
diff --git a/tests/jvm/java/beer/build_data_test.sh b/tests/jvm/java/beer/build_data_test.sh
new file mode 100755
index 0000000..c0c9084
--- /dev/null
+++ b/tests/jvm/java/beer/build_data_test.sh
@@ -0,0 +1,25 @@
+#!/bin/bash -eu
+# 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.
+
+
+# Assert expected files exist
+if ! unzip -l "$TEST_JAR" | grep "Kettle.class"; then
+ exit 1
+fi
+
+# Assert build data is stripped
+if unzip -l "$TEST_JAR" | grep "build-data.properties"; then
+ exit 1
+fi
diff --git a/tests/jvm/java/functions/BUILD b/tests/jvm/java/functions/BUILD
new file mode 100644
index 0000000..aa571fe
--- /dev/null
+++ b/tests/jvm/java/functions/BUILD
@@ -0,0 +1,96 @@
+# 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.
+
+# This package tests importing extension functions.
+load("//kotlin:rules.bzl", "kt_jvm_import", "kt_jvm_library")
+
+licenses(["notice"])
+
+kt_jvm_library(
+ name = "car_demo_src_lib",
+ srcs = ["CarDemo.kt"],
+ deps = [
+ "//tests/jvm/java/functions/car:car_lib",
+ ],
+)
+
+# This binary is built from source and shouldn't have any issues loading functions.
+java_test(
+ name = "car_src_demo",
+ main_class = "functions.CarDemo",
+ tags = ["darwin_x86_64_compatible"],
+ runtime_deps = [
+ ":car_demo_src_lib",
+ ],
+)
+
+java_import(
+ name = "car-jar",
+ jars = ["//tests/jvm/java/functions/car:car_lib-jar"],
+)
+
+kt_jvm_library(
+ name = "car_demo_jar_lib",
+ srcs = ["CarDemo.kt"],
+ deps = [
+ ":car-jar",
+ ],
+)
+
+# This binary includes extension functions defined in an separate jar file, which
+# may be problematic if the metadata is stripped by ijar.
+java_test(
+ name = "car_jar_demo",
+ main_class = "functions.CarDemo",
+ tags = ["darwin_x86_64_compatible"],
+ runtime_deps = [
+ ":car_demo_jar_lib",
+ "@kotlinc//:kotlin_stdlib",
+ ],
+)
+
+kt_jvm_import(
+ name = "car-inline-jar",
+ jars = [
+ "//tests/jvm/java/functions/car:car_inline_lib-jar",
+ "//tests/jvm/java/functions/car:car_extra_lib-jar",
+ ],
+ deps = [
+ ":car-jar",
+ ],
+)
+
+kt_jvm_library(
+ name = "car_demo_inline_lib",
+ srcs = ["CarInlineDemo.kt"],
+ deps = [
+ ":car-inline-jar",
+ ":car-jar",
+ ],
+)
+
+# This binary includes inline functions, imported from a jar file using kt_jvm_import.
+# Inlined functions cannot be imported using java_import, since ijar strips out functionality.
+java_test(
+ name = "car_inline_demo",
+ main_class = "functions.CarInlineDemo",
+ tags = [
+ "darwin_x86_64_compatible",
+ "nozapfhahn",
+ ],
+ runtime_deps = [
+ ":car_demo_inline_lib",
+ "@kotlinc//:kotlin_stdlib",
+ ],
+)
diff --git a/tests/jvm/java/functions/CarDemo.kt b/tests/jvm/java/functions/CarDemo.kt
new file mode 100644
index 0000000..d7b2d0f
--- /dev/null
+++ b/tests/jvm/java/functions/CarDemo.kt
@@ -0,0 +1,33 @@
+/*
+ * * 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.
+ */
+
+package functions
+
+import functions.car.Car
+import functions.car.briefName
+import functions.car.specificName
+import functions.car.abbrName
+
+object CarDemo {
+
+ @JvmStatic
+ fun main(args: Array<String>) {
+ var car: Car = Car("Honda", "Civic", 2001)
+ println("brief: ${car.briefName()}")
+ println("specific: ${car.specificName()}")
+ println("abbr: ${car.abbrName()}")
+ }
+}
diff --git a/tests/jvm/java/functions/CarInlineDemo.kt b/tests/jvm/java/functions/CarInlineDemo.kt
new file mode 100644
index 0000000..c18daff
--- /dev/null
+++ b/tests/jvm/java/functions/CarInlineDemo.kt
@@ -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.
+ */
+
+package functions
+
+import functions.car.Car
+import functions.car.abbrName
+import functions.car.briefName
+import functions.car.customName
+import functions.car.reversedName
+import functions.car.specificName
+
+object CarInlineDemo {
+
+ @JvmStatic
+ fun main(args: Array<String>) {
+ var car: Car = Car("Honda", "Civic", 2001)
+ println("brief: ${car.briefName()}")
+ println("specific: ${car.specificName()}")
+ println("abbr: ${car.abbrName()}")
+ println("reversed: ${car.reversedName()}")
+ val custom: String = car.customName() { year: Int -> year.toString() }
+ println("custom: $custom")
+ }
+}
diff --git a/tests/jvm/java/functions/car/BUILD b/tests/jvm/java/functions/car/BUILD
new file mode 100644
index 0000000..81f0f43
--- /dev/null
+++ b/tests/jvm/java/functions/car/BUILD
@@ -0,0 +1,65 @@
+# 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("//kotlin:rules.bzl", "kt_jvm_library")
+
+package(default_visibility = ["//tests/jvm/java/functions:__subpackages__"])
+
+licenses(["notice"])
+
+# Make Jar files produced by helper targets visible to tests in parent package
+filegroup(
+ name = "car_lib-jar",
+ srcs = ["libcar_lib.jar"],
+)
+
+filegroup(
+ name = "car_inline_lib-jar",
+ srcs = ["libcar_inline_lib.jar"],
+)
+
+filegroup(
+ name = "car_extra_lib-jar",
+ srcs = ["libcar_extra_lib.jar"],
+)
+
+kt_jvm_library(
+ name = "car_lib",
+ srcs = [
+ "Car.kt",
+ "CarUtils.kt",
+ ],
+ deps = [
+ ],
+)
+
+kt_jvm_library(
+ name = "car_inline_lib",
+ srcs = [
+ "CarInlineUtils.kt",
+ ],
+ deps = [
+ ":car_lib",
+ ],
+)
+
+kt_jvm_library(
+ name = "car_extra_lib",
+ srcs = [
+ "CarExtraUtils.kt",
+ ],
+ deps = [
+ ":car_lib",
+ ],
+)
diff --git a/tests/jvm/java/functions/car/Car.kt b/tests/jvm/java/functions/car/Car.kt
new file mode 100644
index 0000000..8bdc445
--- /dev/null
+++ b/tests/jvm/java/functions/car/Car.kt
@@ -0,0 +1,23 @@
+/*
+ * * 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.
+ */
+
+package functions.car
+
+data class Car(val make: String, val model: String, val year: Int)
+
+fun Car.briefName(): String = "$make $model"
+
+fun Car.specificName(): String = "$year $make $model"
diff --git a/tests/jvm/java/functions/car/CarExtraUtils.kt b/tests/jvm/java/functions/car/CarExtraUtils.kt
new file mode 100644
index 0000000..7506694
--- /dev/null
+++ b/tests/jvm/java/functions/car/CarExtraUtils.kt
@@ -0,0 +1,19 @@
+/*
+ * * 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.
+ */
+
+package functions.car
+
+fun Car.reversedName(): String = "$model $make $year"
diff --git a/tests/jvm/java/functions/car/CarInlineUtils.kt b/tests/jvm/java/functions/car/CarInlineUtils.kt
new file mode 100644
index 0000000..f55775e
--- /dev/null
+++ b/tests/jvm/java/functions/car/CarInlineUtils.kt
@@ -0,0 +1,19 @@
+/*
+ * * 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.
+ */
+
+package functions.car
+
+inline fun Car.customName(formatYear: (Int) -> String): String = "${formatYear(year)} $make $model"
diff --git a/tests/jvm/java/functions/car/CarUtils.kt b/tests/jvm/java/functions/car/CarUtils.kt
new file mode 100644
index 0000000..26ac21b
--- /dev/null
+++ b/tests/jvm/java/functions/car/CarUtils.kt
@@ -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.
+ */
+
+package functions.car
+
+fun Car.abbrName(): String {
+ val shortYear: String = year.rem(100).toString().padStart(2, '0')
+ return "'$shortYear $make $model"
+}
diff --git a/tests/jvm/java/ijar/BUILD b/tests/jvm/java/ijar/BUILD
new file mode 100644
index 0000000..d742e75
--- /dev/null
+++ b/tests/jvm/java/ijar/BUILD
@@ -0,0 +1,120 @@
+# 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("//kotlin:rules.bzl", "kt_jvm_library")
+
+licenses(["notice"])
+
+package(default_testonly = 1)
+
+java_test(
+ name = "ijar",
+ main_class = "ijar.MainKt",
+ runtime_deps = [":main"],
+)
+
+java_test(
+ name = "suspense",
+ test_class = "ijar.SuspendTest",
+ runtime_deps = [":SuspendTest"],
+)
+
+kt_jvm_library(
+ name = "inline",
+ srcs = [
+ "InlineCapture.kt",
+ "InlineInnerClass.kt",
+ "ReifiedInline.kt",
+ ],
+)
+
+# Compiling this file by itself triggers synthetic methods needed when compiling
+# dependants. These methods carry annotations.
+kt_jvm_library(
+ name = "statics",
+ srcs = ["JvmStatics.kt"],
+)
+
+kt_jvm_library(
+ name = "main",
+ srcs = ["Main.kt"],
+ deps = [
+ ":inline",
+ ":statics",
+ ],
+)
+
+kt_jvm_library(
+ name = "inlined_suspense",
+ srcs = ["DoubleInline.kt"],
+)
+
+kt_jvm_library(
+ name = "SuspendTest",
+ srcs = ["SuspendTest.kt"],
+ deps = [
+ ":inlined_suspense",
+ "@maven//:com_google_truth_truth",
+ "@maven//:junit_junit",
+ ],
+)
+
+java_library(
+ name = "SamInJava",
+ srcs = ["SamInJava.java"],
+)
+
+kt_jvm_library(
+ name = "SamExt",
+ srcs = ["SamExt.kt"],
+ deps = [
+ ":SamInJava",
+ ],
+)
+
+kt_jvm_library(
+ name = "SamExtUser",
+ srcs = ["SamExtUser.kt"],
+ deps = [
+ ":SamExt",
+ ":SamInJava",
+ ],
+)
+
+java_test(
+ name = "inlinedSamExt",
+ main_class = "ijar.SamExtUserKt",
+ runtime_deps = [
+ ":SamExtUser",
+ ],
+)
+
+kt_jvm_library(
+ name = "InlineWhenMapping",
+ srcs = ["InlineWhenMapping.kt"],
+)
+
+kt_jvm_library(
+ name = "InlineWhenMappingUser",
+ srcs = ["InlineWhenMappingUser.kt"],
+ deps = [":InlineWhenMapping"],
+)
+
+java_test(
+ name = "inlineWhenMapping",
+ main_class = "ijar.InlineWhenMappingUserKt",
+ runtime_deps = [
+ ":InlineWhenMappingUser",
+ ],
+)
diff --git a/tests/jvm/java/ijar/DoubleInline.kt b/tests/jvm/java/ijar/DoubleInline.kt
new file mode 100644
index 0000000..fd2d89b
--- /dev/null
+++ b/tests/jvm/java/ijar/DoubleInline.kt
@@ -0,0 +1,35 @@
+/*
+ * * 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.
+ */
+
+package ijar
+
+/**
+ * Regression test for b/143465893: inlining this function requires access to the inner class
+ * used by the inlined helper [makeAppender], which uses suspend functions.
+ */
+suspend inline fun doubleInline(also: String, crossinline init: suspend () -> String): String {
+ return makeAppender { init() }.apply(also)
+}
+
+inline fun makeAppender(crossinline init: suspend () -> String): Suspended<String> {
+ return object : Suspended<String> {
+ override suspend fun apply(toAppend: String) = init() + toAppend
+ }
+}
+
+interface Suspended<T> {
+ suspend fun apply(input: T): T
+}
diff --git a/tests/jvm/java/ijar/InlineCapture.kt b/tests/jvm/java/ijar/InlineCapture.kt
new file mode 100644
index 0000000..63ce284
--- /dev/null
+++ b/tests/jvm/java/ijar/InlineCapture.kt
@@ -0,0 +1,27 @@
+/*
+ * * 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.
+ */
+
+package ijar
+
+// Regression test for https://youtrack.jetbrains.net/issue/KT-33604
+fun inlineCapture(s: String): String {
+ return with(StringBuilder()) {
+ val o = object {
+ override fun toString() = s
+ }
+ append(o)
+ }.toString()
+}
diff --git a/tests/jvm/java/ijar/InlineInnerClass.kt b/tests/jvm/java/ijar/InlineInnerClass.kt
new file mode 100644
index 0000000..d12df05
--- /dev/null
+++ b/tests/jvm/java/ijar/InlineInnerClass.kt
@@ -0,0 +1,35 @@
+/*
+ * * 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.
+ */
+
+package ijar
+
+import java.util.function.Function
+
+// kotlinc requires the anonymous inner class of this function to be on the classpath in order to
+// inline this function.
+inline fun appender(append: String): Function<String, String> {
+ return object : Function<String, String> {
+ override fun apply(arg: String) = arg + append
+ }
+}
+
+// Additional regression test for https://youtrack.jetbrains.net/issue/KT-29471
+inline fun appender(crossinline init: () -> String): Function<String, String> {
+ return object : Function<String, String> {
+ private val base = init()
+ override fun apply(arg: String) = base + arg
+ }
+}
diff --git a/tests/jvm/java/ijar/InlineWhenMapping.kt b/tests/jvm/java/ijar/InlineWhenMapping.kt
new file mode 100644
index 0000000..ba96d1d
--- /dev/null
+++ b/tests/jvm/java/ijar/InlineWhenMapping.kt
@@ -0,0 +1,21 @@
+/*
+ * * 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.
+ */
+
+package ijar
+
+enum class MyEnum { A }
+
+inline fun <reified T> useWhenMapping(t: T, myE: MyEnum) = when (myE) { MyEnum.A -> t }
diff --git a/tests/jvm/java/ijar/InlineWhenMappingUser.kt b/tests/jvm/java/ijar/InlineWhenMappingUser.kt
new file mode 100644
index 0000000..1954039
--- /dev/null
+++ b/tests/jvm/java/ijar/InlineWhenMappingUser.kt
@@ -0,0 +1,21 @@
+/*
+ * * 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.
+ */
+
+package ijar
+
+fun main() {
+ println(useWhenMapping("OK", MyEnum.A))
+}
diff --git a/tests/jvm/java/ijar/JvmStatics.kt b/tests/jvm/java/ijar/JvmStatics.kt
new file mode 100644
index 0000000..deb14af
--- /dev/null
+++ b/tests/jvm/java/ijar/JvmStatics.kt
@@ -0,0 +1,29 @@
+/*
+ * * 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.
+ */
+
+package ijar
+
+object JvmStatics {
+
+ @JvmStatic
+ val something: String by lazy { "something" }
+
+ // @JvmStatic annotation ends up on synthetic companion method we need to preserve
+ @JvmStatic
+ fun saySomething(): Unit {
+ println("${something}?")
+ }
+}
diff --git a/tests/jvm/java/ijar/Main.kt b/tests/jvm/java/ijar/Main.kt
new file mode 100644
index 0000000..4457731
--- /dev/null
+++ b/tests/jvm/java/ijar/Main.kt
@@ -0,0 +1,25 @@
+/*
+ * * 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.
+ */
+
+package ijar
+
+fun main(args: Array<String>) {
+ JvmStatics.saySomething()
+ inlineMe<JvmStatics>()
+ println(appender("world").apply("hello "))
+ println(appender { "world" }.apply(", hello!"))
+ println(inlineCapture("bye"))
+}
diff --git a/tests/jvm/java/ijar/ReifiedInline.kt b/tests/jvm/java/ijar/ReifiedInline.kt
new file mode 100644
index 0000000..d22d90f
--- /dev/null
+++ b/tests/jvm/java/ijar/ReifiedInline.kt
@@ -0,0 +1,21 @@
+/*
+ * * 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.
+ */
+
+package ijar
+
+// Need this method's content to inline it successfully.
+// The reified type parameter causes this to be compiled to a private method.
+inline fun <reified T : Any> inlineMe() = println("inline ${T::class}!")
diff --git a/tests/jvm/java/ijar/SamExt.kt b/tests/jvm/java/ijar/SamExt.kt
new file mode 100644
index 0000000..b0a4f42
--- /dev/null
+++ b/tests/jvm/java/ijar/SamExt.kt
@@ -0,0 +1,20 @@
+/*
+ * * 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.
+ */
+
+package ijar
+
+inline fun <T, R> SamInJava<T>.map(crossinline transform: (T) -> R): SamInJava<R> =
+ fmap { SamInJava(transform(it)) }
diff --git a/tests/jvm/java/ijar/SamExtUser.kt b/tests/jvm/java/ijar/SamExtUser.kt
new file mode 100644
index 0000000..603c4a2
--- /dev/null
+++ b/tests/jvm/java/ijar/SamExtUser.kt
@@ -0,0 +1,21 @@
+/*
+ * * 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.
+ */
+
+package ijar
+
+fun main() {
+ println(SamInJava("OK").map { it })
+}
diff --git a/tests/jvm/java/ijar/SamInJava.java b/tests/jvm/java/ijar/SamInJava.java
new file mode 100644
index 0000000..6589224
--- /dev/null
+++ b/tests/jvm/java/ijar/SamInJava.java
@@ -0,0 +1,35 @@
+/*
+ * * 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.
+ */
+
+package ijar;
+
+public class SamInJava<T> {
+ public final <R> SamInJava<R> fmap(
+ Function<? super T, ? extends SamInJava<? extends R>> mapper) {
+ return new SamInJava<R>(mapper.run(value).value);
+ }
+
+ public SamInJava(T x) {
+ this.value = x;
+ }
+
+ public final T value;
+
+ @FunctionalInterface
+ public interface Function<T, R> {
+ R run(T arg);
+ }
+}
diff --git a/tests/jvm/java/ijar/SuspendTest.kt b/tests/jvm/java/ijar/SuspendTest.kt
new file mode 100644
index 0000000..c4f9721
--- /dev/null
+++ b/tests/jvm/java/ijar/SuspendTest.kt
@@ -0,0 +1,46 @@
+/*
+ * * 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.
+ */
+
+package ijar
+
+import com.google.common.truth.Truth.assertThat
+import kotlin.coroutines.Continuation
+import kotlin.coroutines.EmptyCoroutineContext
+import kotlin.coroutines.createCoroutine
+import kotlin.coroutines.startCoroutine
+import kotlin.coroutines.resume
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+/** Tests exercising suspend functions. */
+@RunWith(JUnit4::class)
+class SuspendTest {
+
+ /** Regression test for b/143465893. */
+ @Test
+ fun testSuspendDoubleInline() {
+ suspend fun doubleInlineExample(): String {
+ return doubleInline("b") { "a" }
+ }
+
+ // Run doubleInlineExample avoiding dependency on kotlinx.coroutines
+ var result: Result<String>? = null
+ ::doubleInlineExample.startCoroutine(Continuation(EmptyCoroutineContext, { r -> result = r }))
+
+ assertThat(result!!.getOrThrow()).isEqualTo("ab")
+ }
+}
diff --git a/tests/jvm/java/internal/BUILD b/tests/jvm/java/internal/BUILD
new file mode 100644
index 0000000..7bf2d8e
--- /dev/null
+++ b/tests/jvm/java/internal/BUILD
@@ -0,0 +1,49 @@
+# 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("//kotlin:rules.bzl", "kt_jvm_library", "kt_jvm_test")
+
+licenses(["notice"])
+
+kt_jvm_library(
+ name = "internal",
+ srcs = ["Internal.kt"],
+)
+
+kt_jvm_test(
+ name = "InternalTest",
+ srcs = ["InternalTest.kt"],
+ deps = [
+ ":internal",
+ "@maven//:com_google_truth_truth",
+ "@maven//:junit_junit",
+ ],
+)
+
+kt_jvm_library(
+ name = "internal_test_separate",
+ testonly = 1,
+ srcs = ["InternalTest.kt"],
+ deps = [
+ ":internal",
+ "@maven//:com_google_truth_truth",
+ "@maven//:junit_junit",
+ ],
+)
+
+java_test(
+ name = "InternalTest_separate",
+ test_class = "internal.InternalTest",
+ runtime_deps = [":internal_test_separate"],
+)
diff --git a/tests/jvm/java/internal/Internal.kt b/tests/jvm/java/internal/Internal.kt
new file mode 100644
index 0000000..64f345b
--- /dev/null
+++ b/tests/jvm/java/internal/Internal.kt
@@ -0,0 +1,25 @@
+/*
+ * * 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.
+ */
+
+package internal
+
+class InternalClass {
+ internal val value = "Hello World"
+ internal fun hello() = "Hello friend"
+ suspend internal fun helloDelayed() = "Hello friend"
+}
+
+internal fun internalFun(): String = "Hello World"
diff --git a/tests/jvm/java/internal/InternalTest.kt b/tests/jvm/java/internal/InternalTest.kt
new file mode 100644
index 0000000..aa9994f
--- /dev/null
+++ b/tests/jvm/java/internal/InternalTest.kt
@@ -0,0 +1,42 @@
+/*
+ * * 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.
+ */
+
+package internal
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class InternalTest {
+ @Test
+ fun testInternalClassFieldVisible() {
+ val internalClass = InternalClass()
+ assertThat(internalClass.value).isEqualTo("Hello World")
+ }
+
+ @Test
+ fun testInternalClassMethodVisible() {
+ val internalClass = InternalClass()
+ assertThat(internalClass.hello()).isEqualTo("Hello friend")
+ }
+
+ @Test
+ fun testInternalFunVisible() {
+ assertThat(internalFun()).isEqualTo("Hello World")
+ }
+}
diff --git a/tests/jvm/java/jni/BUILD b/tests/jvm/java/jni/BUILD
new file mode 100644
index 0000000..7225ef1
--- /dev/null
+++ b/tests/jvm/java/jni/BUILD
@@ -0,0 +1,92 @@
+# 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(
+ "//kotlin:rules.bzl",
+ "kt_jvm_library",
+ "kt_jvm_test",
+)
+
+package(default_testonly = 1)
+
+licenses(["notice"])
+
+kt_jvm_library(
+ name = "NativeApiKt",
+ srcs = ["NativeApi.kt"],
+ visibility = ["//tests:__subpackages__"],
+ runtime_deps = [":jni_NativeApi"],
+)
+
+java_library(
+ name = "NativeApiJava",
+ srcs = ["NativeApi.java"],
+ deps = [":libNativeApi.so"],
+)
+
+java_library(
+ name = "NativeApiJava-through_cc_lib",
+ srcs = ["NativeApi.java"],
+ deps = [":native_api_so"],
+)
+
+kt_jvm_library(
+ name = "NativeApiKt-through_cc_lib",
+ srcs = ["NativeApi.kt"],
+ runtime_deps = [":native_api_so"],
+)
+
+cc_library(
+ name = "native_api_so",
+ srcs = [":libNativeApi.so"],
+)
+
+cc_binary(
+ name = "libNativeApi.so",
+ linkshared = 1,
+ linkstatic = 1,
+ deps = [":jni_NativeApi"],
+)
+
+cc_library(
+ name = "jni_NativeApi",
+ srcs = ["jni_NativeApi.cc"],
+ hdrs = ["jni_NativeApi.h"], # manually generated with "javac -h NativeApi.java"
+ deps = ["@bazel_tools//tools/jdk:jni"],
+ alwayslink = 1,
+)
+
+[
+ kt_jvm_test(
+ name = "NativeApiTest_" + native_loader,
+ srcs = ["NativeApiTest.kt"],
+ args = args,
+ main_class = "jni.NativeApiTestKt",
+ deps = [
+ native_loader,
+ "@maven//:com_google_truth_truth",
+ "@maven//:junit_junit",
+ ],
+ )
+ for native_loader, args in {
+ "NativeApiJava": ["--load"],
+ "NativeApiJava-through_cc_lib": ["--load"],
+ "NativeApiKt-through_cc_lib": ["--load"],
+ }.items()
+]
+
+sh_test(
+ name = "jdk_check",
+ srcs = ["jdk_check.sh"],
+)
diff --git a/tests/jvm/java/jni/NativeApi.java b/tests/jvm/java/jni/NativeApi.java
new file mode 100644
index 0000000..79d3949
--- /dev/null
+++ b/tests/jvm/java/jni/NativeApi.java
@@ -0,0 +1,27 @@
+/*
+ * * 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.
+ */
+
+package jni;
+
+/**
+ * Java equivalent of {@code NativeApi.kt} to generate a .h file using javac -h. Do not compile this
+ * file and the Kotlin equivalent into the same binary, they would conflict.
+ */
+public class NativeApi {
+ public static native String hello(String name);
+
+ private NativeApi() {}
+}
diff --git a/tests/jvm/java/jni/NativeApi.kt b/tests/jvm/java/jni/NativeApi.kt
new file mode 100644
index 0000000..987ec04
--- /dev/null
+++ b/tests/jvm/java/jni/NativeApi.kt
@@ -0,0 +1,24 @@
+/*
+ * * 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:JvmName("NativeApi")
+
+package jni
+
+object NativeApi {
+ @JvmStatic
+ external fun hello(name: String): String
+}
diff --git a/tests/jvm/java/jni/NativeApiTest.kt b/tests/jvm/java/jni/NativeApiTest.kt
new file mode 100644
index 0000000..f33b379
--- /dev/null
+++ b/tests/jvm/java/jni/NativeApiTest.kt
@@ -0,0 +1,31 @@
+/*
+ * * 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.
+ */
+
+package jni
+
+import com.google.common.truth.Truth.assertThat
+
+/** Unit test for JNI function. */
+fun main(args: Array<String>) {
+ if (args.getOrNull(0) == "--load") {
+ System.loadLibrary("NativeApi") // loads libNativeApi.so
+ }
+
+ assertThat(NativeApi.hello("World")).isEqualTo("Hello, World")
+
+ assertThat(NativeApi.hello("0123456789".repeat(11) + "willbedropped"))
+ .isEqualTo("Hello, " + "0123456789".repeat(11) + "willbedrop")
+}
diff --git a/tests/jvm/java/jni/jdk_check.sh b/tests/jvm/java/jni/jdk_check.sh
new file mode 100755
index 0000000..b741899
--- /dev/null
+++ b/tests/jvm/java/jni/jdk_check.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# 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.
+
+
+if [[ $(type java) =~ /usr/local/buildtools/java/jdk/bin/java ]]; then
+ echo "Unexpected google JDK"
+ exit 1
+fi
diff --git a/tests/jvm/java/jni/jni_NativeApi.cc b/tests/jvm/java/jni/jni_NativeApi.cc
new file mode 100644
index 0000000..a0359ac
--- /dev/null
+++ b/tests/jvm/java/jni/jni_NativeApi.cc
@@ -0,0 +1,26 @@
+// 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.
+
+#include "jni_NativeApi.h"
+#include <string.h>
+
+JNIEXPORT jstring JNICALL Java_jni_NativeApi_hello
+ (JNIEnv *env, jclass clazz, jstring name) {
+ const char* str = env->GetStringUTFChars(name, 0);
+ char cap[128]; // simplified since this is demo code
+ strcpy(cap, "Hello, ");
+ strncpy(cap + 7, str, 120);
+ env->ReleaseStringUTFChars(name, str);
+ return env->NewStringUTF(cap);
+}
diff --git a/tests/jvm/java/jni/jni_NativeApi.h b/tests/jvm/java/jni/jni_NativeApi.h
new file mode 100644
index 0000000..a18afb9
--- /dev/null
+++ b/tests/jvm/java/jni/jni_NativeApi.h
@@ -0,0 +1,35 @@
+// 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.
+
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class jni_NativeApi */
+
+#ifndef _Included_jni_NativeApi
+#define _Included_jni_NativeApi
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: jni_NativeApi
+ * Method: hello
+ * Signature: (Ljava/lang/String;)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_jni_NativeApi_hello
+ (JNIEnv *, jclass, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/tests/jvm/java/junit/BUILD b/tests/jvm/java/junit/BUILD
new file mode 100644
index 0000000..af26b52
--- /dev/null
+++ b/tests/jvm/java/junit/BUILD
@@ -0,0 +1,59 @@
+# 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("//kotlin:rules.bzl", "kt_jvm_library", "kt_jvm_test")
+
+package(default_testonly = 1)
+
+licenses(["notice"])
+
+kt_jvm_library(
+ name = "junit",
+ srcs = glob(["*.kt"]),
+ deps = [
+ "@maven//:com_google_truth_truth",
+ "@maven//:junit_junit",
+ ],
+)
+
+# test_class inferred from test name (srcs irrelevant)
+kt_jvm_test(
+ name = "FooTest",
+ srcs = ["FooTest.kt"],
+ tags = ["darwin_x86_64_compatible"],
+ deps = [
+ "@maven//:com_google_truth_truth",
+ "@maven//:junit_junit",
+ ],
+)
+
+kt_jvm_test(
+ name = "FooTest_separate",
+ tags = ["darwin_x86_64_compatible"],
+ test_class = "junit.FooTest",
+ runtime_deps = [":junit"],
+)
+
+# test_class inferred from test name (srcs not needed)
+kt_jvm_test(
+ name = "BarTest",
+ tags = ["darwin_x86_64_compatible"],
+ runtime_deps = [":junit"],
+)
+
+java_test(
+ name = "SampleTest",
+ tags = ["darwin_x86_64_compatible"],
+ runtime_deps = [":junit"],
+)
diff --git a/tests/jvm/java/junit/BarTest.kt b/tests/jvm/java/junit/BarTest.kt
new file mode 100644
index 0000000..ceab8cc
--- /dev/null
+++ b/tests/jvm/java/junit/BarTest.kt
@@ -0,0 +1,31 @@
+/*
+ * * 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.
+ */
+
+package junit
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class BarTest {
+
+ @Test
+ fun testSomething() {
+ assertThat(false).isFalse()
+ }
+}
diff --git a/tests/jvm/java/junit/FooTest.kt b/tests/jvm/java/junit/FooTest.kt
new file mode 100644
index 0000000..78ddfea
--- /dev/null
+++ b/tests/jvm/java/junit/FooTest.kt
@@ -0,0 +1,31 @@
+/*
+ * * 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.
+ */
+
+package junit
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class FooTest {
+
+ @Test
+ fun testSomething() {
+ assertThat(true).isTrue()
+ }
+}
diff --git a/tests/jvm/java/junit/SampleTest.kt b/tests/jvm/java/junit/SampleTest.kt
new file mode 100644
index 0000000..24b6917
--- /dev/null
+++ b/tests/jvm/java/junit/SampleTest.kt
@@ -0,0 +1,35 @@
+/*
+ * * 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.
+ */
+
+package junit
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+public class SampleTest {
+ @Test
+ public fun tru() {
+ assertThat(true).isTrue()
+ }
+
+ @Test
+ public fun fls() {
+ assertThat(false).isFalse()
+ }
+}
diff --git a/tests/jvm/java/kapt/AP.java b/tests/jvm/java/kapt/AP.java
new file mode 100644
index 0000000..984a444
--- /dev/null
+++ b/tests/jvm/java/kapt/AP.java
@@ -0,0 +1,75 @@
+/*
+ * * 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.
+ */
+
+package kapt;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.auto.service.AutoService;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.util.Set;
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.Processor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+/** Simple test processor that numbered classes in rounds as specified in {@link Count}. */
+@AutoService(Processor.class)
+@SupportedAnnotationTypes("*")
+public class AP extends AbstractProcessor {
+
+ private volatile String prefix = "";
+
+ @Override
+ public synchronized void init(ProcessingEnvironment processingEnv) {
+ super.init(processingEnv);
+ prefix = processingEnv.getOptions().getOrDefault("kapt.AP.indexPrefix", "");
+ }
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latestSupported();
+ }
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ for (Element element : roundEnv.getElementsAnnotatedWith(Count.class)) {
+ Count c = element.getAnnotation(Count.class);
+ if (c.value() > 0) {
+ int next = c.value() - 1;
+ String simpleName = element.getSimpleName() + "_" + prefix + next;
+ try (OutputStream os =
+ processingEnv
+ .getFiler()
+ .createSourceFile("kapt." + simpleName, element)
+ .openOutputStream()) {
+ os.write(
+ String.format("package kapt; @Count(%d) class %s {}", next, simpleName)
+ .getBytes(UTF_8));
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/tests/jvm/java/kapt/APTest.kt b/tests/jvm/java/kapt/APTest.kt
new file mode 100644
index 0000000..cd1dfa6
--- /dev/null
+++ b/tests/jvm/java/kapt/APTest.kt
@@ -0,0 +1,60 @@
+/*
+ * * 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.
+ */
+
+package kapt
+
+import com.google.testing.compile.Compilation
+import com.google.testing.compile.CompilationSubject.assertThat
+import com.google.testing.compile.Compiler.javac
+import com.google.testing.compile.JavaFileObjects
+import javax.tools.JavaFileObject
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+/** Sample test for [AP] that uses `com.google.testing.compile` (b/199411692). */
+@RunWith(JUnit4::class)
+class APTest {
+ @Test
+ fun testKTest() {
+ // This is the stub file kapt generates for KTest.kt as of kotlinc 1.5.31, with the original
+ // Kotlin module name shortened.
+ // Alternatively our test could run kapt to get a fresh stub file, but on the other hand we
+ // can test with a particular stub file this way, which may be useful for some regression tests.
+ val testStub = JavaFileObjects.forSourceString(
+ /* fullyQualifiedName= */ "kapt.KTest",
+ """
+ |package kapt;
+
+ |import java.lang.System;
+
+ |@kotlin.Metadata(mv = {1, 5, 1}, k = 1, d1 = {"\u0000\f\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\b\u0007\u0018\u00002\u00020\u0001B\u0005\u00a2\u0006\u0002\u0010\u0002\u00a8\u0006\u0003"}, d2 = {"Lkapt/KTest;", "", "()V", "shortened.java.kapt_test_kapt"})
+ |@Count(value = 3, clazz = KTest_2_1_0.class)
+ |public final class KTest {
+ |
+ | public KTest() {
+ | super();
+ | }
+ |}
+ """.trimMargin()
+ )
+ val compilation: Compilation = javac().withProcessors(AP()).compile(testStub)
+ assertThat(compilation).succeededWithoutWarnings()
+ assertThat(compilation).generatedSourceFile("kapt.KTest_2")
+ assertThat(compilation).generatedSourceFile("kapt.KTest_2_1")
+ assertThat(compilation).generatedSourceFile("kapt.KTest_2_1_0")
+ }
+}
diff --git a/tests/jvm/java/kapt/BUILD b/tests/jvm/java/kapt/BUILD
new file mode 100644
index 0000000..43b893d
--- /dev/null
+++ b/tests/jvm/java/kapt/BUILD
@@ -0,0 +1,313 @@
+# 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(
+ "//kotlin:rules.bzl",
+ "kt_jvm_library",
+ "kt_jvm_test",
+)
+load("@bazel_skylib//rules:build_test.bzl", "build_test")
+
+licenses(["notice"])
+
+build_test(
+ name = "kapt_regressions",
+ tags = ["darwin_x86_64_compatible"],
+ targets = [
+ ":test_javac",
+ ":test_kapt",
+ ":test_javac",
+ ":test_javac_with_exported_plugin",
+ ":test_kapt_with_exported_plugin",
+ ":test_no_processors",
+ ":test_noop",
+ ":test_noop_processors_ignored",
+ ":test_processor_flags",
+ ":test_processor_with_data",
+ ":test_reference",
+ ":test_stubs",
+ ":test_direct_classpath",
+ ],
+)
+
+# Regression test for no processor outputs (b/79878966)
+# and running non-service processors (b/110540324)
+kt_jvm_library(
+ name = "test_noop",
+ srcs = ["Noop.kt"],
+ plugins = [
+ ":non_service_processor",
+ ],
+)
+
+kt_jvm_library(
+ name = "test_kapt",
+ srcs = [
+ "KTest.kt",
+ ],
+ plugins = [":AP"],
+ deps = [
+ ":anno",
+ ],
+)
+
+# Test support for -A processor flags (b/134963914).
+kt_jvm_library(
+ name = "test_processor_flags",
+ srcs = ["FlagTest.kt"],
+ javacopts = ["-Akapt.AP.indexPrefix=Gen"],
+ plugins = [":AP"],
+ deps = [":anno"],
+)
+
+# Skip kapt altogether when no plugin defines a processor (b/110540324).
+kt_jvm_library(
+ name = "test_no_processors",
+ srcs = [
+ "Noop.kt",
+ ],
+ plugins = [
+ ":ignored_failing_processor", # would fail if run
+ ],
+ deps = [
+ ":anno",
+ ],
+)
+
+# Skip plugins without processors, for consistency with how Blaze runs javac (b/110540324).
+kt_jvm_library(
+ name = "test_noop_processors_ignored",
+ srcs = [
+ "KTest.kt",
+ ],
+ plugins = [
+ ":AP",
+ ":ignored_failing_processor", # would fail if run
+ ],
+ deps = [
+ ":anno",
+ ],
+)
+
+# Use kapt to annotation-process a .java file
+kt_jvm_library(
+ name = "test_kapt_java",
+ srcs = [
+ "Noop.kt", # needed so kapt is used
+ "Test.java",
+ ],
+ plugins = [":AP"],
+ deps = [
+ ":anno",
+ ],
+)
+
+# No .kt sources: javac is used for annotation processing
+kt_jvm_library(
+ name = "test_javac",
+ srcs = ["Test.java"],
+ plugins = [":AP"],
+ deps = [
+ ":anno",
+ ],
+)
+
+# Test for java_library picking up exported_plugin from kt_jvm_library
+java_library(
+ name = "test_javac_with_exported_plugin",
+ srcs = ["Test.java"],
+ deps = [
+ ":anno_with_plugin",
+ ],
+)
+
+# Reference build with java_library
+java_library(
+ name = "test_reference",
+ srcs = ["Test.java"],
+ plugins = [":AP"],
+ deps = [
+ ":anno",
+ ],
+)
+
+# This target compiles repro code for b/118338417 and b/110373008. Since these are issues with the
+# kapt-generated .java stub files, which aren't currently used by the Kotlin build rules, this
+# target compiles, but we can manually inspect the stubs to see if issues were fixed.
+# TODO: Turn this into a dump test asserting the content of the generated stubs
+kt_jvm_library(
+ name = "test_stubs",
+ srcs = [
+ "InnerEnumImport.kt", # repro for https://youtrack.jetbrains.net/issue/KT-28220
+ "SealedClasses.kt", # repro for https://youtrack.jetbrains.net/issue/KT-29924
+ "StaticImport.kt", # Static* repro https://youtrack.jetbrains.net/issue/KT-25071 (fixed)
+ "StaticMethod.java",
+ ],
+ plugins = [":AP"],
+)
+
+java_plugin(
+ name = "AP",
+ generates_api = 1,
+ processor_class = "kapt.AP",
+ deps = [":AP_lib"],
+)
+
+java_library(
+ name = "AP_lib",
+ srcs = ["AP.java"],
+ deps = [
+ ":anno",
+ "//bazel:auto_service",
+ ],
+)
+
+# Processor that doesn't advertise itself to j.u.ServiceLoader (regression for b/110540324)
+java_plugin(
+ name = "non_service_processor",
+ srcs = ["NonServiceProcessor.java"],
+ processor_class = "kapt.NonServiceProcessor",
+)
+
+# Processor that would fail but doesn't declare processor_class and hence shouldn't run.
+java_plugin(
+ name = "ignored_failing_processor",
+ srcs = ["FailingProcessor.java"],
+ deps = [
+ "//bazel:auto_service",
+ ],
+)
+
+java_library(
+ name = "anno",
+ srcs = ["Count.java"],
+)
+
+kt_jvm_library(
+ name = "anno_with_plugin",
+ srcs = ["Count.java"],
+ exported_plugins = [":AP"],
+)
+
+kt_jvm_library(
+ name = "test_kapt_with_exported_plugin",
+ srcs = ["KTest.kt"],
+ deps = [
+ ":anno_with_plugin",
+ ],
+)
+
+# Regression test for b/199932860: processor with data dependency
+java_plugin(
+ name = "ProcessorWithData",
+ data = ["MakeHelperClass.java.template"],
+ processor_class = "kapt.ProcessorWithData",
+ deps = [":processor_with_data"],
+)
+
+kt_jvm_library(
+ name = "processor_with_data",
+ srcs = [
+ "MakeHelper.kt",
+ "ProcessorWithData.kt",
+ ],
+ deps = [
+ "//bazel:auto_service",
+ ],
+)
+
+kt_jvm_library(
+ name = "make_helper",
+ srcs = ["MakeHelper.kt"],
+ exported_plugins = [":ProcessorWithData"],
+)
+
+kt_jvm_library(
+ name = "test_processor_with_data",
+ srcs = ["TriggerHelper.kt"],
+ deps = [":make_helper"],
+)
+
+kt_jvm_library(
+ name = "generates_services",
+ srcs = ["GeneratesServices.kt"],
+ deps = [
+ "//bazel:auto_service",
+ ],
+)
+
+kt_jvm_test(
+ name = "GeneratesServicesTest",
+ srcs = ["GeneratesServicesTest.kt"],
+ tags = ["darwin_x86_64_compatible"],
+ deps = [
+ ":generates_services",
+ "@maven//:com_google_truth_truth",
+ "@maven//:junit_junit",
+ ],
+)
+
+kt_jvm_library(
+ name = "dagger_c",
+ testonly = 1,
+ srcs = ["DaggerC.kt"],
+ deps = [
+ "@maven//:javax_inject_jsr330_api",
+ ],
+)
+
+kt_jvm_library(
+ name = "dagger_b",
+ testonly = 1,
+ srcs = ["DaggerB.kt"],
+ deps = [
+ ":dagger_c",
+ "@maven//:javax_inject_jsr330_api",
+ ],
+)
+
+kt_jvm_library(
+ name = "dagger_a",
+ testonly = 1,
+ srcs = ["DaggerA.kt"],
+ deps = [
+ ":dagger_b",
+ ":dagger_c",
+ "@dagger",
+ ],
+)
+
+# Tests a scenario where Dagger generates code referencing indirect dependencies, which can confuse
+# Blaze's direct classpath optimization for running Turbine.
+kt_jvm_library(
+ name = "test_direct_classpath",
+ testonly = 1,
+ srcs = ["DaggerTopLevel.kt"],
+ deps = [
+ ":dagger_a",
+ ],
+)
+
+# Demonstrates a simple compile test that uses Kotlin kapt stubs (b/199411692)
+kt_jvm_test(
+ name = "APTest",
+ srcs = ["APTest.kt"],
+ tags = ["darwin_x86_64_compatible"],
+ deps = [
+ ":AP_lib",
+ "@maven//:com_google_testing_compile_compile_testing",
+ "@maven//:com_google_truth_truth",
+ "@maven//:junit_junit",
+ ],
+)
diff --git a/tests/jvm/java/kapt/Count.java b/tests/jvm/java/kapt/Count.java
new file mode 100644
index 0000000..17332db
--- /dev/null
+++ b/tests/jvm/java/kapt/Count.java
@@ -0,0 +1,23 @@
+/*
+ * * 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.
+ */
+
+package kapt;
+
+/** Annotation used by {@link AP}. */
+public @interface Count {
+ int value() default 0;
+ Class<?> clazz() default Object.class;
+}
diff --git a/tests/jvm/java/kapt/DaggerA.kt b/tests/jvm/java/kapt/DaggerA.kt
new file mode 100644
index 0000000..ee319bd
--- /dev/null
+++ b/tests/jvm/java/kapt/DaggerA.kt
@@ -0,0 +1,32 @@
+/*
+ * * 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.
+ */
+
+package kapt
+
+import dagger.Component
+import javax.inject.Singleton
+
+class DaggerA {
+ @Singleton
+ @Component
+ public interface Thing {
+ fun b(): DaggerB
+ }
+
+ fun main() {
+ DaggerDaggerA_Thing.builder().build().b()
+ }
+}
diff --git a/tests/jvm/java/kapt/DaggerB.kt b/tests/jvm/java/kapt/DaggerB.kt
new file mode 100644
index 0000000..f487b8a
--- /dev/null
+++ b/tests/jvm/java/kapt/DaggerB.kt
@@ -0,0 +1,21 @@
+/*
+ * * 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.
+ */
+
+package kapt
+
+import javax.inject.Inject
+
+public class DaggerB @Inject public constructor(c: DaggerC) {}
diff --git a/tests/jvm/java/kapt/DaggerC.kt b/tests/jvm/java/kapt/DaggerC.kt
new file mode 100644
index 0000000..6a9dd3d
--- /dev/null
+++ b/tests/jvm/java/kapt/DaggerC.kt
@@ -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.
+ */
+
+package kapt
+
+import javax.inject.Inject
+
+public class DaggerC @Inject public constructor() {}
+
diff --git a/tests/jvm/java/kapt/DaggerTopLevel.kt b/tests/jvm/java/kapt/DaggerTopLevel.kt
new file mode 100644
index 0000000..27adb00
--- /dev/null
+++ b/tests/jvm/java/kapt/DaggerTopLevel.kt
@@ -0,0 +1,23 @@
+/*
+ * * 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.
+ */
+
+package kapt
+
+class DaggerTopLevel {
+ fun main() {
+ DaggerA().main()
+ }
+}
diff --git a/tests/jvm/java/kapt/FailingProcessor.java b/tests/jvm/java/kapt/FailingProcessor.java
new file mode 100644
index 0000000..1e3e703
--- /dev/null
+++ b/tests/jvm/java/kapt/FailingProcessor.java
@@ -0,0 +1,49 @@
+/*
+ * * 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.
+ */
+
+package kapt;
+
+
+import com.google.auto.service.AutoService;
+import java.util.Set;
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.Processor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.TypeElement;
+
+/** Annotation processor that fails when invoked. */
+@AutoService(Processor.class)
+@SupportedAnnotationTypes("*")
+public class FailingProcessor extends AbstractProcessor {
+
+ @Override
+ public synchronized void init(ProcessingEnvironment processingEnv) {
+ super.init(processingEnv);
+ }
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latestSupported();
+ }
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ throw new IllegalStateException("Shouldn't get here");
+ }
+}
diff --git a/tests/jvm/java/kapt/FlagTest.kt b/tests/jvm/java/kapt/FlagTest.kt
new file mode 100644
index 0000000..acf6145
--- /dev/null
+++ b/tests/jvm/java/kapt/FlagTest.kt
@@ -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.
+ */
+
+package kapt
+
+/** Requires -Akapt.AP.indexPrefix=Gen to generate expected class name. */
+@Count(value = 3, clazz = FlagTest_Gen2_Gen1_Gen0::class)
+class FlagTest {
+}
diff --git a/tests/jvm/java/kapt/GeneratesServices.kt b/tests/jvm/java/kapt/GeneratesServices.kt
new file mode 100644
index 0000000..771743d
--- /dev/null
+++ b/tests/jvm/java/kapt/GeneratesServices.kt
@@ -0,0 +1,28 @@
+/*
+ * * 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.
+ */
+
+package kapt
+
+import com.google.auto.service.AutoService
+
+public interface Regressible {
+ val regressed: Boolean
+}
+
+@AutoService(Regressible::class)
+public class Fixed() : Regressible {
+ override val regressed = false
+}
diff --git a/tests/jvm/java/kapt/GeneratesServicesTest.kt b/tests/jvm/java/kapt/GeneratesServicesTest.kt
new file mode 100644
index 0000000..c2b4c56
--- /dev/null
+++ b/tests/jvm/java/kapt/GeneratesServicesTest.kt
@@ -0,0 +1,35 @@
+/*
+ * * 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.
+ */
+
+package kapt
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+import java.util.ServiceLoader
+
+@RunWith(JUnit4::class)
+class GeneratesServicesTest {
+
+ @Test
+ fun servicesDiscoverable() {
+ val impls = ServiceLoader.load(Regressible::class.java)
+ assertThat(impls).isNotEmpty()
+ assertThat(impls.iterator().next().regressed).isFalse()
+ }
+}
diff --git a/tests/jvm/java/kapt/InnerEnumImport.kt b/tests/jvm/java/kapt/InnerEnumImport.kt
new file mode 100644
index 0000000..ef4b4f1
--- /dev/null
+++ b/tests/jvm/java/kapt/InnerEnumImport.kt
@@ -0,0 +1,36 @@
+/*
+ * * 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.
+ */
+
+package kapt
+
+import kapt.InnerEnumImport.Options.A
+import kapt.InnerEnumImport.Options.B
+import kapt.InnerEnumImport.Options.C
+
+class InnerEnumImport {
+ fun name(o: Options) =
+ when (o) {
+ A -> "a"
+ B -> "b"
+ C -> "c"
+ }
+
+ enum class Options {
+ A,
+ B,
+ C
+ }
+}
diff --git a/tests/jvm/java/kapt/InterfaceWithDefaultImpls.kt b/tests/jvm/java/kapt/InterfaceWithDefaultImpls.kt
new file mode 100644
index 0000000..a9aad4f
--- /dev/null
+++ b/tests/jvm/java/kapt/InterfaceWithDefaultImpls.kt
@@ -0,0 +1,25 @@
+/*
+ * * 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.
+ */
+
+// This file contains the example filed upstream for b/121222399.
+// TODO: Turn this into a regression test once the issue is fixed.
+package kapt
+
+interface Base<T>
+
+interface HasDefaultMethod<T> : Base<T> {
+ fun print(msg: String) = println(msg)
+}
diff --git a/tests/jvm/java/kapt/KTest.kt b/tests/jvm/java/kapt/KTest.kt
new file mode 100644
index 0000000..88efba8
--- /dev/null
+++ b/tests/jvm/java/kapt/KTest.kt
@@ -0,0 +1,21 @@
+/*
+ * * 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.
+ */
+
+package kapt
+
+@Count(value = 3, clazz = KTest_2_1_0::class)
+class KTest {
+}
diff --git a/tests/jvm/java/kapt/MakeHelper.kt b/tests/jvm/java/kapt/MakeHelper.kt
new file mode 100644
index 0000000..9809f34
--- /dev/null
+++ b/tests/jvm/java/kapt/MakeHelper.kt
@@ -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.
+ */
+
+package kapt
+
+import kotlin.reflect.KClass
+
+/** Annotation to specify a file name for `ProcessorWithData`. */
+annotation class MakeHelper(val value: String)
diff --git a/tests/jvm/java/kapt/MakeHelperClass.java.template b/tests/jvm/java/kapt/MakeHelperClass.java.template
new file mode 100644
index 0000000..db25fc7
--- /dev/null
+++ b/tests/jvm/java/kapt/MakeHelperClass.java.template
@@ -0,0 +1,20 @@
+/*
+ * * 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.
+ */
+
+package kapt;
+
+/** Java class copied into output by {@code ProcessorWithData}. */
+class |name| {}
diff --git a/tests/jvm/java/kapt/NonServiceProcessor.java b/tests/jvm/java/kapt/NonServiceProcessor.java
new file mode 100644
index 0000000..cab01d9
--- /dev/null
+++ b/tests/jvm/java/kapt/NonServiceProcessor.java
@@ -0,0 +1,45 @@
+/*
+ * * 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.
+ */
+
+package kapt;
+
+import java.util.Set;
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.TypeElement;
+
+/** Annotation processor <b>not</b> loadable via service loader. */
+@SupportedAnnotationTypes("*")
+public class NonServiceProcessor extends AbstractProcessor {
+
+ @Override
+ public synchronized void init(ProcessingEnvironment processingEnv) {
+ super.init(processingEnv);
+ }
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latestSupported();
+ }
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ return false;
+ }
+}
diff --git a/tests/jvm/java/kapt/Noop.kt b/tests/jvm/java/kapt/Noop.kt
new file mode 100644
index 0000000..0c3d9c3
--- /dev/null
+++ b/tests/jvm/java/kapt/Noop.kt
@@ -0,0 +1,20 @@
+/*
+ * * 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.
+ */
+
+package kapt
+
+fun main(argv : Array<String>) {
+}
diff --git a/tests/jvm/java/kapt/ProcessorWithData.kt b/tests/jvm/java/kapt/ProcessorWithData.kt
new file mode 100644
index 0000000..0d58205
--- /dev/null
+++ b/tests/jvm/java/kapt/ProcessorWithData.kt
@@ -0,0 +1,65 @@
+/*
+ * * 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.
+ */
+
+package kapt
+
+import com.google.auto.service.AutoService
+import java.io.IOException
+import java.io.UncheckedIOException
+import java.nio.charset.StandardCharsets.UTF_8
+import java.nio.file.Files
+import java.nio.file.Paths
+import javax.annotation.processing.AbstractProcessor
+import javax.annotation.processing.Processor
+import javax.annotation.processing.RoundEnvironment
+import javax.annotation.processing.SupportedAnnotationTypes
+import javax.lang.model.SourceVersion
+import javax.lang.model.element.TypeElement
+
+/** Annotation processor to test `data` dependencies specified with [MakeHelper] annotations. */
+@AutoService(Processor::class)
+@SupportedAnnotationTypes("*")
+internal class ProcessorWithData : AbstractProcessor() {
+
+ private val template: String =
+ Files.readString(
+ Paths.get(
+ "tests/jvm/java/kapt/MakeHelperClass.java.template"
+ ),
+ UTF_8
+ )
+
+ override fun getSupportedSourceVersion(): SourceVersion = SourceVersion.latestSupported()
+
+ override fun process(
+ annotations: Set<TypeElement>,
+ roundEnv: RoundEnvironment,
+ ): Boolean {
+ for (element in roundEnv.getElementsAnnotatedWith(MakeHelper::class.java)) {
+ val c = element.getAnnotation(MakeHelper::class.java)
+ if (c.value.isNotEmpty()) {
+ try {
+ processingEnv.filer.createSourceFile(c.value, element).openWriter().use {
+ it.write(template.replace("|name|", c.value.substring(c.value.lastIndexOf(".") + 1)))
+ }
+ } catch (e: IOException) {
+ throw UncheckedIOException(e)
+ }
+ }
+ }
+ return false
+ }
+}
diff --git a/tests/jvm/java/kapt/SealedClasses.kt b/tests/jvm/java/kapt/SealedClasses.kt
new file mode 100644
index 0000000..7727e08
--- /dev/null
+++ b/tests/jvm/java/kapt/SealedClasses.kt
@@ -0,0 +1,21 @@
+/*
+ * * 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.
+ */
+
+package kapt
+
+sealed class Sealed
+
+class Sub : Sealed()
diff --git a/tests/jvm/java/kapt/StaticImport.kt b/tests/jvm/java/kapt/StaticImport.kt
new file mode 100644
index 0000000..28d3752
--- /dev/null
+++ b/tests/jvm/java/kapt/StaticImport.kt
@@ -0,0 +1,25 @@
+/*
+ * * 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.
+ */
+
+package kapt
+
+import java.util.Objects.isNull
+import kapt.StaticMethod.of
+
+class StaticImport {
+ val x = isNull("hello")
+ val list = of("hello", "world")
+}
diff --git a/tests/jvm/java/kapt/StaticMethod.java b/tests/jvm/java/kapt/StaticMethod.java
new file mode 100644
index 0000000..5c6fc0c
--- /dev/null
+++ b/tests/jvm/java/kapt/StaticMethod.java
@@ -0,0 +1,32 @@
+/*
+ * * 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.
+ */
+
+package kapt;
+
+public class StaticMethod<T> {
+ public static <T> StaticMethod<T> of(T t1) {
+ return new StaticMethod<T>(t1);
+ }
+ public static <T> StaticMethod<T> of(T t1, T t2) {
+ return new StaticMethod<T>(t1, t2);
+ }
+
+ private final T[] ts;
+
+ private StaticMethod(T... ts) {
+ this.ts = ts;
+ }
+}
diff --git a/tests/jvm/java/kapt/Test.java b/tests/jvm/java/kapt/Test.java
new file mode 100644
index 0000000..f3ca1cf
--- /dev/null
+++ b/tests/jvm/java/kapt/Test.java
@@ -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.
+ */
+
+package kapt;
+
+@Count(value = 3, clazz = Test_2_1_0.class)
+class Test {
+ Test_2_1_0 x;
+}
diff --git a/tests/jvm/java/kapt/TriggerHelper.kt b/tests/jvm/java/kapt/TriggerHelper.kt
new file mode 100644
index 0000000..0ccb204
--- /dev/null
+++ b/tests/jvm/java/kapt/TriggerHelper.kt
@@ -0,0 +1,24 @@
+/*
+ * * 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.
+ */
+
+package kapt
+
+/** Cause `ProcessorWithData` to generate a class with the specified name. */
+@MakeHelper("kapt.GeneratedHelper")
+class TriggerHelper {
+ /** Property that makes sure the file is successfully copied and compiled into this package. */
+ private val helper = GeneratedHelper()
+}
diff --git a/tests/jvm/java/metasyntactic/BUILD b/tests/jvm/java/metasyntactic/BUILD
new file mode 100644
index 0000000..6ee26a9
--- /dev/null
+++ b/tests/jvm/java/metasyntactic/BUILD
@@ -0,0 +1,60 @@
+# 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("//kotlin:rules.bzl", "kt_jvm_library", "kt_jvm_test")
+
+licenses(["notice"])
+
+kt_jvm_library(
+ name = "Bar",
+ srcs = ["Bar.kt"],
+)
+
+kt_jvm_library(
+ name = "FooBar",
+ srcs = ["FooBar.java"],
+ deps = [":Bar"],
+)
+
+java_library(
+ name = "Qux",
+ srcs = ["Qux.java"],
+)
+
+kt_jvm_library(
+ name = "BazQux",
+ srcs = ["BazQux.kt"],
+ deps = [":Qux"],
+)
+
+kt_jvm_library(
+ name = "QuuxCorgeGrault",
+ srcs = [
+ "Corge.java",
+ "QuuxCorge.kt",
+ "QuuxCorgeGrault.java",
+ ],
+)
+
+kt_jvm_test(
+ name = "Main",
+ srcs = ["Main.kt"],
+ main_class = "metasyntactic.Main",
+ tags = ["darwin_x86_64_compatible"],
+ deps = [
+ ":BazQux",
+ ":FooBar",
+ ":QuuxCorgeGrault",
+ ],
+)
diff --git a/tests/jvm/java/metasyntactic/Bar.kt b/tests/jvm/java/metasyntactic/Bar.kt
new file mode 100644
index 0000000..f39c411
--- /dev/null
+++ b/tests/jvm/java/metasyntactic/Bar.kt
@@ -0,0 +1,21 @@
+/*
+ * * 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:JvmName("Bar")
+
+package metasyntactic
+
+fun bar(): String = "Bar"
diff --git a/tests/jvm/java/metasyntactic/BazQux.kt b/tests/jvm/java/metasyntactic/BazQux.kt
new file mode 100644
index 0000000..db6239f
--- /dev/null
+++ b/tests/jvm/java/metasyntactic/BazQux.kt
@@ -0,0 +1,23 @@
+/*
+ * * 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:JvmName("BazQux")
+
+package metasyntactic
+
+fun baz(): String = "Baz"
+
+fun bazQux(): String = baz() + Qux.qux()
diff --git a/tests/jvm/java/metasyntactic/Corge.java b/tests/jvm/java/metasyntactic/Corge.java
new file mode 100644
index 0000000..10e5c36
--- /dev/null
+++ b/tests/jvm/java/metasyntactic/Corge.java
@@ -0,0 +1,25 @@
+/*
+ * * 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.
+ */
+
+package metasyntactic;
+
+/** Corge */
+public class Corge {
+
+ public static String corge() {
+ return "Corge";
+ }
+}
diff --git a/tests/jvm/java/metasyntactic/FooBar.java b/tests/jvm/java/metasyntactic/FooBar.java
new file mode 100644
index 0000000..743ebab
--- /dev/null
+++ b/tests/jvm/java/metasyntactic/FooBar.java
@@ -0,0 +1,29 @@
+/*
+ * * 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.
+ */
+
+package metasyntactic;
+
+/** FooBar */
+public class FooBar {
+
+ public static String foo() {
+ return "Foo";
+ }
+
+ public static String fooBar() {
+ return foo() + Bar.bar();
+ }
+}
diff --git a/tests/jvm/java/metasyntactic/Main.kt b/tests/jvm/java/metasyntactic/Main.kt
new file mode 100644
index 0000000..559822b
--- /dev/null
+++ b/tests/jvm/java/metasyntactic/Main.kt
@@ -0,0 +1,23 @@
+/*
+ * * 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:JvmName("Main")
+
+package metasyntactic
+
+fun main(args: Array<String>) {
+ println(FooBar.fooBar() + bazQux() + QuuxCorgeGrault.quuxCorgeGrault() + "!")
+}
diff --git a/tests/jvm/java/metasyntactic/QuuxCorge.kt b/tests/jvm/java/metasyntactic/QuuxCorge.kt
new file mode 100644
index 0000000..ce84a83
--- /dev/null
+++ b/tests/jvm/java/metasyntactic/QuuxCorge.kt
@@ -0,0 +1,23 @@
+/*
+ * * 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:JvmName("QuuxCorge")
+
+package metasyntactic
+
+fun quux(): String = "Quux"
+
+fun quuxCorge(): String = quux() + Corge.corge()
diff --git a/tests/jvm/java/metasyntactic/QuuxCorgeGrault.java b/tests/jvm/java/metasyntactic/QuuxCorgeGrault.java
new file mode 100644
index 0000000..f7a9771
--- /dev/null
+++ b/tests/jvm/java/metasyntactic/QuuxCorgeGrault.java
@@ -0,0 +1,29 @@
+/*
+ * * 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.
+ */
+
+package metasyntactic;
+
+/** QuuxCorgeGrault */
+public class QuuxCorgeGrault {
+
+ public static String grault() {
+ return "Grault";
+ }
+
+ public static String quuxCorgeGrault() {
+ return QuuxCorge.quuxCorge() + grault();
+ }
+}
diff --git a/tests/jvm/java/metasyntactic/Qux.java b/tests/jvm/java/metasyntactic/Qux.java
new file mode 100644
index 0000000..5c5d231
--- /dev/null
+++ b/tests/jvm/java/metasyntactic/Qux.java
@@ -0,0 +1,25 @@
+/*
+ * * 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.
+ */
+
+package metasyntactic;
+
+/** Qux */
+public class Qux {
+
+ public static String qux() {
+ return "Qux";
+ }
+}
diff --git a/tests/jvm/java/metasyntactic/Qux.kt b/tests/jvm/java/metasyntactic/Qux.kt
new file mode 100644
index 0000000..20517b9
--- /dev/null
+++ b/tests/jvm/java/metasyntactic/Qux.kt
@@ -0,0 +1,21 @@
+/*
+ * * 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:JvmName("FooBar")
+
+package foo
+
+fun bar(): String = "FooBar!"
diff --git a/tests/jvm/java/mockito/BUILD b/tests/jvm/java/mockito/BUILD
new file mode 100644
index 0000000..ade78c9
--- /dev/null
+++ b/tests/jvm/java/mockito/BUILD
@@ -0,0 +1,29 @@
+# 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("//kotlin:rules.bzl", "kt_jvm_test")
+
+package(default_testonly = 1)
+
+licenses(["notice"])
+
+kt_jvm_test(
+ name = "MockitoTest",
+ srcs = glob(["*.kt"]),
+ deps = [
+ "@maven//:com_google_truth_truth",
+ "@maven//:junit_junit",
+ "@maven//:org_mockito_mockito_core",
+ ],
+)
diff --git a/tests/jvm/java/mockito/MockitoTest.kt b/tests/jvm/java/mockito/MockitoTest.kt
new file mode 100644
index 0000000..757f87d
--- /dev/null
+++ b/tests/jvm/java/mockito/MockitoTest.kt
@@ -0,0 +1,39 @@
+/*
+ * * 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.
+ */
+
+package mockito
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mockito
+
+@RunWith(JUnit4::class)
+class MockitoTest {
+ @Test
+ fun dummyTest() {
+ val mocked = Mockito.mock(WithExtensionMethod::class.java)
+ assertThat(mocked).isInstanceOf(WithExtensionMethod::class.java)
+ }
+}
+
+interface WithExtensionMethod {
+ fun GenericClass<*>.doSomething()
+ fun String.doSomethingElse(arg: GenericClass<*>)
+}
+
+open class GenericClass<T>
diff --git a/tests/jvm/java/multijarimport/A.kt b/tests/jvm/java/multijarimport/A.kt
new file mode 100644
index 0000000..7b7f942
--- /dev/null
+++ b/tests/jvm/java/multijarimport/A.kt
@@ -0,0 +1,20 @@
+/*
+ * * 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.
+ */
+
+package multijarimport
+
+/** A test class. */
+class A(val msg: String)
diff --git a/tests/jvm/java/multijarimport/B.kt b/tests/jvm/java/multijarimport/B.kt
new file mode 100644
index 0000000..2505982
--- /dev/null
+++ b/tests/jvm/java/multijarimport/B.kt
@@ -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.
+ */
+
+package multijarimport
+
+/** A test class that needs A */
+class B {
+ fun use(a: A): String = a.msg
+}
diff --git a/tests/jvm/java/multijarimport/BUILD b/tests/jvm/java/multijarimport/BUILD
new file mode 100644
index 0000000..d3e6057
--- /dev/null
+++ b/tests/jvm/java/multijarimport/BUILD
@@ -0,0 +1,65 @@
+# 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("//kotlin:rules.bzl", "kt_jvm_import", "kt_jvm_library")
+
+package(
+ default_testonly = 1,
+)
+
+licenses(["notice"])
+
+# During coverage builds, every library gets a dep on JaCoCo (Java Code Coverage).
+# Libjars, from libraries, only include their direct sources. Together, these behaviours
+# trigger an ImportDepsChecker error for :import_a_and_b. To prevent that, we disable
+# coverage builds on all downstream targets.
+_NO_ZAPFHAHN_BECAUSE_LIBJARS_EXCLUDE_JACOCO = ["nozapfhahn"]
+
+kt_jvm_library(
+ name = "A",
+ srcs = ["A.kt"],
+)
+
+kt_jvm_library(
+ name = "B",
+ srcs = ["B.kt"],
+ deps = [":A"],
+)
+
+# This import target with multiple JARs is the main thing we're testing.
+kt_jvm_import(
+ name = "import_a_and_b",
+ jars = [
+ ":libA.jar",
+ ":libB.jar",
+ ],
+ srcjar = ":libB-src.jar",
+ tags = _NO_ZAPFHAHN_BECAUSE_LIBJARS_EXCLUDE_JACOCO,
+)
+
+kt_jvm_library(
+ name = "TestRunner",
+ srcs = ["TestRunner.kt"],
+ tags = _NO_ZAPFHAHN_BECAUSE_LIBJARS_EXCLUDE_JACOCO,
+ deps = [":import_a_and_b"],
+)
+
+java_test(
+ name = "multijarimport_test",
+ main_class = "multijarimport.TestRunner",
+ tags = _NO_ZAPFHAHN_BECAUSE_LIBJARS_EXCLUDE_JACOCO,
+ runtime_deps = [
+ ":TestRunner",
+ ],
+)
diff --git a/tests/jvm/java/multijarimport/TestRunner.kt b/tests/jvm/java/multijarimport/TestRunner.kt
new file mode 100644
index 0000000..e290159
--- /dev/null
+++ b/tests/jvm/java/multijarimport/TestRunner.kt
@@ -0,0 +1,30 @@
+/*
+ * * 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.
+ */
+
+package multijarimport
+
+object TestRunner {
+
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val a = A("hello")
+ val b = B()
+
+ if (b.use(a) != "hello") {
+ throw AssertionError()
+ }
+ }
+}
diff --git a/tests/jvm/java/srcartifacts/BUILD b/tests/jvm/java/srcartifacts/BUILD
new file mode 100644
index 0000000..4236672
--- /dev/null
+++ b/tests/jvm/java/srcartifacts/BUILD
@@ -0,0 +1,118 @@
+# 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("//kotlin:rules.bzl", "kt_jvm_library", "kt_jvm_test")
+load("//tests/analysis:util.bzl", "create_dir", "create_file")
+load("@bazel_skylib//rules:build_test.bzl", "build_test")
+
+package(default_testonly = 1)
+
+licenses(["notice"])
+
+kt_jvm_test(
+ name = "srcartifacts",
+ srcs = [
+ "JavaSrc.java",
+ "KtSrc.kt",
+ "SrcArtifactsTest.kt",
+ ":JavaSrcjar_gen",
+ ":dir/java",
+ ":dir/kotlin",
+ ],
+ resources = [
+ "dir/empty",
+ "dir/resources",
+ ],
+ test_class = "srcartifacts.SrcArtifactsTest",
+ deps = [
+ "@maven//:com_google_truth_truth",
+ "@maven//:junit_junit",
+ ],
+)
+
+create_dir(
+ name = "dir/java",
+ srcs = [
+ "JavaInJavaDir.java",
+ ],
+ subdir = "srcartifacts",
+)
+
+create_dir(
+ name = "dir/kotlin",
+ srcs = [
+ "KtInKotlinDir.kt",
+ ],
+ subdir = "srcartifacts",
+)
+
+create_dir(
+ name = "dir/empty",
+ srcs = [],
+ subdir = "srcartifacts/empty",
+)
+
+create_dir(
+ name = "dir/resources",
+ srcs = [
+ create_file(
+ name = "resources_in_resources_dir.txt",
+ content = "Test resource content.",
+ ),
+ ],
+ subdir = "resources",
+)
+
+genrule(
+ name = "JavaSrcjar_gen",
+ srcs = [":libJavaSrcjar_lib-src.jar"],
+ outs = ["JavaSrcjar.srcjar"],
+ cmd = "cp $(location :libJavaSrcjar_lib-src.jar) $(location :JavaSrcjar.srcjar)",
+)
+
+java_library(
+ name = "JavaSrcjar_lib",
+ srcs = ["JavaSrcjar.java"],
+ tags = ["manual"],
+)
+
+kt_jvm_library(
+ name = "empty_java_tree_artifact",
+ srcs = [
+ create_dir(
+ name = "dir/empty_java/java",
+ srcs = [],
+ subdir = "srcartifacts",
+ ),
+ ],
+)
+
+kt_jvm_library(
+ name = "empty_kotlin_tree_artifact",
+ srcs = [
+ create_dir(
+ name = "dir/empty_kotlin/kotlin",
+ srcs = [],
+ subdir = "srcartifacts",
+ ),
+ ],
+)
+
+build_test(
+ name = "empty_dirs_build_test",
+ targets = [
+ "empty_java_tree_artifact",
+ "empty_kotlin_tree_artifact",
+ ],
+)
diff --git a/tests/jvm/java/srcartifacts/JavaInJavaDir.java b/tests/jvm/java/srcartifacts/JavaInJavaDir.java
new file mode 100644
index 0000000..70aa7c9
--- /dev/null
+++ b/tests/jvm/java/srcartifacts/JavaInJavaDir.java
@@ -0,0 +1,31 @@
+/*
+ * * 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.
+ */
+
+package srcartifacts;
+
+import java.util.Set;
+
+final class JavaInJavaDir implements SrcArtifact {
+ @Override
+ public Set<Class<? extends SrcArtifact>> getAllSrcArtifacts() {
+ return Set.of(
+ JavaInJavaDir.class, //
+ JavaSrc.class,
+ JavaSrcjar.class,
+ KtInKotlinDir.class,
+ KtSrc.class);
+ }
+}
diff --git a/tests/jvm/java/srcartifacts/JavaSrc.java b/tests/jvm/java/srcartifacts/JavaSrc.java
new file mode 100644
index 0000000..4fdb1c7
--- /dev/null
+++ b/tests/jvm/java/srcartifacts/JavaSrc.java
@@ -0,0 +1,31 @@
+/*
+ * * 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.
+ */
+
+package srcartifacts;
+
+import java.util.Set;
+
+final class JavaSrc implements SrcArtifact {
+ @Override
+ public Set<Class<? extends SrcArtifact>> getAllSrcArtifacts() {
+ return Set.of(
+ JavaInJavaDir.class, //
+ JavaSrc.class,
+ JavaSrcjar.class,
+ KtInKotlinDir.class,
+ KtSrc.class);
+ }
+}
diff --git a/tests/jvm/java/srcartifacts/JavaSrcjar.java b/tests/jvm/java/srcartifacts/JavaSrcjar.java
new file mode 100644
index 0000000..1be65d5
--- /dev/null
+++ b/tests/jvm/java/srcartifacts/JavaSrcjar.java
@@ -0,0 +1,31 @@
+/*
+ * * 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.
+ */
+
+package srcartifacts;
+
+import java.util.Set;
+
+final class JavaSrcjar implements SrcArtifact {
+ @Override
+ public Set<Class<? extends SrcArtifact>> getAllSrcArtifacts() {
+ return Set.of(
+ JavaInJavaDir.class, //
+ JavaSrc.class,
+ JavaSrcjar.class,
+ KtInKotlinDir.class,
+ KtSrc.class);
+ }
+}
diff --git a/tests/jvm/java/srcartifacts/KtInKotlinDir.kt b/tests/jvm/java/srcartifacts/KtInKotlinDir.kt
new file mode 100644
index 0000000..dd2b96d
--- /dev/null
+++ b/tests/jvm/java/srcartifacts/KtInKotlinDir.kt
@@ -0,0 +1,29 @@
+/*
+ * * 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.
+ */
+
+package srcartifacts
+
+class KtInKotlinDir() : SrcArtifact {
+ override fun getAllSrcArtifacts(): Set<Class<out SrcArtifact>> {
+ return setOf(
+ JavaInJavaDir::class.java,
+ JavaSrc::class.java,
+ JavaSrcjar::class.java,
+ KtInKotlinDir::class.java,
+ KtSrc::class.java,
+ )
+ }
+}
diff --git a/tests/jvm/java/srcartifacts/KtSrc.kt b/tests/jvm/java/srcartifacts/KtSrc.kt
new file mode 100644
index 0000000..cca27dc
--- /dev/null
+++ b/tests/jvm/java/srcartifacts/KtSrc.kt
@@ -0,0 +1,29 @@
+/*
+ * * 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.
+ */
+
+package srcartifacts
+
+class KtSrc() : SrcArtifact {
+ override fun getAllSrcArtifacts(): Set<Class<out SrcArtifact>> {
+ return setOf(
+ JavaInJavaDir::class.java,
+ JavaSrc::class.java,
+ JavaSrcjar::class.java,
+ KtInKotlinDir::class.java,
+ KtSrc::class.java,
+ )
+ }
+}
diff --git a/tests/jvm/java/srcartifacts/SrcArtifactsTest.kt b/tests/jvm/java/srcartifacts/SrcArtifactsTest.kt
new file mode 100644
index 0000000..0622804
--- /dev/null
+++ b/tests/jvm/java/srcartifacts/SrcArtifactsTest.kt
@@ -0,0 +1,58 @@
+/*
+ * * 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.
+ */
+
+package srcartifacts
+
+import com.google.common.truth.Truth.assertThat
+import java.nio.charset.StandardCharsets
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+interface SrcArtifact {
+ fun getAllSrcArtifacts(): Set<Class<out SrcArtifact>>
+}
+
+@RunWith(JUnit4::class)
+class SrcArtifactsTest {
+
+ @Test
+ fun allSrcArtifactsInterop() {
+ val allSrcArtifacts =
+ setOf(
+ JavaInJavaDir::class.java,
+ JavaSrc::class.java,
+ JavaSrcjar::class.java,
+ KtInKotlinDir::class.java,
+ KtSrc::class.java,
+ )
+
+ for (artifact in allSrcArtifacts) {
+ val instance = artifact.getDeclaredConstructor().newInstance()
+ assertThat(instance.getAllSrcArtifacts()).isEqualTo(allSrcArtifacts)
+ }
+ }
+
+ @Test
+ fun resourceFileContent() {
+ val fileContent =
+ javaClass.classLoader
+ .getResourceAsStream("resources/resources_in_resources_dir.txt")
+ .use { it.readAllBytes() }
+ .toString(StandardCharsets.UTF_8)
+ assertThat(fileContent).isEqualTo("Test resource content.\n")
+ }
+}
diff --git a/toolchains/kotlin_jvm/BUILD b/toolchains/kotlin_jvm/BUILD
new file mode 100644
index 0000000..587d3a9
--- /dev/null
+++ b/toolchains/kotlin_jvm/BUILD
@@ -0,0 +1,50 @@
+# 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.
+
+"""Kotlin/JVM toolchain."""
+
+load(":kt_jvm_toolchains.bzl", "kt_jvm_toolchains")
+load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
+
+licenses(["notice"])
+
+package(default_visibility = ["//:internal"])
+
+toolchain_type(name = kt_jvm_toolchains.name)
+
+# Toolchain resolution must match :kt_jvm_toolchain_impl. Therefore, there's no
+# need for platform-specific toolchain declarations.
+toolchain(
+ name = "kt_jvm_toolchain",
+ toolchain = ":kt_jvm_toolchain_impl",
+ toolchain_type = kt_jvm_toolchains.type,
+)
+
+alias(
+ name = "kt_jvm_toolchain_impl",
+ actual = select({
+ "@bazel_platforms//os:macos": ":kt_jvm_toolchain_macos_impl",
+ "//conditions:default": ":kt_jvm_toolchain_default_impl",
+ }),
+ visibility = ["//visibility:public"],
+)
+
+kt_jvm_toolchains.declare(
+ name = "kt_jvm_toolchain_macos_impl",
+ enable_turbine_direct = False,
+)
+
+kt_jvm_toolchains.declare(
+ name = "kt_jvm_toolchain_default_impl",
+)
diff --git a/toolchains/kotlin_jvm/java_toolchains.bzl b/toolchains/kotlin_jvm/java_toolchains.bzl
new file mode 100644
index 0000000..63dec4e
--- /dev/null
+++ b/toolchains/kotlin_jvm/java_toolchains.bzl
@@ -0,0 +1,28 @@
+# 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.
+
+"""Java toolchain for Kotlin."""
+
+_ATTRS = dict(
+ _java_toolchain = attr.label(
+ default = Label(
+ "@bazel_tools//tools/jdk:current_java_toolchain",
+ ),
+ ),
+)
+
+java_toolchains = struct(
+ get = lambda ctx: ctx.attr._java_toolchain[java_common.JavaToolchainInfo],
+ attrs = _ATTRS,
+)
diff --git a/toolchains/kotlin_jvm/kt_jvm_toolchains.bzl b/toolchains/kotlin_jvm/kt_jvm_toolchains.bzl
new file mode 100644
index 0000000..0b9c610
--- /dev/null
+++ b/toolchains/kotlin_jvm/kt_jvm_toolchains.bzl
@@ -0,0 +1,257 @@
+# 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.
+
+"""Kotlin toolchain."""
+
+# Work around to toolchains in Google3.
+KtJvmToolchainInfo = provider()
+
+KT_VERSION = "v1_7_10"
+
+KT_LANG_VERSION = "1.7"
+
+# Kotlin JVM toolchain type label
+_TYPE = Label("//toolchains/kotlin_jvm:kt_jvm_toolchain_type")
+
+def _kotlinc_common_flags(ctx, other_flags):
+ """Returns kotlinc flags to use in all compilations."""
+ args = [
+ # We're supplying JDK in bootclasspath explicitly instead
+ "-no-jdk",
+
+ # stdlib included in merged_deps
+ "-no-stdlib",
+
+ # The bytecode format to emit
+ "-jvm-target",
+ ctx.attr.jvm_target,
+
+ # Emit bytecode with parameter names
+ "-java-parameters",
+
+ # Allow default method declarations, akin to what javac emits (b/110378321).
+ "-Xjvm-default=all",
+
+ # Trust JSR305 nullness type qualifier nicknames the same as @Nonnull/@Nullable
+ # (see https://kotlinlang.org/docs/reference/java-interop.html#jsr-305-support)
+ "-Xjsr305=strict",
+
+ # Trust go/JSpecify nullness annotations
+ # (see https://kotlinlang.org/docs/whatsnew1520.html#support-for-jspecify-nullness-annotations)
+ "-Xjspecify-annotations=strict",
+
+ # Trust annotations on type arguments, etc.
+ # (see https://kotlinlang.org/docs/java-interop.html#annotating-type-arguments-and-type-parameters)
+ "-Xtype-enhancement-improvements-strict-mode",
+
+ # TODO: Remove this as the default setting (probably Kotlin 1.7)
+ "-Xenhance-type-parameter-types-to-def-not-null=true",
+
+ # Explicitly set language version so we can update compiler separate from language version
+ "-language-version",
+ ctx.attr.kotlin_language_version,
+
+ # Enable type annotations in the JVM bytecode (b/170647926)
+ "-Xemit-jvm-type-annotations",
+
+ # TODO: Temporarily disable 1.5's sam wrapper conversion
+ "-Xsam-conversions=class",
+
+ # We don't want people to use experimental APIs, but if they do, we want them to use @OptIn
+ "-opt-in=kotlin.RequiresOptIn",
+
+ # Don't complain when using old builds or release candidate builds
+ "-Xskip-prerelease-check",
+
+ # Allows a no source files to create an empty jar.
+ "-Xallow-no-source-files",
+ ] + other_flags
+
+ # --define=extra_kt_jvm_opts is for overriding from command line.
+ # (Last wins in repeated --define=foo= use, so use --define=bar= instead.)
+ extra_kt_jvm_opts = ctx.var.get("extra_kt_jvm_opts", default = None)
+ if extra_kt_jvm_opts:
+ args.extend([o for o in extra_kt_jvm_opts.split(" ") if o])
+ return args
+
+def _kotlinc_ide_flags(ctx):
+ return _kotlinc_common_flags(ctx, other_flags = [])
+
+def _kotlinc_cli_flags(ctx):
+ return _kotlinc_common_flags(ctx, other_flags = [
+ # Silence all warning-level diagnostics
+ "-nowarn",
+ ])
+
+def _kt_jvm_toolchain_impl(ctx):
+ kt_jvm_toolchain = dict(
+ build_marker = ctx.file.build_marker,
+ coverage_instrumenter = ctx.attr.coverage_instrumenter[DefaultInfo].files_to_run,
+ # Don't require JavaInfo provider for integration test convenience.
+ coverage_runtime = ctx.attr.coverage_runtime[JavaInfo] if JavaInfo in ctx.attr.coverage_runtime else None,
+ genclass = ctx.file.genclass,
+ jar_tool = ctx.attr.jar_tool[DefaultInfo].files_to_run,
+ java_runtime = ctx.attr.java_runtime,
+ jvm_abi_gen_plugin = ctx.file.jvm_abi_gen_plugin,
+ kotlin_annotation_processing = ctx.file.kotlin_annotation_processing,
+ kotlin_compiler = ctx.attr.kotlin_compiler[DefaultInfo].files_to_run,
+ kotlin_language_version = ctx.attr.kotlin_language_version,
+ kotlin_libs = [JavaInfo(compile_jar = jar, output_jar = jar) for jar in ctx.files.kotlin_libs],
+ kotlin_sdk_libraries = ctx.attr.kotlin_sdk_libraries,
+ kotlinc_cli_flags = _kotlinc_cli_flags(ctx),
+ kotlinc_ide_flags = _kotlinc_ide_flags(ctx),
+ proguard_whitelister = ctx.attr.proguard_whitelister[DefaultInfo].files_to_run,
+ turbine = ctx.file.turbine,
+ turbine_direct = ctx.file.turbine_direct if ctx.attr.enable_turbine_direct else None,
+ turbine_jsa = ctx.file.turbine_jsa,
+ )
+ return [
+ platform_common.ToolchainInfo(**kt_jvm_toolchain),
+ KtJvmToolchainInfo(**kt_jvm_toolchain),
+ ]
+
+_kt_jvm_toolchain_internal = rule(
+ name = "kt_jvm_toolchain",
+ attrs = dict(
+ build_marker = attr.label(
+ default = "//tools:build_marker",
+ allow_single_file = [".jar"],
+ ),
+ coverage_instrumenter = attr.label(
+ default = "//tools/coverage:offline_instrument",
+ cfg = "exec",
+ executable = True,
+ ),
+ coverage_runtime = attr.label(
+ default = "@maven//:org_jacoco_org_jacoco_agent",
+ ),
+ enable_turbine_direct = attr.bool(
+ # If disabled, the value of turbine_direct will be ignored.
+ # Starlark doesn't allow None to override default-valued attributes:
+ default = True,
+ ),
+ genclass = attr.label(
+ default = "@bazel_tools//tools/jdk:GenClass_deploy.jar",
+ cfg = "exec",
+ allow_single_file = True,
+ ),
+ jar_tool = attr.label(
+ default = "@bazel_tools//tools/jdk:jar",
+ executable = True,
+ allow_files = True,
+ cfg = "exec",
+ ),
+ java_runtime = attr.label(
+ default = "@bazel_tools//tools/jdk:current_java_runtime",
+ cfg = "exec",
+ allow_files = True,
+ ),
+ jvm_abi_gen_plugin = attr.label(
+ default = "@kotlinc//:jvm_abi_gen_plugin",
+ cfg = "exec",
+ allow_single_file = [".jar"],
+ ),
+ jvm_target = attr.string(
+ doc = "The value to pass as -jvm-target, indicating the bytecode format to emit.",
+ ),
+ kotlin_annotation_processing = attr.label(
+ default = "@kotlinc//:kotlin_annotation_processing",
+ cfg = "exec",
+ allow_single_file = True,
+ ),
+ kotlin_compiler = attr.label(
+ default = "@kotlinc//:kotlin_compiler",
+ cfg = "exec",
+ executable = True,
+ ),
+ kotlin_language_version = attr.string(
+ default = KT_LANG_VERSION,
+ ),
+ kotlin_libs = attr.label_list(
+ doc = "The libraries required during all Kotlin builds.",
+ default = [
+ "@kotlinc//:kotlin_stdlib",
+ "@kotlinc//:annotations",
+ ],
+ allow_files = [".jar"],
+ cfg = "target",
+ ),
+ kotlin_sdk_libraries = attr.label_list(
+ doc = "The libraries required to resolve Kotlin code in an IDE.",
+ default = [
+ "@kotlinc//:kotlin_reflect",
+ "@kotlinc//:kotlin_stdlib",
+ "@kotlinc//:kotlin_stdlib_jdk7",
+ "@kotlinc//:kotlin_stdlib_jdk8",
+ "@kotlinc//:kotlin_test_not_testonly",
+ ],
+ cfg = "target",
+ ),
+ proguard_whitelister = attr.label(
+ default = "@bazel_tools//tools/jdk:proguard_whitelister",
+ cfg = "exec",
+ ),
+ runtime = attr.label_list(
+ # This attribute has a "magic" name recognized by the native DexArchiveAspect
+ # (b/78647825). Must list all implicit runtime deps here, this is not limited
+ # to Kotlin runtime libs.
+ default = [
+ "@kotlinc//:kotlin_stdlib",
+ "@kotlinc//:annotations",
+ ],
+ cfg = "target",
+ doc = "The Kotlin runtime libraries grouped into one attribute.",
+ ),
+ turbine = attr.label(
+ default = "@bazel_tools//tools/jdk:turbine_direct",
+ cfg = "exec",
+ allow_single_file = True,
+ ),
+ turbine_direct = attr.label(
+ executable = True,
+ cfg = "exec",
+ allow_single_file = True,
+ ),
+ turbine_jsa = attr.label(
+ cfg = "exec",
+ allow_single_file = True,
+ ),
+ ),
+ provides = [platform_common.ToolchainInfo],
+ implementation = _kt_jvm_toolchain_impl,
+)
+
+def _kt_jvm_toolchain(**kwargs):
+ _kt_jvm_toolchain_internal(
+ jvm_target = select({
+ "//conditions:default": "11",
+ }),
+ **kwargs
+ )
+
+_ATTRS = dict(
+ _toolchain = attr.label(
+ # TODO: Delete this attr when fixed.
+ doc = "Magic attribute name for DexArchiveAspect (b/78647825)",
+ default = "//toolchains/kotlin_jvm:kt_jvm_toolchain_impl",
+ ),
+)
+
+kt_jvm_toolchains = struct(
+ name = _TYPE.name,
+ get = lambda ctx: ctx.toolchains[_TYPE],
+ type = str(_TYPE),
+ declare = _kt_jvm_toolchain,
+ attrs = _ATTRS,
+)
diff --git a/tools/BUILD b/tools/BUILD
new file mode 100644
index 0000000..18f1a9a
--- /dev/null
+++ b/tools/BUILD
@@ -0,0 +1,27 @@
+# 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.
+
+# Description: Kotlin building rules tools
+
+licenses(["notice"])
+
+package(default_visibility = ["//:internal"])
+
+# JAR that contains a marker entry, for identifying apps built by rules_kotlin.
+genrule(
+ name = "build_marker",
+ outs = ["kotlin_build_marker.jar"],
+ cmd = """$(location @bazel_tools//tools/zip:zipper) c $@ "assets/_kotlin=" """,
+ tools = ["@bazel_tools//tools/zip:zipper"],
+)
diff --git a/tools/coverage/BUILD b/tools/coverage/BUILD
new file mode 100644
index 0000000..e97ac5d
--- /dev/null
+++ b/tools/coverage/BUILD
@@ -0,0 +1,27 @@
+# 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"])
+
+sh_binary(
+ name = "offline_instrument",
+ srcs = ["bazel_jar_instrumenter.sh"],
+ data = [
+ "//bazel:jacoco_cli",
+ "@bazel_tools//tools/jdk:jar",
+ ],
+ visibility = [
+ "//:internal",
+ ],
+)
diff --git a/tools/coverage/bazel_jar_instrumenter.sh b/tools/coverage/bazel_jar_instrumenter.sh
new file mode 100755
index 0000000..648c6b6
--- /dev/null
+++ b/tools/coverage/bazel_jar_instrumenter.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# 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.
+
+#
+set -eu
+
+readonly current_dir="$0.runfiles"
+readonly in="$1"
+readonly out="$2"
+shift 2
+
+readonly tmp_dir="$(mktemp -d)"
+trap "rm -rf ${tmp_dir}" EXIT
+
+readonly jacoco="$(ls ${current_dir}/rules_kotlin/bazel/jacoco_cli)"
+readonly jar="$(which jar)"
+
+# Unzip input Jar and run JaCoCo over it
+mkdir "${tmp_dir}/classes"
+mkdir "${tmp_dir}/instrumented"
+unzip -qq -d "${tmp_dir}/classes" "${in}"
+"${jacoco}" instrument "${tmp_dir}/classes" --dest "${tmp_dir}/instrumented" >/dev/null
+
+# Rename input .class files to .class.uninstrumented
+find "${tmp_dir}/classes" -name '*.class' -exec mv {} {}.uninstrumented \;
+
+# Zip all the files together
+"${jar}" cf "${out}" -C "${tmp_dir}/instrumented" .
+"${jar}" uf "${out}" -C "${tmp_dir}/classes" .
+"${jar}" uf "${out}" "$@"