/**
  * Returns {@code true} for declarations that this formatter can format. Specifically:
  *
  * <ul>
  *   <li>Those with {@linkplain BindingDeclaration#bindingElement() binding elements} that are
  *       methods, constructors, or types.
  *   <li>{@link ContributionBinding.Kind#SYNTHETIC_RELEASABLE_REFERENCE_MANAGER} bindings.
  *   <li>{@link ContributionBinding.Kind#SYNTHETIC_RELEASABLE_REFERENCE_MANAGERS} bindings.
  * </ul>
  */
 boolean canFormat(BindingDeclaration bindingDeclaration) {
   if (bindingDeclaration instanceof SubcomponentDeclaration) {
     return true;
   }
   if (bindingDeclaration.bindingElement().isPresent()) {
     return FORMATTABLE_ELEMENT_TYPE_KINDS.contains(
         bindingDeclaration.bindingElement().get().asType().getKind());
   }
   if (bindingDeclaration instanceof ContributionBinding) {
     ContributionBinding contributionBinding = (ContributionBinding) bindingDeclaration;
     return FORMATTABLE_ELEMENTLESS_BINDING_KINDS.contains(contributionBinding.bindingKind());
   }
   return false;
 }
  @Override
  public String format(BindingDeclaration bindingDeclaration) {
    if (bindingDeclaration instanceof SubcomponentDeclaration) {
      return formatSubcomponentDeclaration((SubcomponentDeclaration) bindingDeclaration);
    }

    if (bindingDeclaration instanceof ContributionBinding) {
      ContributionBinding binding = (ContributionBinding) bindingDeclaration;
      switch (binding.bindingKind()) {
        case SYNTHETIC_RELEASABLE_REFERENCE_MANAGER:
          return String.format(
              "binding for %s from the scope declaration",
              stripCommonTypePrefixes(keyFormatter.format(binding.key())));
        case SYNTHETIC_RELEASABLE_REFERENCE_MANAGERS:
          return String.format(
              "Dagger-generated binding for %s",
              stripCommonTypePrefixes(keyFormatter.format(binding.key())));
        default:
          break;
      }
    }

    checkArgument(
        bindingDeclaration.bindingElement().isPresent(),
        "Cannot format bindings without source elements: %s",
        bindingDeclaration);

    Element bindingElement = bindingDeclaration.bindingElement().get();
    switch (bindingElement.asType().getKind()) {
      case EXECUTABLE:
        return methodSignatureFormatter.format(
            MoreElements.asExecutable(bindingElement),
            bindingDeclaration
                .contributingModule()
                .map(module -> MoreTypes.asDeclared(module.asType())));
      case DECLARED:
        return stripCommonTypePrefixes(bindingElement.asType().toString());
      default:
        throw new IllegalArgumentException("Formatting unsupported for element: " + bindingElement);
    }
  }