protected function extractFullyQualifiedClasses(&$class_code, &$imported_classes, $current_namespace = '') {
    $current_namespace_pieces = explode('\\', $current_namespace);

    foreach ($class_code as &$line) {
      // Skip lines which are part of a comment block.
      if (preg_match('@^\s*\*@', $line)) {
        continue;
      }
      // Skip lines which are a single comment.
      if (preg_match('@^\s*//@', $line)) {
        continue;
      }
      // Skip PHPStorm variable typehints.
      if (preg_match('@^\s*/\*\*@', $line)) {
        continue;
      }

      $matches = [];
      // Do not match after a ' or ", as then the class name is a quoted string
      // and should be left alone.
      // Do not match after a letter, as then that's also part of the namespace
      // and we shouldn't be matching only the tail end.
      // Allow a match of '%module' for a namespace piece, for cases where we
      // refer to something we are also in the process of generating, e.g. a
      // plugin base class referencing a plugin interface.
      if (preg_match_all('@(?<![\'"[:alpha:]])(?:\\\\(\w+|%module)){2,}@', $line, $matches, PREG_SET_ORDER)) {
        foreach ($matches as $match_set) {
          $fully_qualified_class_name = $match_set[0];
          $class_name = $match_set[1];
          $line = preg_replace('@' . preg_quote($fully_qualified_class_name) . '@', $class_name, $line);

          $fully_qualified_class_name = ltrim($fully_qualified_class_name, '\\');
          $namespace_pieces = array_slice(explode('\\', $fully_qualified_class_name), 0, -1);

          if ($namespace_pieces != $current_namespace_pieces) {
            $imported_classes[] = ltrim($fully_qualified_class_name, '\\');
          }
        }
      }
    }

    // Remove duplicates.
    $imported_classes = array_unique($imported_classes);
  }