From 23fad5b6a5f866a1a095899fc56c9c341e9a373e Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Mon, 3 Jun 2019 12:49:38 +0100
Subject: [PATCH] Issue #2926068 by almaudoh, andypost, voleger,
 claudiu.cristea, Oleksiy, YurkinPark, yo30, alexpott, dawehner, Berdir:
 Deprecate system_rebuild_module_data() and remove usages in core

---
 core/core.services.yml                        |  4 +-
 core/includes/common.inc                      |  2 +-
 core/includes/install.core.inc                |  8 ++--
 core/includes/update.inc                      |  2 +-
 .../lib/Drupal/Core/Config/ConfigImporter.php | 22 ++++++++++-
 .../ConfigImportSubscriber.php                | 28 +++++---------
 .../Drupal/Core/Extension/ModuleInstaller.php |  6 ++-
 .../RequiredModuleUninstallValidator.php      | 20 ++++++++--
 .../tests/src/Kernel/BookUninstallTest.php    |  2 +-
 .../src/Form/ConfigSingleImportForm.php       | 19 ++++++++--
 core/modules/config/src/Form/ConfigSync.php   | 19 ++++++++--
 .../src/Functional/ConfigImportAllTest.php    |  4 +-
 .../src/Functional/ConfigImportUITest.php     |  2 +-
 .../ConfigUninstallViaCliImportTest.php       |  3 +-
 .../ContentTranslationConfigImportTest.php    |  3 +-
 .../Kernel/FieldDefinitionIntegrityTest.php   |  2 +-
 .../tests/src/Functional/FilterFormTest.php   |  2 -
 .../filter/tests/src/Kernel/FilterAPITest.php |  2 +-
 .../help/tests/src/Functional/HelpTest.php    |  2 +-
 .../tests/src/Kernel/HelpEmptyPageTest.php    |  2 +-
 .../tests/src/Functional/TestCoverageTest.php |  2 +-
 .../src/Kernel/OverriddenConfigImportTest.php |  3 +-
 core/modules/locale/locale.compare.inc        |  2 +-
 .../EntityResourceRestTestCoverageTest.php    |  2 +-
 .../system/src/Form/ModulesListForm.php       | 22 +++++++++--
 .../src/Form/ModulesUninstallConfirmForm.php  | 18 +++++++--
 .../system/src/Form/ModulesUninstallForm.php  | 23 ++++++++---
 core/modules/system/system.install            |  2 +-
 core/modules/system/system.module             |  9 ++++-
 .../Module/InstallUninstallTest.php           |  2 +-
 .../Kernel/Extension/ModuleHandlerTest.php    |  8 +---
 .../tests/src/Kernel/System/InfoAlterTest.php |  4 +-
 .../src/Kernel/SystemFunctionsLegacyTest.php  | 28 ++++++++++++++
 core/modules/update/src/UpdateManager.php     | 20 +++++++++-
 .../src/Functional/UpdateContribTest.php      |  2 +-
 core/modules/update/update.services.yml       |  2 +-
 core/modules/user/src/PermissionHandler.php   |  9 -----
 .../tests/src/Unit/PermissionHandlerTest.php  | 38 +++----------------
 ...solvedLibraryDefinitionsFilesMatchTest.php |  2 +-
 .../Core/Bootstrap/GetFilenameTest.php        |  2 -
 .../Core/Config/ConfigDependencyTest.php      | 12 ------
 .../Core/Config/ConfigImportRecreateTest.php  |  3 +-
 .../ConfigImportRenameValidationTest.php      |  3 +-
 .../ConfigImporterMissingContentTest.php      |  3 +-
 .../Core/Config/ConfigImporterTest.php        |  3 +-
 .../Entity/ContentEntityNullStorageTest.php   |  3 +-
 .../Extension/ModuleConfigureRouteTest.php    |  2 +-
 .../Core/Extension/ModuleInstallerTest.php    |  9 -----
 .../Core/Theme/StableLibraryOverrideTest.php  |  2 +-
 .../Core/Theme/StableTemplateOverrideTest.php |  5 +--
 .../Core/Theme/ThemeInstallerTest.php         |  4 +-
 core/tests/Drupal/Tests/ConfigTestTrait.php   |  3 +-
 52 files changed, 242 insertions(+), 164 deletions(-)
 create mode 100644 core/modules/system/tests/src/Kernel/SystemFunctionsLegacyTest.php

diff --git a/core/core.services.yml b/core/core.services.yml
index 6a410c62440f..cd647713cbae 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -536,7 +536,7 @@ services:
     class: Drupal\Core\Extension\RequiredModuleUninstallValidator
     tags:
       - { name: module_install.uninstall_validator }
-    arguments: ['@string_translation']
+    arguments: ['@string_translation', '@extension.list.module']
     lazy: true
   theme_handler:
     class: Drupal\Core\Extension\ThemeHandler
@@ -1265,7 +1265,7 @@ services:
     class: Drupal\Core\EventSubscriber\ConfigImportSubscriber
     tags:
       - { name: event_subscriber }
-    arguments: ['@theme_handler']
+    arguments: ['@theme_handler', '@extension.list.module']
   config_snapshot_subscriber:
     class: Drupal\Core\EventSubscriber\ConfigSnapshotSubscriber
     tags:
diff --git a/core/includes/common.inc b/core/includes/common.inc
index bc76bf774b94..c3f4190bf5e4 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -1133,7 +1133,7 @@ function drupal_flush_all_caches() {
   \Drupal::service('twig')->invalidate();
 
   // Rebuild module and theme data.
-  $module_data = system_rebuild_module_data();
+  $module_data = \Drupal::service('extension.list.module')->reset()->getList();
   /** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */
   $theme_handler = \Drupal::service('theme_handler');
   $theme_handler->refreshInfo();
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 92bf908e7ace..5258b5d19b9f 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1578,7 +1578,7 @@ function install_profile_modules(&$install_state) {
   install_core_entity_type_definitions();
 
   $modules = \Drupal::state()->get('install_profile_modules') ?: [];
-  $files = system_rebuild_module_data();
+  $files = \Drupal::service('extension.list.module')->getList();
   \Drupal::state()->delete('install_profile_modules');
 
   // Always install required modules first. Respect the dependencies between
@@ -2350,7 +2350,8 @@ function install_config_import_batch() {
     \Drupal::service('module_handler'),
     \Drupal::service('module_installer'),
     \Drupal::service('theme_handler'),
-    \Drupal::service('string_translation')
+    \Drupal::service('string_translation'),
+    \Drupal::service('extension.list.module')
   );
 
   try {
@@ -2421,7 +2422,8 @@ function install_config_revert_install_changes() {
       \Drupal::service('module_handler'),
       \Drupal::service('module_installer'),
       \Drupal::service('theme_handler'),
-      \Drupal::service('string_translation')
+      \Drupal::service('string_translation'),
+      \Drupal::service('extension.list.module')
     );
     try {
       $config_importer->import();
diff --git a/core/includes/update.inc b/core/includes/update.inc
index 2021a6623144..4f34dbd4acd8 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -48,7 +48,7 @@ function update_check_incompatibility($name, $type = 'module') {
     // code changes that were made in the filesystem before the update script
     // was initiated.
     $themes = \Drupal::service('theme_handler')->rebuildThemeData();
-    $modules = system_rebuild_module_data();
+    $modules = \Drupal::service('extension.list.module')->reset()->getList();
   }
 
   if ($type == 'module' && isset($modules[$name])) {
diff --git a/core/lib/Drupal/Core/Config/ConfigImporter.php b/core/lib/Drupal/Core/Config/ConfigImporter.php
index 4dced73e15bf..91317c27f8a5 100644
--- a/core/lib/Drupal/Core/Config/ConfigImporter.php
+++ b/core/lib/Drupal/Core/Config/ConfigImporter.php
@@ -3,6 +3,7 @@
 namespace Drupal\Core\Config;
 
 use Drupal\Core\Config\Importer\MissingContentEvent;
+use Drupal\Core\Extension\ModuleExtensionList;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Extension\ModuleInstallerInterface;
 use Drupal\Core\Extension\ThemeHandlerInterface;
@@ -158,6 +159,13 @@ class ConfigImporter {
    */
   protected $moduleInstaller;
 
+  /**
+   * The module extension list.
+   *
+   * @var \Drupal\Core\Extension\ModuleExtensionList
+   */
+  protected $moduleExtensionList;
+
   /**
    * Constructs a configuration import object.
    *
@@ -180,8 +188,18 @@ class ConfigImporter {
    *   The theme handler
    * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
    *   The string translation service.
+   * @param \Drupal\Core\Extension\ModuleExtensionList|null $extension_list_module
+   *   The module extension list. This is left optional for BC reasons, but the
+   *   optional usage is deprecated and will become required in Drupal 9.0.0.
+   *
+   * @todo Remove null default value https://www.drupal.org/node/2947083
    */
-  public function __construct(StorageComparerInterface $storage_comparer, EventDispatcherInterface $event_dispatcher, ConfigManagerInterface $config_manager, LockBackendInterface $lock, TypedConfigManagerInterface $typed_config, ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, ThemeHandlerInterface $theme_handler, TranslationInterface $string_translation) {
+  public function __construct(StorageComparerInterface $storage_comparer, EventDispatcherInterface $event_dispatcher, ConfigManagerInterface $config_manager, LockBackendInterface $lock, TypedConfigManagerInterface $typed_config, ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, ThemeHandlerInterface $theme_handler, TranslationInterface $string_translation, ModuleExtensionList $extension_list_module = NULL) {
+    if ($extension_list_module === NULL) {
+      @trigger_error('Invoking the ConfigImporter constructor without the module extension list parameter is deprecated in Drupal 8.8.0 and will no longer be supported in Drupal 9.0.0. The extension list parameter is now required in the ConfigImporter constructor. See https://www.drupal.org/node/2943918', E_USER_DEPRECATED);
+      $extension_list_module = \Drupal::service('extension.list.module');
+    }
+    $this->moduleExtensionList = $extension_list_module;
     $this->storageComparer = $storage_comparer;
     $this->eventDispatcher = $event_dispatcher;
     $this->configManager = $config_manager;
@@ -369,7 +387,7 @@ protected function createExtensionChangelist() {
     }
 
     // Get a list of modules with dependency weights as values.
-    $module_data = system_rebuild_module_data();
+    $module_data = $this->moduleExtensionList->getList();
     // Set the actual module weights.
     $module_list = array_combine(array_keys($module_data), array_keys($module_data));
     $module_list = array_map(function ($module) use ($module_data) {
diff --git a/core/lib/Drupal/Core/EventSubscriber/ConfigImportSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ConfigImportSubscriber.php
index c0e3a4a2c8b4..7f2f35c32ba4 100644
--- a/core/lib/Drupal/Core/EventSubscriber/ConfigImportSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/ConfigImportSubscriber.php
@@ -7,6 +7,7 @@
 use Drupal\Core\Config\ConfigImporterEvent;
 use Drupal\Core\Config\ConfigImportValidateEventSubscriberBase;
 use Drupal\Core\Config\ConfigNameException;
+use Drupal\Core\Extension\ModuleExtensionList;
 use Drupal\Core\Extension\ThemeHandlerInterface;
 
 /**
@@ -22,11 +23,11 @@ class ConfigImportSubscriber extends ConfigImportValidateEventSubscriberBase {
   protected $themeData;
 
   /**
-   * Module data.
+   * Module extension list.
    *
-   * @var \Drupal\Core\Extension\Extension[]
+   * @var \Drupal\Core\Extension\ModuleExtensionList
    */
-  protected $moduleData;
+  protected $moduleExtensionList;
 
   /**
    * The theme handler.
@@ -40,9 +41,12 @@ class ConfigImportSubscriber extends ConfigImportValidateEventSubscriberBase {
    *
    * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
    *   The theme handler.
+   * @param \Drupal\Core\Extension\ModuleExtensionList $extension_list_module
+   *   The module extension list.
    */
-  public function __construct(ThemeHandlerInterface $theme_handler) {
+  public function __construct(ThemeHandlerInterface $theme_handler, ModuleExtensionList $extension_list_module) {
     $this->themeHandler = $theme_handler;
+    $this->moduleExtensionList = $extension_list_module;
   }
 
   /**
@@ -108,7 +112,7 @@ protected function validateModules(ConfigImporter $config_importer) {
     }
 
     // Get a list of modules with dependency weights as values.
-    $module_data = $this->getModuleData();
+    $module_data = $this->moduleExtensionList->getList();
     $nonexistent_modules = array_keys(array_diff_key($core_extension['module'], $module_data));
     foreach ($nonexistent_modules as $module) {
       $config_importer->logError($this->t('Unable to install the %module module since it does not exist.', ['%module' => $module]));
@@ -214,7 +218,7 @@ protected function validateDependencies(ConfigImporter $config_importer) {
     ];
 
     $theme_data = $this->getThemeData();
-    $module_data = $this->getModuleData();
+    $module_data = $this->moduleExtensionList->getList();
 
     // Validate the dependencies of all the configuration. We have to validate
     // the entire tree because existing configuration might depend on
@@ -310,18 +314,6 @@ protected function getThemeData() {
     return $this->themeData;
   }
 
-  /**
-   * Gets module data.
-   *
-   * @return \Drupal\Core\Extension\Extension[]
-   */
-  protected function getModuleData() {
-    if (!isset($this->moduleData)) {
-      $this->moduleData = system_rebuild_module_data();
-    }
-    return $this->moduleData;
-  }
-
   /**
    * Gets human readable extension names.
    *
diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
index 77908407e5b4..5246946e097b 100644
--- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php
+++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
@@ -83,7 +83,9 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
     $extension_config = \Drupal::configFactory()->getEditable('core.extension');
     if ($enable_dependencies) {
       // Get all module data so we can find dependencies and sort.
-      $module_data = system_rebuild_module_data();
+      // The module list needs to be reset so that it can re-scan and include
+      // any new modules that may have been added directly into the filesystem.
+      $module_data = \Drupal::service('extension.list.module')->reset()->getList();
       $module_list = $module_list ? array_combine($module_list, $module_list) : [];
       if ($missing_modules = array_diff_key($module_list, $module_data)) {
         // One or more of the given modules doesn't exist.
@@ -335,7 +337,7 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
    */
   public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
     // Get all module data so we can find dependencies and sort.
-    $module_data = system_rebuild_module_data();
+    $module_data = \Drupal::service('extension.list.module')->getList();
     $module_list = $module_list ? array_combine($module_list, $module_list) : [];
     if (array_diff_key($module_list, $module_data)) {
       // One or more of the given modules doesn't exist.
diff --git a/core/lib/Drupal/Core/Extension/RequiredModuleUninstallValidator.php b/core/lib/Drupal/Core/Extension/RequiredModuleUninstallValidator.php
index d3fa533e934a..dc5f999f167b 100644
--- a/core/lib/Drupal/Core/Extension/RequiredModuleUninstallValidator.php
+++ b/core/lib/Drupal/Core/Extension/RequiredModuleUninstallValidator.php
@@ -12,14 +12,24 @@ class RequiredModuleUninstallValidator implements ModuleUninstallValidatorInterf
 
   use StringTranslationTrait;
 
+  /**
+   * The module extension list.
+   *
+   * @var \Drupal\Core\Extension\ModuleExtensionList
+   */
+  protected $moduleExtensionList;
+
   /**
    * Constructs a new RequiredModuleUninstallValidator.
    *
    * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
    *   The string translation service.
+   * @param \Drupal\Core\Extension\ModuleExtensionList $extension_list_module
+   *   The module extension list.
    */
-  public function __construct(TranslationInterface $string_translation) {
+  public function __construct(TranslationInterface $string_translation, ModuleExtensionList $extension_list_module) {
     $this->stringTranslation = $string_translation;
+    $this->moduleExtensionList = $extension_list_module;
   }
 
   /**
@@ -41,11 +51,13 @@ public function validate($module) {
    *   The name of the module.
    *
    * @return array
-   *   The module info, or NULL if that module does not exist.
+   *   The module info, or empty array if that module does not exist.
    */
   protected function getModuleInfoByModule($module) {
-    $modules = system_rebuild_module_data();
-    return isset($modules[$module]->info) ? $modules[$module]->info : [];
+    if ($this->moduleExtensionList->exists($module)) {
+      return $this->moduleExtensionList->get($module)->info;
+    }
+    return [];
   }
 
 }
diff --git a/core/modules/book/tests/src/Kernel/BookUninstallTest.php b/core/modules/book/tests/src/Kernel/BookUninstallTest.php
index d4205ebf11bc..13cbb4228759 100644
--- a/core/modules/book/tests/src/Kernel/BookUninstallTest.php
+++ b/core/modules/book/tests/src/Kernel/BookUninstallTest.php
@@ -76,7 +76,7 @@ public function testBookUninstall() {
 
     $book_node->delete();
     // No nodes exist therefore the book module is not required.
-    $module_data = \Drupal::service('extension.list.module')->reset()->getList();
+    $module_data = \Drupal::service('extension.list.module')->getList();
     $this->assertFalse(isset($module_data['book']->info['required']), 'The book module is not required.');
 
     $node = Node::create(['title' => $this->randomString(), 'type' => $content_type->id()]);
diff --git a/core/modules/config/src/Form/ConfigSingleImportForm.php b/core/modules/config/src/Form/ConfigSingleImportForm.php
index a70f50fd0e9c..3072999149dc 100644
--- a/core/modules/config/src/Form/ConfigSingleImportForm.php
+++ b/core/modules/config/src/Form/ConfigSingleImportForm.php
@@ -13,6 +13,7 @@
 use Drupal\Core\Config\TypedConfigManagerInterface;
 use Drupal\Core\DependencyInjection\DeprecatedServicePropertyTrait;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Extension\ModuleExtensionList;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Extension\ModuleInstallerInterface;
 use Drupal\Core\Extension\ThemeHandlerInterface;
@@ -104,6 +105,13 @@ class ConfigSingleImportForm extends ConfirmFormBase {
    */
   protected $themeHandler;
 
+  /**
+   * The module extension list.
+   *
+   * @var \Drupal\Core\Extension\ModuleExtensionList
+   */
+  protected $moduleExtensionList;
+
   /**
    * The module installer.
    *
@@ -148,8 +156,10 @@ class ConfigSingleImportForm extends ConfirmFormBase {
    *   The module installer.
    * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
    *   The theme handler.
+   * @param \Drupal\Core\Extension\ModuleExtensionList $extension_list_module
+   *   The module extension list.
    */
-  public function __construct(EntityTypeManagerInterface $entity_type_manager, StorageInterface $config_storage, RendererInterface $renderer, EventDispatcherInterface $event_dispatcher, ConfigManagerInterface $config_manager, LockBackendInterface $lock, TypedConfigManagerInterface $typed_config, ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, ThemeHandlerInterface $theme_handler) {
+  public function __construct(EntityTypeManagerInterface $entity_type_manager, StorageInterface $config_storage, RendererInterface $renderer, EventDispatcherInterface $event_dispatcher, ConfigManagerInterface $config_manager, LockBackendInterface $lock, TypedConfigManagerInterface $typed_config, ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, ThemeHandlerInterface $theme_handler, ModuleExtensionList $extension_list_module) {
     $this->entityTypeManager = $entity_type_manager;
     $this->configStorage = $config_storage;
     $this->renderer = $renderer;
@@ -162,6 +172,7 @@ public function __construct(EntityTypeManagerInterface $entity_type_manager, Sto
     $this->moduleHandler = $module_handler;
     $this->moduleInstaller = $module_installer;
     $this->themeHandler = $theme_handler;
+    $this->moduleExtensionList = $extension_list_module;
   }
 
   /**
@@ -178,7 +189,8 @@ public static function create(ContainerInterface $container) {
       $container->get('config.typed'),
       $container->get('module_handler'),
       $container->get('module_installer'),
-      $container->get('theme_handler')
+      $container->get('theme_handler'),
+      $container->get('extension.list.module')
     );
   }
 
@@ -364,7 +376,8 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
           $this->moduleHandler,
           $this->moduleInstaller,
           $this->themeHandler,
-          $this->getStringTranslation()
+          $this->getStringTranslation(),
+          $this->moduleExtensionList
         );
 
         try {
diff --git a/core/modules/config/src/Form/ConfigSync.php b/core/modules/config/src/Form/ConfigSync.php
index 8cbab3b973c8..ccbbbe9a775b 100644
--- a/core/modules/config/src/Form/ConfigSync.php
+++ b/core/modules/config/src/Form/ConfigSync.php
@@ -6,6 +6,7 @@
 use Drupal\Core\Config\ConfigImporter;
 use Drupal\Core\Config\Importer\ConfigImporterBatch;
 use Drupal\Core\Config\TypedConfigManagerInterface;
+use Drupal\Core\Extension\ModuleExtensionList;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Extension\ModuleInstallerInterface;
 use Drupal\Core\Extension\ThemeHandlerInterface;
@@ -104,6 +105,13 @@ class ConfigSync extends FormBase {
    */
   protected $renderer;
 
+  /**
+   * The module extension list.
+   *
+   * @var \Drupal\Core\Extension\ModuleExtensionList
+   */
+  protected $moduleExtensionList;
+
   /**
    * Constructs the object.
    *
@@ -129,8 +137,10 @@ class ConfigSync extends FormBase {
    *   The theme handler.
    * @param \Drupal\Core\Render\RendererInterface $renderer
    *   The renderer.
+   * @param \Drupal\Core\Extension\ModuleExtensionList $extension_list_module
+   *   The module extension list
    */
-  public function __construct(StorageInterface $sync_storage, StorageInterface $active_storage, StorageInterface $snapshot_storage, LockBackendInterface $lock, EventDispatcherInterface $event_dispatcher, ConfigManagerInterface $config_manager, TypedConfigManagerInterface $typed_config, ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, ThemeHandlerInterface $theme_handler, RendererInterface $renderer) {
+  public function __construct(StorageInterface $sync_storage, StorageInterface $active_storage, StorageInterface $snapshot_storage, LockBackendInterface $lock, EventDispatcherInterface $event_dispatcher, ConfigManagerInterface $config_manager, TypedConfigManagerInterface $typed_config, ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, ThemeHandlerInterface $theme_handler, RendererInterface $renderer, ModuleExtensionList $extension_list_module) {
     $this->syncStorage = $sync_storage;
     $this->activeStorage = $active_storage;
     $this->snapshotStorage = $snapshot_storage;
@@ -142,6 +152,7 @@ public function __construct(StorageInterface $sync_storage, StorageInterface $ac
     $this->moduleInstaller = $module_installer;
     $this->themeHandler = $theme_handler;
     $this->renderer = $renderer;
+    $this->moduleExtensionList = $extension_list_module;
   }
 
   /**
@@ -159,7 +170,8 @@ public static function create(ContainerInterface $container) {
       $container->get('module_handler'),
       $container->get('module_installer'),
       $container->get('theme_handler'),
-      $container->get('renderer')
+      $container->get('renderer'),
+      $container->get('extension.list.module')
     );
   }
 
@@ -328,7 +340,8 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
       $this->moduleHandler,
       $this->moduleInstaller,
       $this->themeHandler,
-      $this->getStringTranslation()
+      $this->getStringTranslation(),
+      $this->moduleExtensionList
     );
     if ($config_importer->alreadyImporting()) {
       $this->messenger()->addStatus($this->t('Another request may be synchronizing configuration already.'));
diff --git a/core/modules/config/tests/src/Functional/ConfigImportAllTest.php b/core/modules/config/tests/src/Functional/ConfigImportAllTest.php
index 1d07cde0e33d..5ca30e1b01fa 100644
--- a/core/modules/config/tests/src/Functional/ConfigImportAllTest.php
+++ b/core/modules/config/tests/src/Functional/ConfigImportAllTest.php
@@ -45,7 +45,7 @@ protected function setUp() {
   public function testInstallUninstall() {
 
     // Get a list of modules to enable.
-    $all_modules = system_rebuild_module_data();
+    $all_modules = $this->container->get('extension.list.module')->getList();
     $all_modules = array_filter($all_modules, function ($module) {
       // Filter contrib, hidden, already enabled modules and modules in the
       // Testing package.
@@ -86,7 +86,7 @@ public function testInstallUninstall() {
     // Purge the field data.
     field_purge_batch(1000);
 
-    $all_modules = system_rebuild_module_data();
+    $all_modules = \Drupal::service('extension.list.module')->getList();
 
     // Ensure that only core required modules and the install profile can not be uninstalled.
     $validation_reasons = \Drupal::service('module_installer')->validateUninstall(array_keys($all_modules));
diff --git a/core/modules/config/tests/src/Functional/ConfigImportUITest.php b/core/modules/config/tests/src/Functional/ConfigImportUITest.php
index 715976d1622e..b3b125c22197 100644
--- a/core/modules/config/tests/src/Functional/ConfigImportUITest.php
+++ b/core/modules/config/tests/src/Functional/ConfigImportUITest.php
@@ -498,7 +498,7 @@ public function testExtensionValidation() {
     $core = $sync->read('core.extension');
     // Node depends on text.
     unset($core['module']['text']);
-    $module_data = system_rebuild_module_data();
+    $module_data = $this->container->get('extension.list.module')->getList();
     $this->assertTrue(isset($module_data['node']->requires['text']), 'The Node module depends on the Text module.');
     // Bartik depends on classy.
     unset($core['theme']['classy']);
diff --git a/core/modules/config/tests/src/Kernel/ConfigUninstallViaCliImportTest.php b/core/modules/config/tests/src/Kernel/ConfigUninstallViaCliImportTest.php
index 09f5d09aa3c2..ae56a9c4cb97 100644
--- a/core/modules/config/tests/src/Kernel/ConfigUninstallViaCliImportTest.php
+++ b/core/modules/config/tests/src/Kernel/ConfigUninstallViaCliImportTest.php
@@ -49,7 +49,8 @@ protected function setUp() {
       $this->container->get('module_handler'),
       $this->container->get('module_installer'),
       $this->container->get('theme_handler'),
-      $this->container->get('string_translation')
+      $this->container->get('string_translation'),
+      $this->container->get('extension.list.module')
     );
   }
 
diff --git a/core/modules/content_translation/tests/src/Kernel/ContentTranslationConfigImportTest.php b/core/modules/content_translation/tests/src/Kernel/ContentTranslationConfigImportTest.php
index 7e0d99faa95e..a3a3ad96e11a 100644
--- a/core/modules/content_translation/tests/src/Kernel/ContentTranslationConfigImportTest.php
+++ b/core/modules/content_translation/tests/src/Kernel/ContentTranslationConfigImportTest.php
@@ -51,7 +51,8 @@ protected function setUp() {
       $this->container->get('module_handler'),
       $this->container->get('module_installer'),
       $this->container->get('theme_handler'),
-      $this->container->get('string_translation')
+      $this->container->get('string_translation'),
+      $this->container->get('extension.list.module')
     );
   }
 
diff --git a/core/modules/field/tests/src/Kernel/FieldDefinitionIntegrityTest.php b/core/modules/field/tests/src/Kernel/FieldDefinitionIntegrityTest.php
index afd468a5dab0..7f723f6efa25 100644
--- a/core/modules/field/tests/src/Kernel/FieldDefinitionIntegrityTest.php
+++ b/core/modules/field/tests/src/Kernel/FieldDefinitionIntegrityTest.php
@@ -197,7 +197,7 @@ protected function checkDisplayOption($entity_type_id, $field_id, BaseFieldDefin
    *   and all modules required by any of these modules.
    */
   protected function modulesWithSubdirectory($subdirectory) {
-    $modules = system_rebuild_module_data();
+    $modules = \Drupal::service('extension.list.module')->getList();
     $modules = array_filter($modules, function (Extension $module) use ($subdirectory) {
       // Filter contrib, hidden, already enabled modules and modules in the
       // Testing package.
diff --git a/core/modules/filter/tests/src/Functional/FilterFormTest.php b/core/modules/filter/tests/src/Functional/FilterFormTest.php
index 5457912d9177..89b4713ac143 100644
--- a/core/modules/filter/tests/src/Functional/FilterFormTest.php
+++ b/core/modules/filter/tests/src/Functional/FilterFormTest.php
@@ -71,8 +71,6 @@ public function testFilterForm() {
     // correctly.
     // @see https://www.drupal.org/node/2387983
     \Drupal::service('module_installer')->install(['filter_test_plugin']);
-    // Force rebuild module data.
-    \Drupal::service('extension.list.module')->reset();
   }
 
   /**
diff --git a/core/modules/filter/tests/src/Kernel/FilterAPITest.php b/core/modules/filter/tests/src/Kernel/FilterAPITest.php
index ed6bff8668dd..3885ec4e5c77 100644
--- a/core/modules/filter/tests/src/Kernel/FilterAPITest.php
+++ b/core/modules/filter/tests/src/Kernel/FilterAPITest.php
@@ -488,7 +488,7 @@ public function testDependencyRemoval() {
 
     drupal_static_reset('filter_formats');
     \Drupal::entityTypeManager()->getStorage('filter_format')->resetCache();
-    $module_data = \Drupal::service('extension.list.module')->reset()->getList();
+    $module_data = \Drupal::service('extension.list.module')->getList();
     $this->assertFalse(isset($module_data['filter_test']->info['required']), 'The filter_test module is required.');
 
     // Verify that a dependency exists on the module that provides the filter
diff --git a/core/modules/help/tests/src/Functional/HelpTest.php b/core/modules/help/tests/src/Functional/HelpTest.php
index 3965b53cde9a..029db407da02 100644
--- a/core/modules/help/tests/src/Functional/HelpTest.php
+++ b/core/modules/help/tests/src/Functional/HelpTest.php
@@ -152,7 +152,7 @@ protected function verifyHelp($response = 200) {
    */
   protected function getModuleList() {
     $modules = [];
-    $module_data = system_rebuild_module_data();
+    $module_data = $this->container->get('extension.list.module')->getList();
     foreach (\Drupal::moduleHandler()->getImplementations('help') as $module) {
       $modules[$module] = $module_data[$module]->info['name'];
     }
diff --git a/core/modules/help/tests/src/Kernel/HelpEmptyPageTest.php b/core/modules/help/tests/src/Kernel/HelpEmptyPageTest.php
index 070a95451b3b..7010fc876494 100644
--- a/core/modules/help/tests/src/Kernel/HelpEmptyPageTest.php
+++ b/core/modules/help/tests/src/Kernel/HelpEmptyPageTest.php
@@ -32,7 +32,7 @@ public function register(ContainerBuilder $container) {
    * Ensures that no URL generator is called on a page without hook_help().
    */
   public function testEmptyHookHelp() {
-    $all_modules = system_rebuild_module_data();
+    $all_modules = \Drupal::service('extension.list.module')->getList();
     $all_modules = array_filter($all_modules, function ($module) {
       // Filter contrib, hidden, already enabled modules and modules in the
       // Testing package.
diff --git a/core/modules/jsonapi/tests/src/Functional/TestCoverageTest.php b/core/modules/jsonapi/tests/src/Functional/TestCoverageTest.php
index 217d3d0d9323..b3a2c6083b80 100644
--- a/core/modules/jsonapi/tests/src/Functional/TestCoverageTest.php
+++ b/core/modules/jsonapi/tests/src/Functional/TestCoverageTest.php
@@ -25,7 +25,7 @@ class TestCoverageTest extends BrowserTestBase {
   protected function setUp() {
     parent::setUp();
 
-    $all_modules = system_rebuild_module_data();
+    $all_modules = \Drupal::service('extension.list.module')->getList();
     $stable_core_modules = array_filter($all_modules, function ($module) {
       // Filter out contrib, hidden, testing, and experimental modules. We also
       // don't need to enable modules that are already enabled.
diff --git a/core/modules/language/tests/src/Kernel/OverriddenConfigImportTest.php b/core/modules/language/tests/src/Kernel/OverriddenConfigImportTest.php
index 6a243f5a098d..feddee68b26a 100644
--- a/core/modules/language/tests/src/Kernel/OverriddenConfigImportTest.php
+++ b/core/modules/language/tests/src/Kernel/OverriddenConfigImportTest.php
@@ -48,7 +48,8 @@ protected function setUp() {
       $this->container->get('module_handler'),
       $this->container->get('module_installer'),
       $this->container->get('theme_handler'),
-      $this->container->get('string_translation')
+      $this->container->get('string_translation'),
+      $this->container->get('extension.list.module')
     );
   }
 
diff --git a/core/modules/locale/locale.compare.inc b/core/modules/locale/locale.compare.inc
index f6b79f42ec5e..776bc752591e 100644
--- a/core/modules/locale/locale.compare.inc
+++ b/core/modules/locale/locale.compare.inc
@@ -103,7 +103,7 @@ function locale_translation_project_list() {
       'interface translation project',
       'interface translation server pattern',
     ];
-    $module_data = _locale_translation_prepare_project_list(system_rebuild_module_data(), 'module');
+    $module_data = _locale_translation_prepare_project_list(\Drupal::service('extension.list.module')->getList(), 'module');
     $theme_data = _locale_translation_prepare_project_list(\Drupal::service('theme_handler')->rebuildThemeData(), 'theme');
     $project_info = new ProjectInfo();
     $project_info->processInfoList($projects, $module_data, 'module', TRUE, $additional_whitelist);
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceRestTestCoverageTest.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceRestTestCoverageTest.php
index 0ef640bbb15f..82d47b95a7f5 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceRestTestCoverageTest.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceRestTestCoverageTest.php
@@ -29,7 +29,7 @@ class EntityResourceRestTestCoverageTest extends BrowserTestBase {
   protected function setUp() {
     parent::setUp();
 
-    $all_modules = system_rebuild_module_data();
+    $all_modules = $this->container->get('extension.list.module')->getList();
     $stable_core_modules = array_filter($all_modules, function ($module) {
       // Filter out contrib, hidden, testing, and experimental modules. We also
       // don't need to enable modules that are already enabled.
diff --git a/core/modules/system/src/Form/ModulesListForm.php b/core/modules/system/src/Form/ModulesListForm.php
index c2ade11b7a6d..cabbe2ebaa4b 100644
--- a/core/modules/system/src/Form/ModulesListForm.php
+++ b/core/modules/system/src/Form/ModulesListForm.php
@@ -8,6 +8,7 @@
 use Drupal\Core\Access\AccessManagerInterface;
 use Drupal\Core\Extension\Extension;
 use Drupal\Core\Extension\InfoParserException;
+use Drupal\Core\Extension\ModuleExtensionList;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Extension\ModuleInstallerInterface;
 use Drupal\Core\Form\FormBase;
@@ -66,6 +67,13 @@ class ModulesListForm extends FormBase {
    */
   protected $permissionHandler;
 
+  /**
+   * The module extension list.
+   *
+   * @var \Drupal\Core\Extension\ModuleExtensionList
+   */
+  protected $moduleExtensionList;
+
   /**
    * {@inheritdoc}
    */
@@ -76,7 +84,8 @@ public static function create(ContainerInterface $container) {
       $container->get('keyvalue.expirable')->get('module_list'),
       $container->get('access_manager'),
       $container->get('current_user'),
-      $container->get('user.permissions')
+      $container->get('user.permissions'),
+      $container->get('extension.list.module')
     );
   }
 
@@ -95,8 +104,11 @@ public static function create(ContainerInterface $container) {
    *   The current user.
    * @param \Drupal\user\PermissionHandlerInterface $permission_handler
    *   The permission handler.
+   * @param \Drupal\Core\Extension\ModuleExtensionList $extension_list_module
+   *   The module extension list.
    */
-  public function __construct(ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, KeyValueStoreExpirableInterface $key_value_expirable, AccessManagerInterface $access_manager, AccountInterface $current_user, PermissionHandlerInterface $permission_handler) {
+  public function __construct(ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, KeyValueStoreExpirableInterface $key_value_expirable, AccessManagerInterface $access_manager, AccountInterface $current_user, PermissionHandlerInterface $permission_handler, ModuleExtensionList $extension_list_module) {
+    $this->moduleExtensionList = $extension_list_module;
     $this->moduleHandler = $module_handler;
     $this->moduleInstaller = $module_installer;
     $this->keyValueExpirable = $key_value_expirable;
@@ -145,7 +157,9 @@ public function buildForm(array $form, FormStateInterface $form_state) {
 
     // Sort all modules by their names.
     try {
-      $modules = system_rebuild_module_data();
+      // The module list needs to be reset so that it can re-scan and include
+      // any new modules that may have been added directly into the filesystem.
+      $modules = $this->moduleExtensionList->reset()->getList();
       uasort($modules, 'system_sort_modules_by_info_name');
     }
     catch (InfoParserException $e) {
@@ -377,7 +391,7 @@ protected function buildModuleList(FormStateInterface $form_state) {
       'experimental' => [],
     ];
 
-    $data = system_rebuild_module_data();
+    $data = $this->moduleExtensionList->getList();
     foreach ($data as $name => $module) {
       // If the module is installed there is nothing to do.
       if ($this->moduleHandler->moduleExists($name)) {
diff --git a/core/modules/system/src/Form/ModulesUninstallConfirmForm.php b/core/modules/system/src/Form/ModulesUninstallConfirmForm.php
index 4a66020dcca9..37717e2d275f 100644
--- a/core/modules/system/src/Form/ModulesUninstallConfirmForm.php
+++ b/core/modules/system/src/Form/ModulesUninstallConfirmForm.php
@@ -6,6 +6,7 @@
 use Drupal\Core\Config\Entity\ConfigDependencyDeleteFormTrait;
 use Drupal\Core\DependencyInjection\DeprecatedServicePropertyTrait;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Extension\ModuleExtensionList;
 use Drupal\Core\Extension\ModuleInstallerInterface;
 use Drupal\Core\Form\ConfirmFormBase;
 use Drupal\Core\Form\FormStateInterface;
@@ -64,6 +65,13 @@ class ModulesUninstallConfirmForm extends ConfirmFormBase {
    */
   protected $modules = [];
 
+  /**
+   * The module extension list.
+   *
+   * @var \Drupal\Core\Extension\ModuleExtensionList
+   */
+  protected $moduleExtensionList;
+
   /**
    * Constructs a ModulesUninstallConfirmForm object.
    *
@@ -75,12 +83,15 @@ class ModulesUninstallConfirmForm extends ConfirmFormBase {
    *   The configuration manager.
    * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
    *   The entity type manager.
+   * @param \Drupal\Core\Extension\ModuleExtensionList $extension_list_module
+   *   The module extension list.
    */
-  public function __construct(ModuleInstallerInterface $module_installer, KeyValueStoreExpirableInterface $key_value_expirable, ConfigManagerInterface $config_manager, EntityTypeManagerInterface $entity_type_manager) {
+  public function __construct(ModuleInstallerInterface $module_installer, KeyValueStoreExpirableInterface $key_value_expirable, ConfigManagerInterface $config_manager, EntityTypeManagerInterface $entity_type_manager, ModuleExtensionList $extension_list_module) {
     $this->moduleInstaller = $module_installer;
     $this->keyValueExpirable = $key_value_expirable;
     $this->configManager = $config_manager;
     $this->entityTypeManager = $entity_type_manager;
+    $this->moduleExtensionList = $extension_list_module;
   }
 
   /**
@@ -91,7 +102,8 @@ public static function create(ContainerInterface $container) {
       $container->get('module_installer'),
       $container->get('keyvalue.expirable')->get('modules_uninstall'),
       $container->get('config.manager'),
-      $container->get('entity_type.manager')
+      $container->get('entity_type.manager'),
+      $container->get('extension.list.module')
     );
   }
 
@@ -144,7 +156,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       return $this->redirect('system.modules_uninstall');
     }
 
-    $data = system_rebuild_module_data();
+    $data = $this->moduleExtensionList->getList();
     $form['text']['#markup'] = '<p>' . $this->t('The following modules will be completely uninstalled from your site, and <em>all data from these modules will be lost</em>!') . '</p>';
     $form['modules'] = [
       '#theme' => 'item_list',
diff --git a/core/modules/system/src/Form/ModulesUninstallForm.php b/core/modules/system/src/Form/ModulesUninstallForm.php
index 841a741e44db..9370050d15d8 100644
--- a/core/modules/system/src/Form/ModulesUninstallForm.php
+++ b/core/modules/system/src/Form/ModulesUninstallForm.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\system\Form;
 
+use Drupal\Core\Extension\ModuleExtensionList;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Extension\ModuleInstallerInterface;
 use Drupal\Core\Form\FormBase;
@@ -37,6 +38,13 @@ class ModulesUninstallForm extends FormBase {
    */
   protected $keyValueExpirable;
 
+  /**
+   * The module extension list.
+   *
+   * @var \Drupal\Core\Extension\ModuleExtensionList
+   */
+  protected $moduleExtensionList;
+
   /**
    * {@inheritdoc}
    */
@@ -44,7 +52,8 @@ public static function create(ContainerInterface $container) {
     return new static(
       $container->get('module_handler'),
       $container->get('module_installer'),
-      $container->get('keyvalue.expirable')->get('modules_uninstall')
+      $container->get('keyvalue.expirable')->get('modules_uninstall'),
+      $container->get('extension.list.module')
     );
   }
 
@@ -57,8 +66,11 @@ public static function create(ContainerInterface $container) {
    *   The module installer.
    * @param \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface $key_value_expirable
    *   The key value expirable factory.
+   * @param \Drupal\Core\Extension\ModuleExtensionList $extension_list_module
+   *   The module extension list.
    */
-  public function __construct(ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, KeyValueStoreExpirableInterface $key_value_expirable) {
+  public function __construct(ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, KeyValueStoreExpirableInterface $key_value_expirable, ModuleExtensionList $extension_list_module) {
+    $this->moduleExtensionList = $extension_list_module;
     $this->moduleHandler = $module_handler;
     $this->moduleInstaller = $module_installer;
     $this->keyValueExpirable = $key_value_expirable;
@@ -78,10 +90,9 @@ public function buildForm(array $form, FormStateInterface $form_state) {
     // Make sure the install API is available.
     include_once DRUPAL_ROOT . '/core/includes/install.inc';
 
-    // Get a list of all available modules.
-    $modules = system_rebuild_module_data();
-    $uninstallable = array_filter($modules, function ($module) use ($modules) {
-      return empty($modules[$module->getName()]->info['required']) && $module->status;
+    // Get a list of all available modules that can be uninstalled.
+    $uninstallable = array_filter($this->moduleExtensionList->getList(), function ($module) {
+       return empty($module->info['required']) && $module->status;
     });
 
     // Include system.admin.inc so we can use the sort callbacks.
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index c6d1678834cf..61b619dc3281 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -797,7 +797,7 @@ function system_requirements($phase) {
   // Display an error if a newly introduced dependency in a module is not resolved.
   if ($phase == 'update') {
     $profile = drupal_get_profile();
-    $files = system_rebuild_module_data();
+    $files = \Drupal::service('extension.list.module')->getList();
     foreach ($files as $module => $file) {
       // Ignore disabled modules and installation profiles.
       if (!$file->status || $module == $profile) {
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 014153958eaf..1371ea07217d 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -965,7 +965,7 @@ function system_check_directory($form_element, FormStateInterface $form_state) {
  *   information for $name, if given. If no records are available, an empty
  *   array is returned.
  *
- * @see system_rebuild_module_data()
+ * @see \Drupal\Core\Extension\ModuleExtensionList::getList()
  * @see \Drupal\Core\Extension\ThemeExtensionList
  */
 function system_get_info($type, $name = NULL) {
@@ -1032,8 +1032,15 @@ function _system_rebuild_module_data() {
  *
  * @return \Drupal\Core\Extension\Extension[]
  *   Array of all available modules and their data.
+ *
+ * @deprecated in Drupal 8.8.0 and will be removed before Drupal 9.0.0.
+ *   Use \Drupal::service('extension.list.module')->getList() instead.
+ *   Note: use reset() only when you really need to rescan and rebuild the list.
+ *
+ * @see https://www.drupal.org/node/2709919
  */
 function system_rebuild_module_data() {
+  @trigger_error('system_rebuild_module_data() is deprecated in Drupal 8.8.0 and will be removed before Drupal 9.0.0. Instead, you should use \Drupal::service("extension.list.module")->getList(). See https://www.drupal.org/node/2709919', E_USER_DEPRECATED);
   return \Drupal::service('extension.list.module')->reset()->getList();
 }
 
diff --git a/core/modules/system/tests/src/Functional/Module/InstallUninstallTest.php b/core/modules/system/tests/src/Functional/Module/InstallUninstallTest.php
index bcdf8ea33df9..fd84c4db7ec1 100644
--- a/core/modules/system/tests/src/Functional/Module/InstallUninstallTest.php
+++ b/core/modules/system/tests/src/Functional/Module/InstallUninstallTest.php
@@ -36,7 +36,7 @@ public function testInstallUninstall() {
     $this->assertEqual($this->container->get('state')->get('system_test_preuninstall_module'), 'module_test');
     $this->resetAll();
 
-    $all_modules = system_rebuild_module_data();
+    $all_modules = $this->container->get('extension.list.module')->getList();
 
     // Test help on required modules, but do not test uninstalling.
     $required_modules = array_filter($all_modules, function ($module) {
diff --git a/core/modules/system/tests/src/Kernel/Extension/ModuleHandlerTest.php b/core/modules/system/tests/src/Kernel/Extension/ModuleHandlerTest.php
index 63229a913980..bc6a580ea54c 100644
--- a/core/modules/system/tests/src/Kernel/Extension/ModuleHandlerTest.php
+++ b/core/modules/system/tests/src/Kernel/Extension/ModuleHandlerTest.php
@@ -89,7 +89,6 @@ public function testDependencyResolution() {
     // Color will depend on Config, which depends on a non-existing module Foo.
     // Nothing should be installed.
     \Drupal::state()->set('module_test.dependency', 'missing dependency');
-    \Drupal::service('extension.list.module')->reset();
 
     try {
       $result = $this->moduleInstaller()->install(['color']);
@@ -104,7 +103,6 @@ public function testDependencyResolution() {
     // Fix the missing dependency.
     // Color module depends on Config. Config depends on Help module.
     \Drupal::state()->set('module_test.dependency', 'dependency');
-    \Drupal::service('extension.list.module')->reset();
 
     $result = $this->moduleInstaller()->install(['color']);
     $this->assertTrue($result, 'ModuleInstaller::install() returns the correct value.');
@@ -136,7 +134,6 @@ public function testDependencyResolution() {
     // dependency on a specific version of Help module in its info file. Make
     // sure that Drupal\Core\Extension\ModuleInstaller::install() still works.
     \Drupal::state()->set('module_test.dependency', 'version dependency');
-    \Drupal::service('extension.list.module')->reset();
 
     $result = $this->moduleInstaller()->install(['color']);
     $this->assertTrue($result, 'ModuleInstaller::install() returns the correct value.');
@@ -171,7 +168,7 @@ public function testUninstallProfileDependencyBC() {
     drupal_get_filename('profile', $profile, 'core/profiles/' . $profile . '/' . $profile . '.info.yml');
     $this->enableModules(['module_test', $profile]);
 
-    $data = \Drupal::service('extension.list.module')->reset()->getList();
+    $data = \Drupal::service('extension.list.module')->getList();
     $this->assertFalse(isset($data[$profile]->requires[$dependency]));
     $this->assertContains($dependency, $data[$profile]->info['install']);
 
@@ -280,7 +277,6 @@ public function testUninstallContentDependency() {
     // entity_test will depend on help. This way help can not be uninstalled
     // when there is test content preventing entity_test from being uninstalled.
     \Drupal::state()->set('module_test.dependency', 'dependency');
-    \Drupal::service('extension.list.module')->reset();
 
     // Create an entity so that the modules can not be disabled.
     $entity = EntityTest::create(['name' => $this->randomString()]);
@@ -319,7 +315,7 @@ public function testUninstallContentDependency() {
    */
   public function testModuleMetaData() {
     // Generate the list of available modules.
-    $modules = system_rebuild_module_data();
+    $modules = $this->container->get('extension.list.module')->getList();
     // Check that the mtime field exists for the system module.
     $this->assertTrue(!empty($modules['system']->info['mtime']), 'The system.info.yml file modification time field is present.');
     // Use 0 if mtime isn't present, to avoid an array index notice.
diff --git a/core/modules/system/tests/src/Kernel/System/InfoAlterTest.php b/core/modules/system/tests/src/Kernel/System/InfoAlterTest.php
index ebdac3ce0dbf..ee5fbf6adf8a 100644
--- a/core/modules/system/tests/src/Kernel/System/InfoAlterTest.php
+++ b/core/modules/system/tests/src/Kernel/System/InfoAlterTest.php
@@ -22,14 +22,14 @@ class InfoAlterTest extends KernelTestBase {
    */
   public function testSystemInfoAlter() {
     \Drupal::state()->set('module_required_test.hook_system_info_alter', TRUE);
-    $info = system_rebuild_module_data();
+    $info = \Drupal::service('extension.list.module')->getList();
     $this->assertFalse(isset($info['node']->info['required']), 'Before the module_required_test is installed the node module is not required.');
 
     // Enable the test module.
     \Drupal::service('module_installer')->install(['module_required_test'], FALSE);
     $this->assertTrue(\Drupal::moduleHandler()->moduleExists('module_required_test'), 'Test required module is enabled.');
 
-    $info = system_rebuild_module_data();
+    $info = \Drupal::service('extension.list.module')->getList();
     $this->assertTrue($info['node']->info['required'], 'After the module_required_test is installed the node module is required.');
   }
 
diff --git a/core/modules/system/tests/src/Kernel/SystemFunctionsLegacyTest.php b/core/modules/system/tests/src/Kernel/SystemFunctionsLegacyTest.php
new file mode 100644
index 000000000000..fd97b0ecfe23
--- /dev/null
+++ b/core/modules/system/tests/src/Kernel/SystemFunctionsLegacyTest.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Drupal\Tests\system\Kernel;
+
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * Tests deprecated system module functions.
+ *
+ * @group system
+ * @group legacy
+ */
+class SystemFunctionsLegacyTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['system'];
+
+  /**
+   * @expectedDeprecation system_rebuild_module_data() is deprecated in Drupal 8.8.0 and will be removed before Drupal 9.0.0. Instead, you should use \Drupal::service("extension.list.module")->getList(). See https://www.drupal.org/node/2709919
+   * @see system_rebuild_module_data()
+   */
+  public function testSystemRebuildModuleDataDeprecation() {
+    system_rebuild_module_data();
+  }
+
+}
diff --git a/core/modules/update/src/UpdateManager.php b/core/modules/update/src/UpdateManager.php
index 07416915af6b..cbb74d703de0 100644
--- a/core/modules/update/src/UpdateManager.php
+++ b/core/modules/update/src/UpdateManager.php
@@ -4,6 +4,7 @@
 
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
+use Drupal\Core\Extension\ModuleExtensionList;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Extension\ThemeHandlerInterface;
 use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
@@ -67,6 +68,13 @@ class UpdateManager implements UpdateManagerInterface {
    */
   protected $themeHandler;
 
+  /**
+   * The module extension list.
+   *
+   * @var \Drupal\Core\Extension\ModuleExtensionList
+   */
+  protected $moduleExtensionList;
+
   /**
    * Constructs a UpdateManager.
    *
@@ -82,8 +90,11 @@ class UpdateManager implements UpdateManagerInterface {
    *   The expirable key/value factory.
    * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
    *   The theme handler.
+   * @param \Drupal\Core\Extension\ModuleExtensionList|null $extension_list_module
+   *   The module extension list. This is left optional for BC reasons, but the
+   *   optional usage is deprecated and will become required in Drupal 9.0.0.
    */
-  public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, UpdateProcessorInterface $update_processor, TranslationInterface $translation, KeyValueFactoryInterface $key_value_expirable_factory, ThemeHandlerInterface $theme_handler) {
+  public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, UpdateProcessorInterface $update_processor, TranslationInterface $translation, KeyValueFactoryInterface $key_value_expirable_factory, ThemeHandlerInterface $theme_handler, ModuleExtensionList $extension_list_module = NULL) {
     $this->updateSettings = $config_factory->get('update.settings');
     $this->moduleHandler = $module_handler;
     $this->updateProcessor = $update_processor;
@@ -92,6 +103,11 @@ public function __construct(ConfigFactoryInterface $config_factory, ModuleHandle
     $this->themeHandler = $theme_handler;
     $this->availableReleasesTempStore = $key_value_expirable_factory->get('update_available_releases');
     $this->projects = [];
+    if ($extension_list_module === NULL) {
+      @trigger_error('Invoking the UpdateManager constructor without the module extension list parameter is deprecated in Drupal 8.8.0 and will no longer be supported in Drupal 9.0.0. The extension list parameter is now required in the ConfigImporter constructor. See https://www.drupal.org/node/2943918', E_USER_DEPRECATED);
+      $extension_list_module = \Drupal::service('extension.list.module');
+    }
+    $this->moduleExtensionList = $extension_list_module;
   }
 
   /**
@@ -129,7 +145,7 @@ public function getProjects() {
       $this->projects = $this->projectStorage('update_project_projects');
       if (empty($this->projects)) {
         // Still empty, so we have to rebuild.
-        $module_data = system_rebuild_module_data();
+        $module_data = $this->moduleExtensionList->reset()->getList();
         $theme_data = $this->themeHandler->rebuildThemeData();
         $project_info = new ProjectInfo();
         $project_info->processInfoList($this->projects, $module_data, 'module', TRUE);
diff --git a/core/modules/update/tests/src/Functional/UpdateContribTest.php b/core/modules/update/tests/src/Functional/UpdateContribTest.php
index e16a3df77bc2..aa0d44abd653 100644
--- a/core/modules/update/tests/src/Functional/UpdateContribTest.php
+++ b/core/modules/update/tests/src/Functional/UpdateContribTest.php
@@ -120,7 +120,7 @@ public function testUpdateContribBasic() {
    * project. We need to make sure that we see the "BBB" project before the
    * "CCC" project, even though "CCC" includes a module that's processed first
    * if you sort alphabetically by module name (which is the order we see things
-   * inside system_rebuild_module_data() for example).
+   * inside \Drupal\Core\Extension\ExtensionList::getList() for example).
    */
   public function testUpdateContribOrder() {
     // We want core to be version 8.0.0.
diff --git a/core/modules/update/update.services.yml b/core/modules/update/update.services.yml
index fc176d6f7bed..767a1d1f3018 100644
--- a/core/modules/update/update.services.yml
+++ b/core/modules/update/update.services.yml
@@ -6,7 +6,7 @@ services:
       - { name: access_check, applies_to: _access_update_manager }
   update.manager:
     class: Drupal\update\UpdateManager
-    arguments: ['@config.factory', '@module_handler', '@update.processor', '@string_translation', '@keyvalue.expirable', '@theme_handler']
+    arguments: ['@config.factory', '@module_handler', '@update.processor', '@string_translation', '@keyvalue.expirable', '@theme_handler', '@extension.list.module']
   update.processor:
     class: Drupal\update\UpdateProcessor
     arguments: ['@config.factory', '@queue', '@update.fetcher', '@state', '@private_key', '@keyvalue', '@keyvalue.expirable']
diff --git a/core/modules/user/src/PermissionHandler.php b/core/modules/user/src/PermissionHandler.php
index 1f07b25d9509..056c435dffdf 100644
--- a/core/modules/user/src/PermissionHandler.php
+++ b/core/modules/user/src/PermissionHandler.php
@@ -229,13 +229,4 @@ protected function getModuleNames() {
     return $modules;
   }
 
-  /**
-   * Wraps system_rebuild_module_data()
-   *
-   * @return \Drupal\Core\Extension\Extension[]
-   */
-  protected function systemRebuildModuleData() {
-    return system_rebuild_module_data();
-  }
-
 }
diff --git a/core/modules/user/tests/src/Unit/PermissionHandlerTest.php b/core/modules/user/tests/src/Unit/PermissionHandlerTest.php
index 3cc76f8fa282..28ba38adee83 100644
--- a/core/modules/user/tests/src/Unit/PermissionHandlerTest.php
+++ b/core/modules/user/tests/src/Unit/PermissionHandlerTest.php
@@ -29,7 +29,7 @@ class PermissionHandlerTest extends UnitTestCase {
   /**
    * The tested permission handler.
    *
-   * @var \Drupal\Tests\user\Unit\TestPermissionHandler|\Drupal\user\PermissionHandler
+   * @var \Drupal\user\PermissionHandler
    */
   protected $permissionHandler;
 
@@ -142,10 +142,7 @@ public function testBuildPermissionsYaml() {
     $this->controllerResolver->expects($this->never())
       ->method('getControllerFromDefinition');
 
-    $this->permissionHandler = new TestPermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
-
-    // Setup system_rebuild_module_data().
-    $this->permissionHandler->setSystemRebuildModuleData($extensions);
+    $this->permissionHandler = new PermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
 
     $actual_permissions = $this->permissionHandler->getPermissions();
     $this->assertPermissions($actual_permissions);
@@ -206,7 +203,7 @@ public function testBuildPermissionsSortPerModule() {
       ->method('getModuleList')
       ->willReturn(array_flip($modules));
 
-    $permissionHandler = new TestPermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
+    $permissionHandler = new PermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
     $actual_permissions = $permissionHandler->getPermissions();
     $this->assertEquals(['access_module_a4', 'access_module_a1', 'access_module_a2', 'access_module_a3'],
       array_keys($actual_permissions));
@@ -287,10 +284,7 @@ public function testBuildPermissionsYamlCallback() {
       ->with('Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescriptionRestrictAccess')
       ->willReturn([new TestPermissionCallbacks(), 'titleDescriptionRestrictAccess']);
 
-    $this->permissionHandler = new TestPermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
-
-    // Setup system_rebuild_module_data().
-    $this->permissionHandler->setSystemRebuildModuleData($extensions);
+    $this->permissionHandler = new PermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
 
     $actual_permissions = $this->permissionHandler->getPermissions();
     $this->assertPermissions($actual_permissions);
@@ -341,10 +335,7 @@ public function testPermissionsYamlStaticAndCallback() {
       ->with('Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription')
       ->willReturn([new TestPermissionCallbacks(), 'titleDescription']);
 
-    $this->permissionHandler = new TestPermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
-
-    // Setup system_rebuild_module_data().
-    $this->permissionHandler->setSystemRebuildModuleData($extensions);
+    $this->permissionHandler = new PermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
 
     $actual_permissions = $this->permissionHandler->getPermissions();
 
@@ -377,25 +368,6 @@ protected function assertPermissions(array $actual_permissions) {
 
 }
 
-class TestPermissionHandler extends PermissionHandler {
-
-  /**
-   * Test module data.
-   *
-   * @var array
-   */
-  protected $systemModuleData;
-
-  protected function systemRebuildModuleData() {
-    return $this->systemModuleData;
-  }
-
-  public function setSystemRebuildModuleData(array $extensions) {
-    $this->systemModuleData = $extensions;
-  }
-
-}
-
 class TestPermissionCallbacks {
 
   public function singleDescription() {
diff --git a/core/tests/Drupal/KernelTests/Core/Asset/ResolvedLibraryDefinitionsFilesMatchTest.php b/core/tests/Drupal/KernelTests/Core/Asset/ResolvedLibraryDefinitionsFilesMatchTest.php
index 321443d4db16..af0ffd89ed74 100644
--- a/core/tests/Drupal/KernelTests/Core/Asset/ResolvedLibraryDefinitionsFilesMatchTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Asset/ResolvedLibraryDefinitionsFilesMatchTest.php
@@ -99,7 +99,7 @@ protected function setUp() {
     $this->container->get('theme_installer')->install($this->allThemes);
 
     // Enable all core modules.
-    $all_modules = system_rebuild_module_data();
+    $all_modules = $this->container->get('extension.list.module')->getList();
     $all_modules = array_filter($all_modules, function ($module) {
       // Filter contrib, hidden, already enabled modules and modules in the
       // Testing package.
diff --git a/core/tests/Drupal/KernelTests/Core/Bootstrap/GetFilenameTest.php b/core/tests/Drupal/KernelTests/Core/Bootstrap/GetFilenameTest.php
index e19911c53583..48a031606172 100644
--- a/core/tests/Drupal/KernelTests/Core/Bootstrap/GetFilenameTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Bootstrap/GetFilenameTest.php
@@ -30,8 +30,6 @@ public function register(ContainerBuilder $container) {
    * Tests that drupal_get_filename() works when the file is not in database.
    */
   public function testDrupalGetFilename() {
-    system_rebuild_module_data();
-
     // Retrieving the location of a module.
     $this->assertIdentical(drupal_get_filename('module', 'system'), 'core/modules/system/system.info.yml');
 
diff --git a/core/tests/Drupal/KernelTests/Core/Config/ConfigDependencyTest.php b/core/tests/Drupal/KernelTests/Core/Config/ConfigDependencyTest.php
index 2889d9d65f96..fb310bd32de0 100644
--- a/core/tests/Drupal/KernelTests/Core/Config/ConfigDependencyTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigDependencyTest.php
@@ -217,10 +217,6 @@ public function testConfigEntityUninstall() {
       ]
     );
     $entity2->save();
-    // Perform a module rebuild so we can know where the node module is located
-    // and uninstall it.
-    // @todo Remove as part of https://www.drupal.org/node/2186491
-    system_rebuild_module_data();
     // Test that doing a config uninstall of the node module deletes entity2
     // since it is dependent on entity1 which is dependent on the node module.
     $config_manager->uninstall('module', 'node');
@@ -359,10 +355,6 @@ public function testConfigEntityUninstallComplex(array $entity_id_suffixes) {
     $this->assertEqual($entity_4->uuid(), $config_entities['delete'][0]->uuid(), 'Entity 4 will be deleted.');
     $this->assertEqual($entity_5->uuid(), $config_entities['update'][1]->uuid(), 'Entity 5 is updated.');
 
-    // Perform a module rebuild so we can know where the node module is located
-    // and uninstall it.
-    // @todo Remove as part of https://www.drupal.org/node/2186491
-    system_rebuild_module_data();
     // Perform the uninstall.
     $config_manager->uninstall('module', 'node');
 
@@ -476,10 +468,6 @@ public function testConfigEntityUninstallThirdParty() {
     $this->assertSame(['config' => [], 'content' => [], 'module' => ['node'], 'theme' => []], $called[$entity_2->id()]);
     $this->assertSame(['config' => [], 'content' => [], 'module' => ['node'], 'theme' => []], $called[$entity_4->id()]);
 
-    // Perform a module rebuild so we can know where the node module is located
-    // and uninstall it.
-    // @todo Remove as part of https://www.drupal.org/node/2186491
-    system_rebuild_module_data();
     // Perform the uninstall.
     $config_manager->uninstall('module', 'node');
 
diff --git a/core/tests/Drupal/KernelTests/Core/Config/ConfigImportRecreateTest.php b/core/tests/Drupal/KernelTests/Core/Config/ConfigImportRecreateTest.php
index 5b40e3318d08..3ff2dea5989f 100644
--- a/core/tests/Drupal/KernelTests/Core/Config/ConfigImportRecreateTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigImportRecreateTest.php
@@ -50,7 +50,8 @@ protected function setUp() {
       $this->container->get('module_handler'),
       $this->container->get('module_installer'),
       $this->container->get('theme_handler'),
-      $this->container->get('string_translation')
+      $this->container->get('string_translation'),
+      $this->container->get('extension.list.module')
     );
   }
 
diff --git a/core/tests/Drupal/KernelTests/Core/Config/ConfigImportRenameValidationTest.php b/core/tests/Drupal/KernelTests/Core/Config/ConfigImportRenameValidationTest.php
index 7378da161e8c..4ec352e57d58 100644
--- a/core/tests/Drupal/KernelTests/Core/Config/ConfigImportRenameValidationTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigImportRenameValidationTest.php
@@ -55,7 +55,8 @@ protected function setUp() {
       $this->container->get('module_handler'),
       $this->container->get('module_installer'),
       $this->container->get('theme_handler'),
-      $this->container->get('string_translation')
+      $this->container->get('string_translation'),
+      $this->container->get('extension.list.module')
     );
   }
 
diff --git a/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterMissingContentTest.php b/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterMissingContentTest.php
index a4b084756342..c67e0425dae0 100644
--- a/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterMissingContentTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterMissingContentTest.php
@@ -55,7 +55,8 @@ protected function setUp() {
       $this->container->get('module_handler'),
       $this->container->get('module_installer'),
       $this->container->get('theme_handler'),
-      $this->container->get('string_translation')
+      $this->container->get('string_translation'),
+      $this->container->get('extension.list.module')
     );
   }
 
diff --git a/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php b/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php
index 70dbb874c96f..29ff1fb59683 100644
--- a/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php
@@ -60,7 +60,8 @@ protected function setUp() {
       $this->container->get('module_handler'),
       $this->container->get('module_installer'),
       $this->container->get('theme_handler'),
-      $this->container->get('string_translation')
+      $this->container->get('string_translation'),
+      $this->container->get('extension.list.module')
     );
   }
 
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/ContentEntityNullStorageTest.php b/core/tests/Drupal/KernelTests/Core/Entity/ContentEntityNullStorageTest.php
index 1b22b20a5ce9..188e9d1a495f 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/ContentEntityNullStorageTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/ContentEntityNullStorageTest.php
@@ -63,7 +63,8 @@ public function testDeleteThroughImport() {
       $this->container->get('module_handler'),
       $this->container->get('module_installer'),
       $this->container->get('theme_handler'),
-      $this->container->get('string_translation')
+      $this->container->get('string_translation'),
+      $this->container->get('extension.list.module')
     );
 
     // Delete the contact message in sync.
diff --git a/core/tests/Drupal/KernelTests/Core/Extension/ModuleConfigureRouteTest.php b/core/tests/Drupal/KernelTests/Core/Extension/ModuleConfigureRouteTest.php
index 0fca6d2e6ecf..54a4b7779ba0 100644
--- a/core/tests/Drupal/KernelTests/Core/Extension/ModuleConfigureRouteTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Extension/ModuleConfigureRouteTest.php
@@ -38,7 +38,7 @@ class ModuleConfigureRouteTest extends KernelTestBase {
   protected function setUp() {
     parent::setUp();
     $this->routeProvider = \Drupal::service('router.route_provider');
-    $this->moduleInfo = system_rebuild_module_data();
+    $this->moduleInfo = \Drupal::service('extension.list.module')->getList();
   }
 
   /**
diff --git a/core/tests/Drupal/KernelTests/Core/Extension/ModuleInstallerTest.php b/core/tests/Drupal/KernelTests/Core/Extension/ModuleInstallerTest.php
index 7ffe65c9fc33..b453afc92ffc 100644
--- a/core/tests/Drupal/KernelTests/Core/Extension/ModuleInstallerTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Extension/ModuleInstallerTest.php
@@ -15,15 +15,6 @@
  */
 class ModuleInstallerTest extends KernelTestBase {
 
-  /**
-   * Modules to install.
-   *
-   * The System module is required because system_rebuild_module_data() is used.
-   *
-   * @var array
-   */
-  public static $modules = ['system'];
-
   /**
    * Tests that routes are rebuilt during install and uninstall of modules.
    *
diff --git a/core/tests/Drupal/KernelTests/Core/Theme/StableLibraryOverrideTest.php b/core/tests/Drupal/KernelTests/Core/Theme/StableLibraryOverrideTest.php
index 049438b25402..795ea334664b 100644
--- a/core/tests/Drupal/KernelTests/Core/Theme/StableLibraryOverrideTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Theme/StableLibraryOverrideTest.php
@@ -60,7 +60,7 @@ protected function setUp() {
     $this->container->get('theme_installer')->install(['stable']);
 
     // Enable all core modules.
-    $all_modules = system_rebuild_module_data();
+    $all_modules = $this->container->get('extension.list.module')->getList();
     $all_modules = array_filter($all_modules, function ($module) {
       // Filter contrib, hidden, experimental, already enabled modules, and
       // modules in the Testing package.
diff --git a/core/tests/Drupal/KernelTests/Core/Theme/StableTemplateOverrideTest.php b/core/tests/Drupal/KernelTests/Core/Theme/StableTemplateOverrideTest.php
index 88bbde23a09c..73d467ce67b9 100644
--- a/core/tests/Drupal/KernelTests/Core/Theme/StableTemplateOverrideTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Theme/StableTemplateOverrideTest.php
@@ -56,11 +56,8 @@ protected function setUp() {
    * Installs all core modules.
    */
   protected function installAllModules() {
-    // Needed for system_rebuild_module_data().
-    include_once $this->root . '/core/modules/system/system.module';
-
     // Enable all core modules.
-    $all_modules = system_rebuild_module_data();
+    $all_modules = $this->container->get('extension.list.module')->getList();
     $all_modules = array_filter($all_modules, function ($module) {
       // Filter contrib, hidden, experimental, already enabled modules, and
       // modules in the Testing package.
diff --git a/core/tests/Drupal/KernelTests/Core/Theme/ThemeInstallerTest.php b/core/tests/Drupal/KernelTests/Core/Theme/ThemeInstallerTest.php
index 5c650d4f4684..180b708a3766 100644
--- a/core/tests/Drupal/KernelTests/Core/Theme/ThemeInstallerTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Theme/ThemeInstallerTest.php
@@ -311,9 +311,7 @@ public function testThemeInfoAlter() {
     $themes = $this->themeHandler()->listInfo();
     $this->assertFalse(isset($themes[$name]->info['regions']['test_region']));
 
-    // Rebuild module data so we know where module_test is located.
-    // @todo Remove as part of https://www.drupal.org/node/2186491
-    system_rebuild_module_data();
+    // Install module_test.
     $this->moduleInstaller()->install(['module_test'], FALSE);
     $this->assertTrue($this->moduleHandler()->moduleExists('module_test'));
 
diff --git a/core/tests/Drupal/Tests/ConfigTestTrait.php b/core/tests/Drupal/Tests/ConfigTestTrait.php
index 45a7c728bf50..139f7f36270b 100644
--- a/core/tests/Drupal/Tests/ConfigTestTrait.php
+++ b/core/tests/Drupal/Tests/ConfigTestTrait.php
@@ -36,7 +36,8 @@ protected function configImporter() {
         $this->container->get('module_handler'),
         $this->container->get('module_installer'),
         $this->container->get('theme_handler'),
-        $this->container->get('string_translation')
+        $this->container->get('string_translation'),
+        $this->container->get('extension.list.module')
       );
     }
     // Always recalculate the changelist when called.
-- 
GitLab