| # 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", "kt_friend_labels_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 = [ |
| "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, |
| kt_friend_labels_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: Support 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 |
| } |
| ) |