protected function addPluginTypeServiceData(&$data) {
    // Get a reflection for the plugin manager service.
    $service = \Drupal::service($data['service_id']);
    $reflection = new \ReflectionClass($service);

    // Determine the alter hook name.
    if ($reflection->hasProperty('alterHook')) {
      $property_alter_hook = $reflection->getProperty('alterHook');
      $property_alter_hook->setAccessible(TRUE);
      $alter_hook_name = $property_alter_hook->getValue($service);
      if (!empty($alter_hook_name)) {
        $data['alter_hook_name'] = $alter_hook_name . '_alter';
      }
    }

    // Determine the plugin discovery type.
    // Get the discovery object from the plugin manager.
    $method_getDiscovery = $reflection->getMethod('getDiscovery');
    $method_getDiscovery->setAccessible(TRUE);
    $discovery = $method_getDiscovery->invoke($service);
    $class_dicovery = new \ReflectionClass($discovery);

    // This is typically decorated at least once, for derivative discover.
    // Ascend up the chain of decorated objects to the innermost discovery
    // object.
    while ($class_dicovery->hasProperty('decorated')) {
      $property_decorated = $class_dicovery->getProperty('decorated');
      $property_decorated->setAccessible(TRUE);
      $discovery = $property_decorated->getValue($discovery);
      $class_dicovery = new \ReflectionClass($discovery);
    }

    $inner_discovery_class = get_class($discovery);

    // See if the plugin type's discovery class inherits from one of the ones
    // we handle.
    $known_discovery_classes = [
      'Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery',
      'Drupal\Core\Plugin\Discovery\YamlDiscovery',
      // We don't handle this type; only migrations use it. But we don't want
      // to ascend the class hierarchy for this type as then we'll get
      // YamlDiscovery and the analysis for that will fail.
      'Drupal\Core\Plugin\Discovery\YamlDirectoryDiscovery',
    ];

    if (in_array($inner_discovery_class, $known_discovery_classes)) {
      $data['discovery'] = $inner_discovery_class;
    }
    else {
      $discovery_class = $inner_discovery_class;
      while ($discovery_class = get_parent_class($discovery_class)) {
        if (in_array($discovery_class, $known_discovery_classes)) {
          $data['discovery'] = $discovery_class;
          break;
        }
      }

      // We didn't find a class we know in the parents: just set the inner
      // discovery class.
      if (!isset($data['discovery'])) {
        $data['discovery'] = $inner_discovery_class;
      }
    }

    // Get more data from the service, depending on the discovery type of the
    // plugin.
    $discovery_pieces = explode('\\', $data['discovery']);
    $discovery_short_name = array_pop($discovery_pieces);

    // Add in empty properties from the different discovery types analyses so
    // they are always present.
    $discovery_dependent_properties = [
      'subdir',
      'plugin_interface',
      'plugin_definition_annotation_name',
      'yaml_file_suffix',
      'yaml_properties',
      'annotation_id_only',
    ];
    foreach ($discovery_dependent_properties as $property) {
      $data[$property] = NULL;
    }

    switch ($discovery_short_name) {
      case 'AnnotatedClassDiscovery':
        $this->addPluginTypeServiceDataAnnotated($data, $service, $discovery);
        break;
      case 'YamlDiscovery':
        $this->addPluginTypeServiceDataYaml($data, $service, $discovery);
        break;
    }
  }