/**
  * Add a Skylark transitive info. The provider value must be safe (i.e. a String, a Boolean, an
  * Integer, an Artifact, a Label, None, a Java TransitiveInfoProvider or something composed from
  * these in Skylark using lists, sets, structs or dicts). Otherwise an EvalException is thrown.
  */
 public RuleConfiguredTargetBuilder addSkylarkTransitiveInfo(
     String name, Object value, Location loc) throws EvalException {
   try {
     checkSkylarkObjectSafe(value);
   } catch (IllegalArgumentException e) {
     throw new EvalException(
         loc,
         String.format("Value of provider '%s' is of an illegal type: %s", name, e.getMessage()));
   }
   skylarkProviders.put(name, value);
   return this;
 }
 private void checkCompositeSkylarkObjectSafe(Object object) {
   if (object instanceof SkylarkApiProvider) {
     return;
   } else if (object instanceof SkylarkList) {
     SkylarkList list = (SkylarkList) object;
     if (list == SkylarkList.EMPTY_LIST
         || isSimpleSkylarkObjectSafe(list.getContentType().getType())) {
       // Try not to iterate over the list if avoidable.
       return;
     }
     // The list can be a tuple or a list of composite items.
     for (Object listItem : list) {
       checkSkylarkObjectSafe(listItem);
     }
     return;
   } else if (object instanceof SkylarkNestedSet) {
     // SkylarkNestedSets cannot have composite items.
     Class<?> contentType = ((SkylarkNestedSet) object).getContentType().getType();
     if (!contentType.equals(Object.class) && !isSimpleSkylarkObjectSafe(contentType)) {
       throw new IllegalArgumentException(EvalUtils.getDataTypeName(contentType));
     }
     return;
   } else if (object instanceof Map<?, ?>) {
     for (Map.Entry<?, ?> entry : ((Map<?, ?>) object).entrySet()) {
       checkSkylarkObjectSafe(entry.getKey());
       checkSkylarkObjectSafe(entry.getValue());
     }
     return;
   } else if (object instanceof ClassObject) {
     ClassObject struct = (ClassObject) object;
     for (String key : struct.getKeys()) {
       checkSkylarkObjectSafe(struct.getValue(key));
     }
     return;
   }
   throw new IllegalArgumentException(EvalUtils.getDataTypeName(object));
 }
 /** Add a Skylark transitive info. The provider value must be safe. */
 public RuleConfiguredTargetBuilder addSkylarkTransitiveInfo(String name, Object value) {
   checkSkylarkObjectSafe(value);
   skylarkProviders.put(name, value);
   return this;
 }