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      )