1# Copyright 2022 Google LLC. All rights reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the License); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""Combined aspect for all rules_kotlin behaviours that need to traverse exports.""" 16 17load("//:visibility.bzl", "RULES_KOTLIN") 18load(":compiler_plugin.bzl", "kt_compiler_plugin_visitor") 19load(":direct_jdeps.bzl", "kt_direct_jdeps_visitor") 20load(":forbidden_deps.bzl", "kt_forbidden_deps_visitor") 21load(":friend_jars.bzl", "kt_friend_jars_visitor") 22load(":friend_labels.bzl", "kt_friend_labels_visitor") 23load(":java_plugin.bzl", "java_plugin_visitor") 24 25visibility(RULES_KOTLIN) 26 27# java_xxx_proto_library don't populate java_outputs but we can get them through 28# required_aspect_providers from their proto_library deps. 29_DEPS_AS_EXPORTS_RULES = [ 30 "java_proto_library", 31 "java_lite_proto_library", 32 "java_mutable_proto_library", 33] 34 35_NO_SRCS_DEPS_AS_EXPORTS_RULES = [ 36 "proto_library", 37] 38 39# visitor = struct[T]( 40# name = string, 41# visit_target = function(Target, ctx.rule): list[T], 42# filter_edge = None|(function(src: ?, dest: Target): bool), 43# process_unvisited_target = None|(function(Target): list[T]), 44# finish_expansion = None|(function(depset[T]): depset[T]), 45# ) 46_VISITORS = [ 47 kt_forbidden_deps_visitor, 48 kt_direct_jdeps_visitor, 49 kt_compiler_plugin_visitor, 50 kt_friend_jars_visitor, 51 kt_friend_labels_visitor, 52 java_plugin_visitor, 53] 54 55_KtTraverseExportsInfo = provider( 56 doc = "depsets for transitive info about exports", 57 fields = { 58 v.name: ("depset[%s]" % v.name) 59 for v in _VISITORS 60 }, 61) 62 63_EMPTY_KT_TRAVERSE_EXPORTS_INFO = _KtTraverseExportsInfo(**{ 64 v.name: depset() 65 for v in _VISITORS 66}) 67 68def _aspect_impl(target, ctx): 69 if not (JavaInfo in target): 70 # Ignore non-JVM targets. This also chops-up the 71 # traversal domain at these targets. 72 # TODO: Support non-JVM targets for KMP 73 return _EMPTY_KT_TRAVERSE_EXPORTS_INFO 74 75 exports = [] 76 exports.extend(getattr(ctx.rule.attr, "exports", [])) # exports list is frozen 77 if ctx.rule.kind in _DEPS_AS_EXPORTS_RULES: 78 exports.extend(ctx.rule.attr.deps) 79 elif ctx.rule.kind in _NO_SRCS_DEPS_AS_EXPORTS_RULES and not ctx.rule.attr.srcs: 80 exports.extend(ctx.rule.attr.deps) 81 82 return _KtTraverseExportsInfo(**{ 83 v.name: depset( 84 direct = v.visit_target(target, ctx.rule), 85 transitive = [ 86 getattr(e[_KtTraverseExportsInfo], v.name) 87 for e in exports 88 if (not v.filter_edge or v.filter_edge(target, e)) 89 ], 90 ) 91 for v in _VISITORS 92 }) 93 94_aspect = aspect( 95 implementation = _aspect_impl, 96 provides = [_KtTraverseExportsInfo], 97 # Transitively check exports, since they are effectively directly depended on. 98 # "deps" needed for rules that treat deps as exports (usually absent srcs). 99 attr_aspects = ["exports", "deps"], 100 required_aspect_providers = [JavaInfo], # to get at JavaXxxProtoAspects' JavaInfos 101) 102 103def _create_visitor_expand(visitor): 104 def _visitor_expand(targets, root = None): 105 direct = [] 106 transitive = [] 107 for t in targets: 108 if (not visitor.filter_edge or visitor.filter_edge(root, t)): 109 if _KtTraverseExportsInfo in t: 110 transitive.append(getattr(t[_KtTraverseExportsInfo], visitor.name)) 111 elif visitor.process_unvisited_target: 112 direct.extend(visitor.process_unvisited_target(t)) 113 114 expanded_set = depset(direct = direct, transitive = transitive) 115 return visitor.finish_expansion(expanded_set) if visitor.finish_expansion else expanded_set 116 117 return _visitor_expand 118 119kt_traverse_exports = struct( 120 aspect = _aspect, 121 **{ 122 "expand_" + v.name: _create_visitor_expand(v) 123 for v in _VISITORS 124 } 125) 126