github.com/bazelbuild/bazel-gazelle@v0.36.1-0.20240520142334-61b277ba6fed/internal/bzlmod/utils.bzl (about) 1 # Copyright 2023 The Bazel Authors. 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 load("@bazel_features//:features.bzl", "bazel_features") 16 17 visibility([ 18 "//tests/bzlmod/...", 19 ]) 20 21 # structs have certain built-in methods or attributes that should not 22 # be overwritten. Load these by calling `dir` on an empty struct. 23 # e.g. ["to_proto", "to_json"] 24 _STRUCT_PROTECTED_ATTRIBUTES = dir(struct()) 25 26 def drop_nones(dict): 27 """Drop entries with None values from a dictionary. 28 29 Args: 30 dict: A dictionary. 31 32 Returns: 33 A new dictionary with the same keys as dict, but with entries with 34 None values removed. 35 """ 36 return {k: v for k, v in dict.items() if v != None} 37 38 def format_rule_call(_kind, **attrs): 39 """Format a rule call. 40 41 Args: 42 _kind: The kind of the rule. 43 attrs: The attributes of the rule. The attributes are sorted by name, 44 except for the "name" attribute, which is always first. None 45 values are ignored. 46 47 Returns: 48 A string representing the rule call. 49 """ 50 51 lines = [_kind + "("] 52 for attr, value in sorted(attrs.items(), key = _attrs_sort_key): 53 if value == None: 54 continue 55 lines.append(" {} = {},".format(attr, repr(value))) 56 lines.append(")") 57 58 return "\n".join(lines) 59 60 def _attrs_sort_key(entry): 61 """Sort key for attributes. 62 63 Attributes are sorted by name, except for the "name" attribute, which is 64 always first. 65 66 Args: 67 entry: A tuple of (attribute name, attribute value). 68 69 Returns: 70 An opaque sort key. 71 """ 72 attr, _ = entry 73 if attr == "name": 74 # Sort "name" first. 75 return "" 76 return attr 77 78 def get_directive_value(directives, key): 79 """Get the value of a directive. 80 81 Args: 82 directives: A list of directives. 83 key: The key of the directive. 84 85 Returns: 86 The value of the last directive, or None if the directive is not 87 present. 88 """ 89 prefix = "gazelle:" + key + " " 90 91 value = None 92 for directive in directives: 93 if directive.startswith(prefix): 94 # Treat "gazelle:key value" the same as "gazelle:key value". 95 value = directive[len(prefix):].lstrip() 96 97 return value 98 99 def with_replaced_or_new_fields(_struct, **replacements): 100 """Provides a shallow copy of a structure with replacements and/or new fields 101 102 Args: 103 _struct: structure to shallow copy. 104 **replacements: kwargs for fields to either replace or add to the new struct. 105 106 Returns: 107 The resulting updated structure. 108 """ 109 110 new_struct_assignments = { 111 key: getattr(_struct, key) 112 for key in dir(_struct) 113 if key not in _STRUCT_PROTECTED_ATTRIBUTES 114 } 115 116 # Overwrite existing fields and add new ones. 117 for key, value in replacements.items(): 118 new_struct_assignments[key] = value 119 120 return struct(**new_struct_assignments) 121 122 def extension_metadata( 123 module_ctx, 124 *, 125 root_module_direct_deps = None, 126 root_module_direct_dev_deps = None, 127 reproducible = False): 128 if not hasattr(module_ctx, "extension_metadata"): 129 return None 130 metadata_kwargs = {} 131 if bazel_features.external_deps.extension_metadata_has_reproducible: 132 metadata_kwargs["reproducible"] = reproducible 133 return module_ctx.extension_metadata( 134 root_module_direct_deps = root_module_direct_deps, 135 root_module_direct_dev_deps = root_module_direct_dev_deps, 136 **metadata_kwargs 137 )