Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: Clarify scoping of excluded functions for which a declaration was found #871

Merged
merged 5 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,43 @@ return [

This enriches the list of Symbols PHP-Scoper's Reflector considers as "internal",
i.e. PHP engine or extension symbols. Such symbols will be left completely
untouched.
untouched.*

This feature should be use very carefully as it can easily break the Composer
*: There is _one_ exception, which is declarations of functions. If you have the function
theofidry marked this conversation as resolved.
Show resolved Hide resolved
`trigger_deprecation` excluded, then any usage of it in the code will be left alone:

```php
use function trigger_deprecation; // Will not be turned into Prefix\trigger_deprecation
```

However, PHP-Scoper may come across its declaration:

```php
// global namespace!

if (!function_exists('trigger_deprecation')) {
function trigger_deprecation() {}
}
```

Then it will be scoped into:

```php
namespace Prefix;

if (!function_exists('Prefix\trigger_deprecation')) {
function trigger_deprecation() {}
}
```

Indeed the namespace _needs_ to be added in order to not break autoloading, in which
case wrapping the function declaration into a non-namespace could work, but is tricky
(so not implemented so far, PoC for supporting it are welcomed) hence was not attempted.

So if left alone, this will break any piece of code that relied on `\trigger_deprecation`,
which is why PHP-Scoper will still add an alias for it, as if it was an exposed function.

**WARNING**: This exclusion feature should be use very carefully as it can easily break the Composer
auto-loading. Indeed, if you have the following package:

```json
Expand Down
83 changes: 40 additions & 43 deletions scoper.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,35 @@
*/

$jetBrainStubs = (static function (): array {
$packageDir = __DIR__.'/vendor/jetbrains/phpstorm-stubs';
theofidry marked this conversation as resolved.
Show resolved Hide resolved
$files = [];
$ignoredDirectories = [
$packageDir.'/tests',
$packageDir.'/meta',
];

foreach (new DirectoryIterator(__DIR__.'/vendor/jetbrains/phpstorm-stubs') as $directoryInfo) {
if ($directoryInfo->isDot()) {
continue;
}

if (false === $directoryInfo->isDir()) {
continue;
}

if (in_array($directoryInfo->getBasename(), ['tests', 'meta'], true)) {
continue;
}

foreach (new DirectoryIterator($directoryInfo->getPathName()) as $fileInfo) {
if ($fileInfo->isDot()) {
$collectFiles = static function (RecursiveIteratorIterator $iterator) use (&$collectFiles, &$files, $ignoredDirectories): void {
foreach ($iterator as $fileInfo) {
/** @var SplFileInfo $fileInfo */
if (str_starts_with($fileInfo->getFilename(), '.')
|| $fileInfo->isDir()
|| !$fileInfo->isReadable()
|| 'php' !== $fileInfo->getExtension()
) {
continue;
}

if (1 !== preg_match('/\.php$/', $fileInfo->getBasename())) {
continue;
foreach ($ignoredDirectories as $ignoredDirectory) {
if (str_starts_with($fileInfo->getPathname(), $ignoredDirectory)) {
continue 2;
}
}

$files[] = $fileInfo->getPathName();
}
}
};

$collectFiles(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($packageDir)));

return $files;
})();
Expand All @@ -50,37 +52,32 @@
'exclude-classes' => [
'Isolated\Symfony\Component\Finder\Finder',
],
'exclude-functions' => [
// symfony/deprecation-contracts
'trigger_deprecation',

// nikic/php-parser
// https://github.com/nikic/PHP-Parser/issues/957
'assertArgs',
'ensureDirExists',
'execCmd',
'formatErrorMessage',
'magicSplit',
'parseArgs',
'preprocessGrammar',
'regex',
'removeTrailingWhitespace',
'resolveMacros',
'resolveNodes',
'resolveStackAccess',
'showHelp',
],
'exclude-constants' => [
// Symfony global constants
'/^SYMFONY\_[\p{L}_]+$/',
],
'exclude-files' => $jetBrainStubs,
'patchers' => [
//
// PHPStorm stub map: leave it unchanged
//
static function (string $filePath, string $prefix, string $contents): string {
if ('vendor/jetbrains/phpstorm-stubs/PhpStormStubsMap.php' !== $filePath) {
return $contents;
}

return str_replace(
[
$prefix.'\\\\',
$prefix.'\\',
'namespace JetBrains\PHPStormStub;',
],
[
'',
'',
sprintf(
'namespace %s\JetBrains\PHPStormStub;',
$prefix,
),
],
$contents,
);
},
//
// Reflector: leave the registered internal symbols unchanged
//
Expand Down
6 changes: 3 additions & 3 deletions src/Configuration/ConfigurationFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ final class ConfigurationFactory
public const DEFAULT_FILE_NAME = 'scoper.inc.php';

public function __construct(
private readonly Filesystem $fileSystem,
private readonly SymbolsConfigurationFactory $configurationWhitelistFactory,
private readonly Filesystem $fileSystem,
private readonly SymbolsConfigurationFactory $symbolsConfigurationFactory,
) {
}

Expand Down Expand Up @@ -91,7 +91,7 @@ public function create(?string $path = null, array $paths = []): Configuration
array_unshift($patchers, new SymfonyParentTraitPatcher());
array_unshift($patchers, new ComposerPatcher());

$symbolsConfiguration = $this->configurationWhitelistFactory->createSymbolsConfiguration($config);
$symbolsConfiguration = $this->symbolsConfigurationFactory->createSymbolsConfiguration($config);
theofidry marked this conversation as resolved.
Show resolved Hide resolved

$finders = self::retrieveFinders($config);
$filesFromPaths = self::retrieveFilesFromPaths($paths);
Expand Down
9 changes: 8 additions & 1 deletion src/Console/Command/InspectCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
use Symfony\Component\VarDumper\Cloner\VarCloner;
use Symfony\Component\VarDumper\Dumper\CliDumper;
use function array_key_exists;
use function file_exists;
use function Safe\getcwd;
use function sprintf;
use const DIRECTORY_SEPARATOR;
Expand Down Expand Up @@ -157,7 +158,13 @@ private function getConfigFilePath(IO $io, string $cwd): ?string
{
$configFilePath = (string) $io->getOption(self::CONFIG_FILE_OPT)->asNullableString();

return '' === $configFilePath ? null : $this->canonicalizePath($configFilePath, $cwd);
if ('' !== $configFilePath) {
return $this->canonicalizePath($configFilePath, $cwd);
}

$defaultConfigFilePath = $this->canonicalizePath(ConfigurationFactory::DEFAULT_FILE_NAME, $cwd);
theofidry marked this conversation as resolved.
Show resolved Hide resolved

return file_exists($defaultConfigFilePath) ? $defaultConfigFilePath : null;
}

/**
Expand Down
170 changes: 170 additions & 0 deletions src/Symbol/Reflector.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,168 @@ final class Reflector
// https://youtrack.jetbrains.com/issue/WI-29503
'bson_encode',
'bson_decode',

// https://youtrack.jetbrains.com/issue/WI-74920
'swoole_async_dns_lookup',
'swoole_async_readfile',
'swoole_async_write',
'swoole_async_writefile',

// https://youtrack.jetbrains.com/issue/WI-74921
'ssh2_send_eof',

// https://youtrack.jetbrains.com/issue/WI-74922
'ssdeep_fuzzy_compare',
'ssdeep_fuzzy_hash',
'ssdeep_fuzzy_hash_filename',

// https://youtrack.jetbrains.com/issue/WI-74918
'ps_add_bookmark',
'ps_add_launchlink',
'ps_add_locallink',
'ps_add_note',
'ps_add_pdflink',
'ps_add_weblink',
'ps_arc',
'ps_arcn',
'ps_begin_page',
'ps_begin_pattern',
'ps_begin_template',
'ps_circle',
'ps_clip',
'ps_close_image',
'ps_close',
'ps_closepath_stroke',
'ps_closepath',
'ps_continue_text',
'ps_curveto',
'ps_delete',
'ps_end_page',
'ps_end_pattern',
'ps_end_template',
'ps_fill_stroke',
'ps_fill',
'ps_findfont',
'ps_get_buffer',
'ps_get_parameter',
'ps_get_value',
'ps_hyphenate',
'ps_include_file',
'ps_lineto',
'ps_makespotcolor',
'ps_moveto',
'ps_new',
'ps_open_file',
'ps_open_image_file',
'ps_open_image',
'ps_open_memory_image',
'ps_place_image',
'ps_rect',
'ps_restore',
'ps_rotate',
'ps_save',
'ps_scale',
'ps_set_border_color',
'ps_set_border_dash',
'ps_set_border_style',
'ps_set_info',
'ps_set_parameter',
'ps_set_text_pos',
'ps_set_value',
'ps_setcolor',
'ps_setdash',
'ps_setflat',
'ps_setfont',
'ps_setgray',
'ps_setlinecap',
'ps_setlinejoin',
'ps_setlinewidth',
'ps_setmiterlimit',
'ps_setoverprintmode',
'ps_setpolydash',
'ps_shading_pattern',
'ps_shading',
'ps_shfill',
'ps_show_boxed',
'ps_show_xy2',
'ps_show_xy',
'ps_show2',
'ps_show',
'ps_string_geometry',
'ps_stringwidth',
'ps_stroke',
'ps_symbol_name',
'ps_symbol_width',
'ps_symbol',
'ps_translate',

// https://youtrack.jetbrains.com/issue/WI-74919
'yaz_addinfo',
'yaz_ccl_conf',
'yaz_ccl_parse',
'yaz_close',
'yaz_connect',
'yaz_database',
'yaz_element',
'yaz_errno',
'yaz_error',
'yaz_es_result',
'yaz_es',
'yaz_get_option',
'yaz_hits',
'yaz_itemorder',
'yaz_present',
'yaz_range',
'yaz_record',
'yaz_scan_result',
'yaz_scan',
'yaz_schema',
'yaz_search',
'yaz_set_option',
'yaz_sort',
'yaz_syntax',
'yaz_wait',

// https://youtrack.jetbrains.com/issue/WI-74923
'setproctitle',
'setthreadtitle',

// https://youtrack.jetbrains.com/issue/WI-74924
'rpmaddtag',

// https://youtrack.jetbrains.com/issue/WI-74925
'oci_set_prefetch_lob',

// https://youtrack.jetbrains.com/issue/WI-74926
'normalizer_is_normalized',
'normalizer_normalize',

// https://youtrack.jetbrains.com/issue/WI-74927
'mysql_drop_db',
'mysql_create_db',

// https://youtrack.jetbrains.com/issue/WI-74928
'event_base_reinit',
'event_priority_set',

// https://youtrack.jetbrains.com/issue/WI-74929
'db2_pclose',

// https://youtrack.jetbrains.com/issue/WI-74930
'cubrid_current_oid',

// https://youtrack.jetbrains.com/issue/WI-74931
'ctype_alnum',
'ctype_alpha',
'ctype_cntrl',
'ctype_digit',
'ctype_graph',
'ctype_lower',
'ctype_print',
'ctype_punct',
'ctype_space',
'ctype_upper',
'ctype_xdigit',
];

/**
Expand Down Expand Up @@ -83,6 +245,14 @@ final class Reflector
// https://youtrack.jetbrains.com/issue/WI-29503
'MONGODB_VERSION',
'MONGODB_STABILITY',

// https://youtrack.jetbrains.com/issue/WI-74918/Missing-PostScript-extension-symbols
'ps_LINECAP_BUTT',
'ps_LINECAP_ROUND',
'ps_LINECAP_SQUARED',
'ps_LINEJOIN_MITER',
'ps_LINEJOIN_ROUND',
'ps_LINEJOIN_BEVEL',
];

public static function createWithPhpStormStubs(): self
Expand Down
Loading
Loading