# Copyright 2023 The Bazel Authors. 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("@bazel_features//:features.bzl", "bazel_features") visibility([ "//tests/bzlmod/...", ]) # structs have certain built-in methods or attributes that should not # be overwritten. Load these by calling `dir` on an empty struct. # e.g. ["to_proto", "to_json"] _STRUCT_PROTECTED_ATTRIBUTES = dir(struct()) def drop_nones(dict): """Drop entries with None values from a dictionary. Args: dict: A dictionary. Returns: A new dictionary with the same keys as dict, but with entries with None values removed. """ return {k: v for k, v in dict.items() if v != None} def format_rule_call(_kind, **attrs): """Format a rule call. Args: _kind: The kind of the rule. attrs: The attributes of the rule. The attributes are sorted by name, except for the "name" attribute, which is always first. None values are ignored. Returns: A string representing the rule call. """ lines = [_kind + "("] for attr, value in sorted(attrs.items(), key = _attrs_sort_key): if value == None: continue lines.append(" {} = {},".format(attr, repr(value))) lines.append(")") return "\n".join(lines) def _attrs_sort_key(entry): """Sort key for attributes. Attributes are sorted by name, except for the "name" attribute, which is always first. Args: entry: A tuple of (attribute name, attribute value). Returns: An opaque sort key. """ attr, _ = entry if attr == "name": # Sort "name" first. return "" return attr def get_directive_value(directives, key): """Get the value of a directive. Args: directives: A list of directives. key: The key of the directive. Returns: The value of the last directive, or None if the directive is not present. """ prefix = "gazelle:" + key + " " value = None for directive in directives: if directive.startswith(prefix): # Treat "gazelle:key value" the same as "gazelle:key value". value = directive[len(prefix):].lstrip() return value def with_replaced_or_new_fields(_struct, **replacements): """Provides a shallow copy of a structure with replacements and/or new fields Args: _struct: structure to shallow copy. **replacements: kwargs for fields to either replace or add to the new struct. Returns: The resulting updated structure. """ new_struct_assignments = { key: getattr(_struct, key) for key in dir(_struct) if key not in _STRUCT_PROTECTED_ATTRIBUTES } # Overwrite existing fields and add new ones. for key, value in replacements.items(): new_struct_assignments[key] = value return struct(**new_struct_assignments) def extension_metadata( module_ctx, *, root_module_direct_deps = None, root_module_direct_dev_deps = None, reproducible = False): if not hasattr(module_ctx, "extension_metadata"): return None metadata_kwargs = {} if bazel_features.external_deps.extension_metadata_has_reproducible: metadata_kwargs["reproducible"] = reproducible return module_ctx.extension_metadata( root_module_direct_deps = root_module_direct_deps, root_module_direct_dev_deps = root_module_direct_dev_deps, **metadata_kwargs )