diff --git a/config/schema/plugin.schema.yml b/config/schema/plugin.schema.yml
index cff8247..3cd443f 100644
--- a/config/schema/plugin.schema.yml
+++ b/config/schema/plugin.schema.yml
@@ -41,3 +41,8 @@ plugin.plugin_configuration.*:
       label: Plugin configuration
       type: string
   type: config_object
+
+# The "plugin_id" Views filter plugin configuration schema.
+views.filter.plugin_id:
+  type: views.filter.in_operator
+  label: 'Plugin ID'
diff --git a/modules/plugin_test_mvpbf/config/install/views.view.plugin_test_mvpbf.yml b/modules/plugin_test_mvpbf/config/install/views.view.plugin_test_mvpbf.yml
new file mode 100644
index 0000000..722c62e
--- /dev/null
+++ b/modules/plugin_test_mvpbf/config/install/views.view.plugin_test_mvpbf.yml
@@ -0,0 +1,188 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - plugin
+    - plugin_test_mvpbf
+_core:
+  default_config_hash: _T5pPzZqW19SO8ybFZhbU5wDMdfQRuwM53iD450YpHY
+id: plugin_test_mvpbf
+label: 'Multi-value plugin base field'
+module: views
+description: ''
+tag: ''
+base_table: plugin_test_mvpbf
+base_field: id
+core: 8.x
+display:
+  default:
+    display_plugin: default
+    id: default
+    display_title: Master
+    position: 0
+    display_options:
+      access:
+        type: none
+        options: {  }
+      cache:
+        type: tag
+        options: {  }
+      query:
+        type: views_query
+        options:
+          disable_sql_rewrite: false
+          distinct: false
+          replica: false
+          query_comment: ''
+          query_tags: {  }
+      exposed_form:
+        type: basic
+        options:
+          submit_button: Apply
+          reset_button: false
+          reset_button_label: Reset
+          exposed_sorts_label: 'Sort by'
+          expose_sort_order: true
+          sort_asc_label: Asc
+          sort_desc_label: Desc
+      pager:
+        type: mini
+        options:
+          items_per_page: 10
+          offset: 0
+          id: 0
+          total_pages: null
+          expose:
+            items_per_page: false
+            items_per_page_label: 'Items per page'
+            items_per_page_options: '5, 10, 25, 50'
+            items_per_page_options_all: false
+            items_per_page_options_all_label: '- All -'
+            offset: false
+            offset_label: Offset
+          tags:
+            previous: ‹‹
+            next: ››
+      style:
+        type: default
+        options:
+          grouping: {  }
+          row_class: ''
+          default_row_class: true
+          uses_fields: false
+      row:
+        type: fields
+        options:
+          inline: {  }
+          separator: ''
+          hide_empty: false
+          default_field_elements: true
+      fields:
+        rendered_entity:
+          table: plugin_test_mvpbf
+          field: rendered_entity
+          id: rendered_entity
+          entity_type: null
+          entity_field: null
+          plugin_id: rendered_entity
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: ''
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: true
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          view_mode: default
+      filters:
+        plugin__plugin_id:
+          id: plugin__plugin_id
+          table: plugin_test_mvpbf__plugin
+          field: plugin__plugin_id
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: in
+          value: {  }
+          group: 1
+          exposed: true
+          expose:
+            operator_id: plugin__plugin_id_op
+            label: 'Mock plugin ID (plugin:plugin__plugin_id)'
+            description: ''
+            use_operator: false
+            operator: plugin__plugin_id_op
+            identifier: plugin__plugin_id
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+              anonymous: '0'
+              administrator: '0'
+            reduce: false
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          entity_type: plugin_test_mvpbf
+          entity_field: plugin
+          plugin_id: plugin_id
+      sorts: {  }
+      header: {  }
+      footer: {  }
+      empty: {  }
+      relationships: {  }
+      arguments: {  }
+      display_extenders: {  }
+    cache_metadata:
+      max-age: 0
+      contexts:
+        - 'languages:language_interface'
+        - url
+        - url.query_args
+      tags: {  }
diff --git a/modules/plugin_test_mvpbf/plugin_test_mvpbf.info.yml b/modules/plugin_test_mvpbf/plugin_test_mvpbf.info.yml
new file mode 100644
index 0000000..49157be
--- /dev/null
+++ b/modules/plugin_test_mvpbf/plugin_test_mvpbf.info.yml
@@ -0,0 +1,8 @@
+name: Plugin Test (Multi-value plugin base field)
+core: 8.x
+type: module
+dependencies:
+  - plugin
+  - plugin_test_helper
+  - views
+hidden: true
diff --git a/modules/plugin_test_mvpbf/src/Entity/MultiValuePluginBaseField.php b/modules/plugin_test_mvpbf/src/Entity/MultiValuePluginBaseField.php
new file mode 100644
index 0000000..1344f66
--- /dev/null
+++ b/modules/plugin_test_mvpbf/src/Entity/MultiValuePluginBaseField.php
@@ -0,0 +1,46 @@
+<?php
+
+namespace Drupal\plugin_test_mvpbf\Entity;
+
+use Drupal\Core\Entity\ContentEntityBase;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Field\BaseFieldDefinition;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+
+/**
+ * Defines an entity with a multi-value plugin base field.
+ *
+ * @ContentEntityType(
+ *   base_table = "plugin_test_mvpbf",
+ *   handlers = {
+ *     "storage" = "Drupal\Core\Entity\Sql\SqlContentEntityStorage",
+ *     "views_data" = "Drupal\views\EntityViewsData"
+ *   },
+ *   entity_keys = {
+ *     "id" = "id",
+ *     "uuid" = "uuid",
+ *   },
+ *   id = "plugin_test_mvpbf",
+ *   label = @Translation("Multi-value value plugin base field")
+ * )
+ */
+class MultiValuePluginBaseField extends ContentEntityBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
+    $fields = parent::baseFieldDefinitions($entity_type);
+    $fields['plugin'] = BaseFieldDefinition::create('plugin:plugin_test_helper_mock')
+      ->setLabel(t('Plugin'))
+      ->setDisplayOptions('view', array(
+        'type' => 'plugin_label',
+        'weight' => 0,
+      ))
+      ->setDisplayConfigurable('view', TRUE)
+      ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
+
+    return $fields;
+  }
+
+}
diff --git a/modules/plugin_test_pcf/config/install/field.field.node.plugin_test_pcf.plugin_test_pcf.yml b/modules/plugin_test_pcf/config/install/field.field.node.plugin_test_pcf.plugin_test_pcf.yml
new file mode 100644
index 0000000..a3db0a3
--- /dev/null
+++ b/modules/plugin_test_pcf/config/install/field.field.node.plugin_test_pcf.plugin_test_pcf.yml
@@ -0,0 +1,20 @@
+langcode: en
+status: true
+dependencies:
+  config:
+    - field.storage.node.plugin_test_pcf
+    - node.type.plugin_test_pcf
+  module:
+    - plugin
+id: node.plugin_test_pcf.plugin_test_pcf
+field_name: plugin_test_pcf
+entity_type: node
+bundle: plugin_test_pcf
+label: Plugin
+description: ''
+required: false
+translatable: true
+default_value: {  }
+default_value_callback: ''
+settings: {  }
+field_type: 'plugin:plugin_test_helper_mock'
diff --git a/modules/plugin_test_pcf/config/install/field.storage.node.plugin_test_pcf.yml b/modules/plugin_test_pcf/config/install/field.storage.node.plugin_test_pcf.yml
new file mode 100644
index 0000000..edc0abb
--- /dev/null
+++ b/modules/plugin_test_pcf/config/install/field.storage.node.plugin_test_pcf.yml
@@ -0,0 +1,18 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - node
+    - plugin
+id: node.plugin_test_pcf
+field_name: plugin_test_pcf
+entity_type: node
+type: 'plugin:plugin_test_helper_mock'
+settings: {  }
+module: plugin
+locked: false
+cardinality: 1
+translatable: true
+indexes: {  }
+persist_with_no_fields: false
+custom_storage: false
diff --git a/modules/plugin_test_pcf/config/install/node.type.plugin_test_pcf.yml b/modules/plugin_test_pcf/config/install/node.type.plugin_test_pcf.yml
new file mode 100644
index 0000000..dcbe26f
--- /dev/null
+++ b/modules/plugin_test_pcf/config/install/node.type.plugin_test_pcf.yml
@@ -0,0 +1,10 @@
+langcode: en
+status: true
+dependencies: {  }
+name: Plugin configurable field
+type: plugin_test_pcf
+description: null
+help: null
+new_revision: false
+preview_mode: 1
+display_submitted: true
diff --git a/modules/plugin_test_pcf/config/install/views.view.plugin_test_pcf.yml b/modules/plugin_test_pcf/config/install/views.view.plugin_test_pcf.yml
new file mode 100644
index 0000000..d0b317e
--- /dev/null
+++ b/modules/plugin_test_pcf/config/install/views.view.plugin_test_pcf.yml
@@ -0,0 +1,206 @@
+langcode: en
+status: true
+dependencies:
+  config:
+    - node.type.plugin_test_pcf
+  module:
+    - node
+    - plugin
+    - user
+id: plugin_test_pcf
+label: 'Plugin configurable field'
+module: views
+description: ''
+tag: ''
+base_table: node_field_data
+base_field: nid
+core: 8.x
+display:
+  default:
+    display_plugin: default
+    id: default
+    display_title: Master
+    position: 0
+    display_options:
+      access:
+        type: perm
+        options:
+          perm: 'access content'
+      cache:
+        type: tag
+        options: {  }
+      query:
+        type: views_query
+        options:
+          disable_sql_rewrite: false
+          distinct: false
+          replica: false
+          query_comment: ''
+          query_tags: {  }
+      exposed_form:
+        type: basic
+        options:
+          submit_button: Apply
+          reset_button: false
+          reset_button_label: Reset
+          exposed_sorts_label: 'Sort by'
+          expose_sort_order: true
+          sort_asc_label: Asc
+          sort_desc_label: Desc
+      pager:
+        type: mini
+        options:
+          items_per_page: 10
+          offset: 0
+          id: 0
+          total_pages: null
+          expose:
+            items_per_page: false
+            items_per_page_label: 'Items per page'
+            items_per_page_options: '5, 10, 25, 50'
+            items_per_page_options_all: false
+            items_per_page_options_all_label: '- All -'
+            offset: false
+            offset_label: Offset
+          tags:
+            previous: ‹‹
+            next: ››
+      style:
+        type: default
+        options:
+          grouping: {  }
+          row_class: ''
+          default_row_class: true
+          uses_fields: false
+      row:
+        type: fields
+        options:
+          inline: {  }
+          separator: ''
+          hide_empty: false
+          default_field_elements: true
+      fields:
+        title:
+          id: title
+          table: node_field_data
+          field: title
+          entity_type: node
+          entity_field: title
+          label: ''
+          alter:
+            alter_text: false
+            make_link: false
+            absolute: false
+            trim: false
+            word_boundary: false
+            ellipsis: false
+            strip_tags: false
+            html: false
+          hide_empty: false
+          empty_zero: false
+          settings:
+            link_to_entity: true
+          plugin_id: field
+          relationship: none
+          group_type: group
+          admin_label: ''
+          exclude: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: true
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+      filters:
+        status:
+          value: true
+          table: node_field_data
+          field: status
+          plugin_id: boolean
+          entity_type: node
+          entity_field: status
+          id: status
+          expose:
+            operator: ''
+          group: 1
+        type:
+          id: type
+          table: node_field_data
+          field: type
+          value:
+            plugin_test_pcf: plugin_test_pcf
+          entity_type: node
+          entity_field: type
+          plugin_id: bundle
+        plugin_test_pcf_plugin_id:
+          id: plugin_test_pcf_plugin_id
+          table: node__plugin_test_pcf
+          field: plugin_test_pcf_plugin_id
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: in
+          value: {  }
+          group: 1
+          exposed: true
+          expose:
+            operator_id: plugin_test_pcf_plugin_id_op
+            label: 'node.plugin_test_pcf (plugin ID)'
+            description: ''
+            use_operator: false
+            operator: plugin_test_pcf_plugin_id_op
+            identifier: plugin_test_pcf_plugin_id
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+              anonymous: '0'
+              administrator: '0'
+            reduce: false
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          plugin_id: plugin_id
+      sorts: {  }
+      header: {  }
+      footer: {  }
+      empty: {  }
+      relationships: {  }
+      arguments: {  }
+      display_extenders: {  }
+    cache_metadata:
+      max-age: 0
+      contexts:
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - url
+        - url.query_args
+        - 'user.node_grants:view'
+        - user.permissions
+      tags: {  }
diff --git a/modules/plugin_test_pcf/plugin_test_pcf.info.yml b/modules/plugin_test_pcf/plugin_test_pcf.info.yml
new file mode 100644
index 0000000..f2d256e
--- /dev/null
+++ b/modules/plugin_test_pcf/plugin_test_pcf.info.yml
@@ -0,0 +1,9 @@
+name: Plugin Test (Plugin configurable field)
+core: 8.x
+type: module
+dependencies:
+  - node
+  - plugin
+  - plugin_test_helper
+  - views
+hidden: true
diff --git a/modules/plugin_test_svpbf/config/install/views.view.plugin_test_svpbf.yml b/modules/plugin_test_svpbf/config/install/views.view.plugin_test_svpbf.yml
new file mode 100644
index 0000000..a7d8fa8
--- /dev/null
+++ b/modules/plugin_test_svpbf/config/install/views.view.plugin_test_svpbf.yml
@@ -0,0 +1,185 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - plugin
+    - plugin_test_svpbf
+id: plugin_test_svpbf
+label: 'Single-value plugin base field'
+module: views
+description: ''
+tag: ''
+base_table: plugin_test_svpbf
+base_field: id
+core: 8.x
+display:
+  default:
+    display_plugin: default
+    id: default
+    display_title: Master
+    position: 0
+    display_options:
+      access:
+        type: none
+        options: {  }
+      cache:
+        type: tag
+        options: {  }
+      query:
+        type: views_query
+        options:
+          disable_sql_rewrite: false
+          distinct: false
+          replica: false
+          query_comment: ''
+          query_tags: {  }
+      exposed_form:
+        type: basic
+        options:
+          submit_button: Apply
+          reset_button: false
+          reset_button_label: Reset
+          exposed_sorts_label: 'Sort by'
+          expose_sort_order: true
+          sort_asc_label: Asc
+          sort_desc_label: Desc
+      pager:
+        type: mini
+        options:
+          items_per_page: 10
+          offset: 0
+          id: 0
+          total_pages: null
+          expose:
+            items_per_page: false
+            items_per_page_label: 'Items per page'
+            items_per_page_options: '5, 10, 25, 50'
+            items_per_page_options_all: false
+            items_per_page_options_all_label: '- All -'
+            offset: false
+            offset_label: Offset
+          tags:
+            previous: ‹‹
+            next: ››
+      style:
+        type: default
+        options:
+          grouping: {  }
+          row_class: ''
+          default_row_class: true
+          uses_fields: false
+      row:
+        type: fields
+        options:
+          inline: {  }
+          separator: ''
+          hide_empty: false
+          default_field_elements: true
+      fields:
+        rendered_entity:
+          table: plugin_test_svpbf
+          field: rendered_entity
+          id: rendered_entity
+          entity_type: null
+          entity_field: null
+          plugin_id: rendered_entity
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: ''
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: true
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          view_mode: default
+      filters:
+        plugin__plugin_id_filter:
+          id: plugin__plugin_id_filter
+          table: plugin_test_svpbf
+          field: plugin__plugin_id_filter
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: in
+          value: {  }
+          group: 1
+          exposed: true
+          expose:
+            operator_id: plugin__plugin_id_filter_op
+            label: Plugin
+            description: ''
+            use_operator: false
+            operator: plugin__plugin_id_filter_op
+            identifier: plugin__plugin_id_filter
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              anonymous: anonymous
+              authenticated: authenticated
+              administrator: '0'
+            reduce: false
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          entity_type: plugin_test_svpbf
+          plugin_id: plugin_id
+      sorts: {  }
+      header: {  }
+      footer: {  }
+      empty: {  }
+      relationships: {  }
+      arguments: {  }
+      display_extenders: {  }
+    cache_metadata:
+      max-age: 0
+      contexts:
+        - 'languages:language_interface'
+        - url
+        - url.query_args
+      tags: {  }
diff --git a/modules/plugin_test_svpbf/plugin_test_svpbf.info.yml b/modules/plugin_test_svpbf/plugin_test_svpbf.info.yml
new file mode 100644
index 0000000..c43628a
--- /dev/null
+++ b/modules/plugin_test_svpbf/plugin_test_svpbf.info.yml
@@ -0,0 +1,8 @@
+name: Plugin Test (Single-value plugin base field)
+core: 8.x
+type: module
+dependencies:
+  - plugin
+  - plugin_test_helper
+  - views
+hidden: true
diff --git a/modules/plugin_test_svpbf/src/Entity/SingleValuePluginBaseField.php b/modules/plugin_test_svpbf/src/Entity/SingleValuePluginBaseField.php
new file mode 100644
index 0000000..32d8348
--- /dev/null
+++ b/modules/plugin_test_svpbf/src/Entity/SingleValuePluginBaseField.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Drupal\plugin_test_svpbf\Entity;
+
+use Drupal\Core\Entity\ContentEntityBase;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Field\BaseFieldDefinition;
+
+/**
+ * Defines an entity with a single-value plugin base field.
+ *
+ * @ContentEntityType(
+ *   base_table = "plugin_test_svpbf",
+ *   handlers = {
+ *     "storage" = "Drupal\Core\Entity\Sql\SqlContentEntityStorage",
+ *     "views_data" = "Drupal\views\EntityViewsData"
+ *   },
+ *   entity_keys = {
+ *     "id" = "id",
+ *     "uuid" = "uuid",
+ *   },
+ *   id = "plugin_test_svpbf",
+ *   label = @Translation("Single-value value plugin base field")
+ * )
+ */
+class SingleValuePluginBaseField extends ContentEntityBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
+    $fields = parent::baseFieldDefinitions($entity_type);
+    $fields['plugin'] = BaseFieldDefinition::create('plugin:plugin_test_helper_mock')
+      ->setLabel(t('Plugin'))
+      ->setDisplayOptions('view', array(
+        'type' => 'plugin_label',
+        'weight' => 0,
+      ))
+      ->setDisplayConfigurable('view', TRUE);
+
+    return $fields;
+  }
+
+}
diff --git a/plugin.info.yml b/plugin.info.yml
index 5919998..936c03c 100644
--- a/plugin.info.yml
+++ b/plugin.info.yml
@@ -5,3 +5,4 @@ type: module
 configure: plugin.plugin_type.list
 dependencies:
   - system (>=8.0.5)
+version: 8.x-2.x
diff --git a/plugin.module b/plugin.module
index fc8387a..18dc374 100644
--- a/plugin.module
+++ b/plugin.module
@@ -5,6 +5,7 @@
  * Contains hook implementations.
  */
 
+use Drupal\field\FieldStorageConfigInterface;
 use Drupal\plugin\Plugin\Field\FieldType\PluginCollectionItemInterface;
 
 function plugin_field_info_alter(array &$field_type_definitions) {
@@ -33,6 +34,24 @@ function plugin_field_widget_info_alter(array &$field_widget_definitions) {
 }
 
 /**
+ * Implements hook_views_data_alter().
+ */
+function plugin_views_data_alter(array &$data) {
+  /** @var \Drupal\plugin\ViewsData $views_data */
+  $views_data = \Drupal::service('plugin.views_data');
+  $views_data->alterViewsData($data);
+}
+
+/**
+ * Implements hook_field_views_data_alter().
+ */
+function plugin_field_views_data_alter(array &$data, FieldStorageConfigInterface $field_storage) {
+  /** @var \Drupal\plugin\ViewsData $views_data */
+  $views_data = \Drupal::service('plugin.views_data');
+  $views_data->alterFieldViewsData($data, $field_storage);
+}
+
+/**
  * Gets the IDs of plugin item collection field types.
  *
  * @return string[]
diff --git a/plugin.services.yml b/plugin.services.yml
index 1ff1628..790fa58 100644
--- a/plugin.services.yml
+++ b/plugin.services.yml
@@ -10,3 +10,6 @@ services:
   plugin.default_plugin_resolver:
     class: Drupal\plugin\DefaultPluginResolver\EventBasedDefaultPluginResolver
     arguments: ['@event_dispatcher']
+  plugin.views_data:
+    class: Drupal\plugin\ViewsData
+    arguments: ['@entity_type.manager', '@entity_field.manager', '@plugin.plugin_type_manager']
diff --git a/src/Plugin/views/filter/PluginId.php b/src/Plugin/views/filter/PluginId.php
new file mode 100644
index 0000000..12d8107
--- /dev/null
+++ b/src/Plugin/views/filter/PluginId.php
@@ -0,0 +1,122 @@
+<?php
+
+namespace Drupal\plugin\Plugin\views\filter;
+
+use Drupal\Core\Cache\CacheableMetadata;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\plugin\PluginDefinition\PluginLabelDefinitionInterface;
+use Drupal\plugin\PluginType\PluginTypeInterface;
+use Drupal\views\Plugin\views\filter\InOperator;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a Views filter for plugin IDs.
+ *
+ * @ingroup views_filter_handlers
+ *
+ * @ViewsFilter("plugin_id")
+ */
+class PluginId extends InOperator implements ContainerFactoryPluginInterface {
+
+  /**
+   * The plugin type.
+   *
+   * @var \Drupal\plugin\PluginType\PluginTypeInterface
+   */
+  protected $pluginType;
+
+  /**
+   * Constructs a new instance.
+   *
+   * @param mixed[] $configuration
+   *   The plugin configuration.
+   * @param string $plugin_id
+   *   The plugin ID.
+   * @param mixed[] $plugin_definition
+   *   The plugin definition.
+   * @param \Drupal\plugin\PluginType\PluginTypeInterface $plugin_type
+   *   The plugin type.
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, PluginTypeInterface $plugin_type) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->pluginType = $plugin_type;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    /** @var \Drupal\plugin\PluginType\PluginTypeManagerInterface $plugin_type_manager */
+    $plugin_type_manager = $container->get('plugin.plugin_type_manager');
+
+    return new static($configuration, $plugin_id, $plugin_definition, $plugin_type_manager->getPluginType($configuration['plugin_type_id']));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getValueOptions() {
+    if (!is_null($this->valueOptions)) {
+      return $this->valueOptions;
+    }
+
+    $this->valueTitle = (string) $this->pluginType->getLabel();
+    $this->valueOptions = array_reduce($this->pluginType->getPluginManager()->getDefinitions(), function(array $value_options, $plugin_definition) {
+      $plugin_definition = $this->pluginType->ensureTypedPluginDefinition($plugin_definition);
+      $value_options[$plugin_definition->getId()] = $plugin_definition instanceof PluginLabelDefinitionInterface ? $plugin_definition->getLabel() : $plugin_definition->getId();
+      return $value_options;
+    }, []);
+    natcasesort($this->valueOptions);
+
+    return $this->valueOptions;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function valueForm(&$form, FormStateInterface $form_state) {
+    parent::valueForm($form, $form_state);
+    // Apply cacheability metadata, because the parent class does not.
+    $this->getCacheableMetadata()->applyTo($form);
+
+    return $form;
+  }
+
+  /**
+   * Gets this instance's cacheable metadata.
+   *
+   * @return \Drupal\Core\Cache\CacheableMetadata
+   */
+  protected function getCacheableMetadata() {
+    $cacheable_metadata = new CacheableMetadata();
+    $cacheable_metadata->addCacheableDependency($this->pluginType->getPluginManager());
+    $cacheable_metadata->addCacheTags(parent::getCacheTags());
+    $cacheable_metadata->addCacheContexts(parent::getCacheContexts());
+    $cacheable_metadata->mergeCacheMaxAge(parent::getCacheMaxAge());
+
+    return $cacheable_metadata;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCacheTags() {
+    return $this->getCacheableMetadata()->getCacheTags();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCacheContexts() {
+    return $this->getCacheableMetadata()->getCacheContexts();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCacheMaxAge() {
+    return $this->getCacheableMetadata()->getCacheMaxAge();
+  }
+
+}
diff --git a/src/ViewsData.php b/src/ViewsData.php
new file mode 100644
index 0000000..3f4f1f2
--- /dev/null
+++ b/src/ViewsData.php
@@ -0,0 +1,172 @@
+<?php
+
+namespace Drupal\plugin;
+
+use Drupal\Core\Entity\EntityFieldManagerInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Entity\FieldableEntityInterface;
+use Drupal\Core\Entity\Sql\SqlEntityStorageInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\field\FieldStorageConfigInterface;
+use Drupal\plugin\PluginType\PluginTypeManagerInterface;
+
+/**
+ * Provides/alters Views data.
+ */
+class ViewsData {
+
+  /**
+   * The entity field manager.
+   *
+   * @var \Drupal\Core\Entity\EntityFieldManagerInterface
+   */
+  protected $entityFieldManager;
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * The plugin type manager.
+   *
+   * @var \Drupal\plugin\PluginType\PluginTypeManagerInterface
+   */
+  protected $pluginTypeManager;
+
+  /**
+   * Constructs a new instance.
+   *
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
+   *   The entity field manager.
+   * @param \Drupal\plugin\PluginType\PluginTypeManagerInterface
+   *   The plugin type manager.
+   */
+  public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, PluginTypeManagerInterface $plugin_type_manager) {
+    $this->entityFieldManager = $entity_field_manager;
+    $this->entityTypeManager = $entity_type_manager;
+    $this->pluginTypeManager = $plugin_type_manager;
+  }
+
+  /**
+   * Implements hook_views_data_alter().
+   */
+  public function alterViewsData(array &$data) {
+    // We need to work with entity type database table mappings, which are
+    // available per entity type.
+    foreach ($this->entityTypeManager->getDefinitions() as $entity_type) {
+      // Skip non-fieldable entity types.
+      if (!$entity_type->isSubclassOf(FieldableEntityInterface::class)) {
+        continue;
+      }
+
+      $base_field_definitions = $this->entityFieldManager->getBaseFieldDefinitions($entity_type->id());
+      $entity_storage = $this->entityTypeManager
+        ->getStorage($entity_type->id());
+
+      // We cannot alter Views data if we cannot map fields to tables.
+      if (!($entity_storage instanceof SqlEntityStorageInterface)) {
+        continue;
+      }
+
+      $table_mapping = $entity_storage->getTableMapping();
+
+      // Loop through all of this entity type's stored fields.
+      foreach ($table_mapping->getTableNames() as $table_name) {
+        foreach ($table_mapping->getFieldNames($table_name) as $field_name) {
+          // Skip fields that are no base fields.
+          if (!isset($base_field_definitions[$field_name])) {
+            continue;
+          }
+
+          $base_field_storage_definition = $base_field_definitions[$field_name]->getFieldStorageDefinition();
+
+          // Skip if this is no "plugin" base field.
+          if (strpos($base_field_storage_definition->getType(), 'plugin:') !== 0) {
+            continue;
+          }
+
+          // Get the column names.
+          if ($base_field_storage_definition->getCardinality() == 1) {
+            $plugin_id_column_name = $table_mapping->getFieldColumnName($base_field_storage_definition, 'plugin_id');
+            $plugin_configuration_column_name = $table_mapping->getFieldColumnName($base_field_storage_definition, 'plugin_configuration');
+          }
+          else {
+            $plugin_id_column_name = $base_field_storage_definition->getName() . '__plugin_id';
+            $plugin_configuration_column_name = $base_field_storage_definition->getName() . '__plugin_configuration';
+          }
+
+          $this->alterPluginFieldData($data, $base_field_storage_definition, $table_name, $plugin_id_column_name, $plugin_configuration_column_name);
+        }
+      }
+    }
+  }
+
+  /**
+   * Implements hook_field_views_data_alter().
+   */
+  public function alterFieldViewsData(array &$data, FieldStorageConfigInterface $field_storage) {
+    // Alters Views data for configurable "plugin" fields.
+    if (strpos($field_storage->getType(), 'plugin:') === 0) {
+      $table_name = $field_storage->getTargetEntityTypeId() . '__' . $field_storage->getName();
+      $plugin_id_column_name = $field_storage->getName() . '_plugin_id';
+      $plugin_configuration_column_name = $field_storage->getName() . '_plugin_configuration';
+
+      // Skip if there is no Views data for this field.
+      if (!isset($data[$table_name][$plugin_id_column_name])) {
+        return;
+      }
+
+      $this->alterPluginFieldData($data, $field_storage, $table_name, $plugin_id_column_name, $plugin_configuration_column_name);
+    }
+  }
+
+  /**
+   * Alters Views data for the "plugin" field type.
+   *
+   * @param array[] $data
+   *   An array of Views data.
+   * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $field_storage_definition
+   *   The storage definition of the field to alter the data for.
+   * @param string $table_name
+   *   The name of the table to alter the data for.
+   * @param string $plugin_id_column_name
+   *   The name of the plugin ID column.
+   * @param string|null $plugin_configuration_column_name
+   *   The name of the plugin configuration column, or NULL if there is none.
+   *
+   * @throws \InvalidArgumentException
+   */
+  protected function alterPluginFieldData(array &$data, FieldStorageDefinitionInterface $field_storage_definition, $table_name, $plugin_id_column_name, $plugin_configuration_column_name = NULL) {
+    if (strpos($field_storage_definition->getType(), 'plugin:') !== 0 || !isset($data[$table_name][$plugin_id_column_name])) {
+      throw new \InvalidArgumentException('The Views data being altered is not for a "plugin" field.');
+    }
+
+    $plugin_type_id = substr($field_storage_definition->getType(), 7);
+    $plugin_type = $this->pluginTypeManager->getPluginType($plugin_type_id);
+
+    // Alter the plugin ID column.
+    /** @var \Drupal\Core\StringTranslation\TranslatableMarkup $plugin_id_old_title */
+    $plugin_id_old_title = $data[$table_name][$plugin_id_column_name]['title'];
+    $plugin_id_title_arguments = [
+      '@type_label' => $plugin_type->getLabel(),
+      '@name' => $field_storage_definition->getName(),
+      '@column' => $plugin_id_column_name,
+    ];
+    $data[$table_name][$plugin_id_column_name]['title'] = new TranslatableMarkup('@type_label ID (@name:@column)', $plugin_id_title_arguments, $plugin_id_old_title->getOptions());
+    $data[$table_name][$plugin_id_column_name]['filter']['id'] = 'plugin_id';
+    $data[$table_name][$plugin_id_column_name]['filter']['plugin_type_id'] = $plugin_type_id;
+
+    // Alter the plugin configuration column. We cannot display it, or filter by
+    // it, so we remove it to prevent confusion.
+    if ($plugin_configuration_column_name) {
+      unset($data[$table_name][$plugin_configuration_column_name]);
+    }
+  }
+
+}
diff --git a/tests/src/Functional/ViewsFilterPluginIdConfigurableFieldTest.php b/tests/src/Functional/ViewsFilterPluginIdConfigurableFieldTest.php
new file mode 100644
index 0000000..5277c50
--- /dev/null
+++ b/tests/src/Functional/ViewsFilterPluginIdConfigurableFieldTest.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Drupal\Tests\plugin\Functional;
+
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * Tests the configurable field integration of the "plugin_id" Views filter.
+ *
+ * @group Plugin
+ */
+class ViewsFilterPluginIdConfigurableFieldTest extends BrowserTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['field', 'node', 'plugin', 'plugin_test_helper', 'plugin_test_pcf', 'system', 'user', 'views'];
+
+  /**
+   * Tests the integration.
+   */
+  public function testIntegration() {
+    $entity = \Drupal::entityTypeManager()->getStorage('node')->create([
+      'type' => 'plugin_test_pcf',
+      'title' => 'Plugin configurable field',
+    ]);
+    $entity->save();
+
+    // The filter class itself is tested using unit tests. Here we just assert
+    // that a view using this filter does not break.
+    /** @var \Drupal\views\ViewEntityInterface $view */
+    $view = \Drupal::entityTypeManager()->getStorage('view')->load('plugin_test_pcf');
+    $view->getExecutable()->execute();
+    $this->assertCount(1, $view->getExecutable()->result);
+  }
+
+}
diff --git a/tests/src/Functional/ViewsFilterPluginIdMultiValueBaseFieldTest.php b/tests/src/Functional/ViewsFilterPluginIdMultiValueBaseFieldTest.php
new file mode 100644
index 0000000..1f15911
--- /dev/null
+++ b/tests/src/Functional/ViewsFilterPluginIdMultiValueBaseFieldTest.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Drupal\Tests\plugin\Functional;
+
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * Tests the multi-value base field integration of the "plugin_id" Views filter.
+ *
+ * @group Plugin
+ */
+class ViewsFilterPluginIdMultiValueBaseFieldTest extends BrowserTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['plugin', 'plugin_test_helper', 'plugin_test_mvpbf', 'system', 'views'];
+
+  /**
+   * Tests the integration.
+   */
+  public function testIntegration() {
+    $entity = \Drupal::entityTypeManager()->getStorage('plugin_test_mvpbf')->create();
+    $entity->save();
+
+    // The filter class itself is tested using unit tests. Here we just assert
+    // that a view using this filter does not break.
+    /** @var \Drupal\views\ViewEntityInterface $view */
+    $view = \Drupal::entityTypeManager()->getStorage('view')->load('plugin_test_mvpbf');
+    $view->getExecutable()->execute();
+    $this->assertCount(1, $view->getExecutable()->result);
+  }
+
+}
diff --git a/tests/src/Functional/ViewsFilterPluginIdSingleValueBaseFieldTest.php b/tests/src/Functional/ViewsFilterPluginIdSingleValueBaseFieldTest.php
new file mode 100644
index 0000000..88d6ab1
--- /dev/null
+++ b/tests/src/Functional/ViewsFilterPluginIdSingleValueBaseFieldTest.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Drupal\Tests\plugin\Functional;
+
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * Tests the single-value base field integration of the "plugin_id" Views filter.
+ *
+ * @group Plugin
+ */
+class ViewsFilterPluginIdSingleValueBaseFieldTest extends BrowserTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['plugin', 'plugin_test_helper', 'plugin_test_svpbf', 'system', 'views'];
+
+  /**
+   * Tests the integration.
+   */
+  public function testIntegration() {
+    $entity = \Drupal::entityTypeManager()->getStorage('plugin_test_svpbf')->create();
+    $entity->save();
+
+    // The filter class itself is tested using unit tests. Here we just assert
+    // that a view using this filter does not break.
+    /** @var \Drupal\views\ViewEntityInterface $view */
+    $view = \Drupal::entityTypeManager()->getStorage('view')->load('plugin_test_svpbf');
+    $view->getExecutable()->execute();
+    $this->assertCount(1, $view->getExecutable()->result);
+  }
+
+}
diff --git a/tests/src/Unit/Plugin/views/filter/PluginIdTest.php b/tests/src/Unit/Plugin/views/filter/PluginIdTest.php
new file mode 100644
index 0000000..feda71f
--- /dev/null
+++ b/tests/src/Unit/Plugin/views/filter/PluginIdTest.php
@@ -0,0 +1,208 @@
+<?php
+
+namespace Drupal\plugin\Tests\Unit\Plugin\views\filter;
+
+use Drupal\Component\Plugin\PluginManagerInterface;
+use Drupal\Core\Cache\Cache;
+use Drupal\Core\Cache\CacheableDependencyInterface;
+use Drupal\plugin\Plugin\views\filter\PluginId;
+use Drupal\plugin\PluginDefinition\PluginDefinitionInterface;
+use Drupal\plugin\PluginDefinition\PluginLabelDefinitionInterface;
+use Drupal\plugin\PluginType\PluginTypeInterface;
+use Drupal\plugin\PluginType\PluginTypeManagerInterface;
+use Drupal\Tests\UnitTestCase;
+use Prophecy\Argument;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * @coversDefaultClass \Drupal\plugin\Plugin\views\filter\PluginId
+ *
+ * @group Plugin
+ */
+class PluginIdTest extends UnitTestCase {
+
+  /**
+   * The plugin type.
+   *
+   * @var \Drupal\plugin\PluginType\PluginTypeInterface|\Prophecy\Prophecy\ObjectProphecy
+   */
+  protected $pluginType;
+
+  /**
+   * The system under test.
+   *
+   * @var \Drupal\plugin\Plugin\views\filter\PluginId
+   */
+  protected $sut;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+
+    $plugin_type_id = 'foo_bar';
+    $plugin_id = '';
+    $plugin_definition = [
+      'id' => $plugin_id,
+    ];
+    $configuration = [
+      'plugin_type_id' => $plugin_type_id,
+    ];
+
+    $this->pluginType = $this->prophesize(PluginTypeInterface::class);
+
+    $this->sut = new PluginId($configuration, $plugin_id, $plugin_definition, $this->pluginType->reveal());
+  }
+
+  /**
+   * @covers ::create
+   * @covers ::__construct
+   */
+  public function testCreate() {
+    $plugin_type_id = 'foo_bar';
+    $plugin_id = '';
+    $plugin_definition = [
+      'id' => $plugin_id,
+    ];
+    $configuration = [
+      'plugin_type_id' => $plugin_type_id,
+    ];
+
+    $plugin_type_manager = $this->prophesize(PluginTypeManagerInterface::class);
+    $plugin_type_manager->getPluginType($plugin_type_id)->wilLReturn($this->pluginType->reveal());
+
+    $container = $this->prophesize(ContainerInterface::class);
+    $container->get('plugin.plugin_type_manager')->willReturn($plugin_type_manager->reveal());
+
+    $this->sut = PluginId::create($container->reveal(), $configuration, $plugin_id, $plugin_definition);
+    $this->assertInstanceOf(PluginId::class, $this->sut);
+  }
+
+  /**
+   * @covers ::getCacheContexts
+   * @covers ::getCacheableMetadata
+   */
+  public function testCacheContexts() {
+    $plugin_manager_cache_contexts = ['dog', 'ball'];
+
+    $plugin_manager = $this->prophesize(CacheableDependencyPluginManagerInterface::class);
+    $plugin_manager->getCacheContexts()->willReturn($plugin_manager_cache_contexts);
+    $plugin_manager->getCacheTags()->willReturn([]);
+    $plugin_manager->getCacheMaxAge()->willReturn(0);
+
+    $this->pluginType->getPluginManager()->willReturn($plugin_manager->reveal());
+
+    // Temporarily disable asserts, because Cache::mergeContexts() calls
+    // \Drupal::service(). See https://www.drupal.org/node/2720947.
+    assert_options(ASSERT_ACTIVE, FALSE);
+    $cache_contexts = $this->sut->getCacheContexts();
+    $this->assertInternalType('array', $cache_contexts);
+    foreach ($plugin_manager_cache_contexts as $plugin_manager_cache_context) {
+      $this->assertTrue(in_array($plugin_manager_cache_context, $cache_contexts));
+    }
+    assert_options(ASSERT_ACTIVE, TRUE);
+  }
+
+  /**
+   * @covers ::getCacheTags
+   * @covers ::getCacheableMetadata
+   */
+  public function testCacheTags() {
+    $plugin_manager_cache_tags = ['bar', 'foo'];
+
+    $plugin_manager = $this->prophesize(CacheableDependencyPluginManagerInterface::class);
+    $plugin_manager->getCacheContexts()->willReturn([]);
+    $plugin_manager->getCacheTags()->willReturn($plugin_manager_cache_tags);
+    $plugin_manager->getCacheMaxAge()->willReturn(0);
+
+    $this->pluginType->getPluginManager()->willReturn($plugin_manager->reveal());
+
+    $this->assertArraySubset($plugin_manager_cache_tags, $this->sut->getCacheTags());
+  }
+
+  /**
+   * @covers ::getCacheMaxAge
+   * @covers ::getCacheableMetadata
+   *
+   * @dataProvider provideCacheMaxAge
+   */
+  public function testCacheMaxAge($expected, $plugin_manager_max_age) {
+    $plugin_manager = $this->prophesize(CacheableDependencyPluginManagerInterface::class);
+    $plugin_manager->getCacheContexts()->willReturn([]);
+    $plugin_manager->getCacheTags()->willReturn([]);
+    $plugin_manager->getCacheMaxAge()->willReturn($plugin_manager_max_age);
+
+    $this->pluginType->getPluginManager()->willReturn($plugin_manager->reveal());
+
+    $this->assertSame($expected, $this->sut->getCacheMaxAge());
+  }
+
+  /**
+   * Provides data to self::testCacheMaxAge().
+   */
+  public function provideCacheMaxAge() {
+    $data = [];
+
+    $data['plugin-manager-permanent'] = [Cache::PERMANENT, Cache::PERMANENT];
+    $data['plugin-manager-never'] = [0, 0];
+    $data['plugin-manager-limited'] = [7, 7];
+
+    return $data;
+  }
+
+  /**
+   * @covers ::getValueOptions
+   * @covers ::getCacheableMetadata
+   */
+  public function testGetValueOptions() {
+    $plugin_label_1 = 'Foo';
+    $plugin_id_1 = 'aaa_foo';
+    $plugin_id_2 = 'baz';
+    $plugin_id_3 = 'qux';
+    $plugin_label_4 = 'Bar';
+    $plugin_id_4 = 'zzz_bar';
+
+    // Values must be sorted naturally.
+    $expected = [
+      $plugin_id_4 => $plugin_label_4,
+      $plugin_id_2 => $plugin_id_2,
+      $plugin_id_1 => $plugin_label_1,
+      $plugin_id_3 => $plugin_id_3,
+    ];
+
+    $plugin_definition_1 = $this->prophesize(PluginLabelDefinitionInterface::class);
+    $plugin_definition_1->getId()->willReturn($plugin_id_1);
+    $plugin_definition_1->getLabel()->willReturn($plugin_label_1);
+    $plugin_definition_2 = $this->prophesize(PluginDefinitionInterface::class);
+    $plugin_definition_2->getId()->willReturn($plugin_id_2);
+    $plugin_definition_3 = $this->prophesize(PluginDefinitionInterface::class);
+    $plugin_definition_3->getId()->willReturn($plugin_id_3);
+    $plugin_definition_4 = $this->prophesize(PluginLabelDefinitionInterface::class);
+    $plugin_definition_4->getId()->willReturn($plugin_id_4);
+    $plugin_definition_4->getLabel()->willReturn($plugin_label_4);
+
+    $plugin_definitions = [
+      $plugin_id_1 => $plugin_definition_1,
+      $plugin_id_2 => $plugin_definition_2,
+      $plugin_id_3 => $plugin_definition_3,
+      $plugin_id_4 => $plugin_definition_4,
+    ];
+
+    $plugin_manager = $this->prophesize(PluginManagerInterface::class);
+    $plugin_manager->getDefinitions()->willReturn($plugin_definitions);
+
+    $this->pluginType->ensureTypedPluginDefinition(Argument::any())->willReturnArgument();
+    $this->pluginType->getPluginManager()->willReturn($plugin_manager);
+
+    $this->assertSame($expected, $this->sut->getValueOptions());
+  }
+
+
+}
+
+/**
+ * Defines a plugin manager which is also a cacheable dependency.
+ */
+interface CacheableDependencyPluginManagerInterface extends PluginManagerInterface, CacheableDependencyInterface {
+}
