Skip to content

Commit

Permalink
Add support for regexes for excluded symbols (#660)
Browse files Browse the repository at this point in the history
  • Loading branch information
theofidry authored Feb 13, 2022
1 parent 8feb2ae commit cb23986
Show file tree
Hide file tree
Showing 17 changed files with 136 additions and 165 deletions.
6 changes: 3 additions & 3 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,9 @@ Symbols can be marked as excluded as follows:

return [
'exclude-namespaces' => [ 'WP', '/regex/' ],
'exclude-classes' => ['Stringeable'],
'exclude-functions' => ['str_contains'],
'exclude-constants' => ['PHP_EOL'],
'exclude-classes' => ['Stringeable', '/regex/'],
'exclude-functions' => ['str_contains', '/regex/'],
'exclude-constants' => ['PHP_EOL', '/regex/'],
];
```

Expand Down
4 changes: 0 additions & 4 deletions docs/further-reading.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,7 @@ return [
],
'exclude-constants' => [
// Symfony global constants
// TODO: switch to the following regex once regexes are supported here
// https://github.com/humbug/php-scoper/issues/634
'/^SYMFONY\_[\p{L}_]+$/',
// Meanwhile:
'SYMFONY_GRAPHEME_CLUSTER_RX',
],
'exclude-files' => [
...$polyfillsBootstraps,
Expand Down
3 changes: 0 additions & 3 deletions fixtures/set020-infection/scoper.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@
],
'exclude-constants' => [
// Symfony global constants
// TODO: switch to the following regex once regexes are supported here
// https://github.com/humbug/php-scoper/issues/634
'/^SYMFONY\_[\p{L}_]+$/',
'SYMFONY_GRAPHEME_CLUSTER_RX',
],
'exclude-files' => [
...$polyfillsBootstraps,
Expand Down
3 changes: 0 additions & 3 deletions scoper.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,7 @@
],
'exclude-constants' => [
// Symfony global constants
// TODO: switch to the following regex once regexes are supported here
// https://github.com/humbug/php-scoper/issues/634
'/^SYMFONY\_[\p{L}_]+$/',
'SYMFONY_GRAPHEME_CLUSTER_RX',
],
'exclude-files' => [
...$jetBrainStubs,
Expand Down
80 changes: 25 additions & 55 deletions src/Configuration/SymbolsConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,10 @@ final class SymbolsConfiguration
private SymbolRegistry $exposedFunctions;
private SymbolRegistry $exposedConstants;

/**
* @var string[]
*/
private array $excludedClassNames;

/**
* @var string[]
*/
private array $excludedFunctionNames;

/**
* @var string[]
*/
private array $excludedConstantNames;

/**
* @param string[] $excludedClassNames
* @param string[] $excludedFunctionNames
* @param string[] $excludedConstantNames
*/
private SymbolRegistry $excludedClasses;
private SymbolRegistry $excludedFunctions;
private SymbolRegistry $excludedConstants;

public static function create(
bool $exposeGlobalConstants = false,
bool $exposeGlobalClasses = false,
Expand All @@ -58,12 +42,12 @@ public static function create(
// Does not contain the list of excluded symbols which go to the
// Reflector (which has no notion of namespaces)
?NamespaceRegistry $exposedNamespaces = null,
SymbolRegistry $exposedClasses = null,
SymbolRegistry $exposedFunctions = null,
SymbolRegistry $exposedConstants = null,
array $excludedClassNames = [],
array $excludedFunctionNames = [],
array $excludedConstantNames = []
?SymbolRegistry $exposedClasses = null,
?SymbolRegistry $exposedFunctions = null,
?SymbolRegistry $exposedConstants = null,
?SymbolRegistry $excludedClasses = null,
?SymbolRegistry $excludedFunctions = null,
?SymbolRegistry $excludedConstants = null
): self {
return new self(
$exposeGlobalConstants,
Expand All @@ -74,17 +58,12 @@ public static function create(
$exposedClasses ?? SymbolRegistry::create(),
$exposedFunctions ?? SymbolRegistry::create(),
$exposedConstants ?? SymbolRegistry::createForConstants(),
$excludedClassNames,
$excludedFunctionNames,
$excludedConstantNames,
$excludedClasses ?? SymbolRegistry::create(),
$excludedFunctions ?? SymbolRegistry::create(),
$excludedConstants ?? SymbolRegistry::createForConstants(),
);
}

/**
* @param string[] $excludedClassNames
* @param string[] $excludedFunctionNames
* @param string[] $excludedConstantNames
*/
private function __construct(
bool $exposeGlobalConstants,
bool $exposeGlobalClasses,
Expand All @@ -94,9 +73,9 @@ private function __construct(
SymbolRegistry $exposedClasses,
SymbolRegistry $exposedFunctions,
SymbolRegistry $exposedConstants,
array $excludedClassNames,
array $excludedFunctionNames,
array $excludedConstantNames
SymbolRegistry $excludedClasses,
SymbolRegistry $excludedFunctions,
SymbolRegistry $excludedConstants
) {
$this->exposeGlobalConstants = $exposeGlobalConstants;
$this->exposeGlobalClasses = $exposeGlobalClasses;
Expand All @@ -106,9 +85,9 @@ private function __construct(
$this->exposedClasses = $exposedClasses;
$this->exposedFunctions = $exposedFunctions;
$this->exposedConstants = $exposedConstants;
$this->excludedClassNames = $excludedClassNames;
$this->excludedFunctionNames = $excludedFunctionNames;
$this->excludedConstantNames = $excludedConstantNames;
$this->excludedClasses = $excludedClasses;
$this->excludedFunctions = $excludedFunctions;
$this->excludedConstants = $excludedConstants;
}

public function shouldExposeGlobalConstants(): bool
Expand Down Expand Up @@ -151,27 +130,18 @@ public function getExposedConstants(): SymbolRegistry
return $this->exposedConstants;
}

/**
* @return string[]
*/
public function getExcludedClassNames(): array
public function getExcludedClasses(): SymbolRegistry
{
return $this->excludedClassNames;
return $this->excludedClasses;
}

/**
* @return string[]
*/
public function getExcludedFunctionNames(): array
public function getExcludedFunctions(): SymbolRegistry
{
return $this->excludedFunctionNames;
return $this->excludedFunctions;
}

/**
* @return string[]
*/
public function getExcludedConstantNames(): array
public function getExcludedConstants(): SymbolRegistry
{
return $this->excludedConstantNames;
return $this->excludedConstants;
}
}
53 changes: 24 additions & 29 deletions src/Configuration/SymbolsConfigurationFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,27 @@ public function createSymbolsConfiguration(array $config): SymbolsConfiguration
ConfigurationKeys::EXPOSE_CONSTANTS_SYMBOLS_KEYWORD,
);

$excludedClasses = SymbolRegistry::create(
...$this->retrieveElements(
$config,
ConfigurationKeys::CLASSES_INTERNAL_SYMBOLS_KEYWORD,
),
);

$excludedFunctions = SymbolRegistry::create(
...$this->retrieveElements(
$config,
ConfigurationKeys::FUNCTIONS_INTERNAL_SYMBOLS_KEYWORD,
),
);

$excludedConstants = SymbolRegistry::createForConstants(
...$this->retrieveElements(
$config,
ConfigurationKeys::CONSTANTS_INTERNAL_SYMBOLS_KEYWORD,
),
);

return SymbolsConfiguration::create(
$exposeGlobalConstants,
$exposeGlobalClasses,
Expand Down Expand Up @@ -135,7 +156,9 @@ public function createSymbolsConfiguration(array $config): SymbolsConfiguration
$legacyExposedSymbolsPatterns,
),
),
...self::retrieveAllExcludedSymbols($config),
$excludedClasses,
$excludedFunctions,
$excludedConstants,
);
}

Expand Down Expand Up @@ -253,18 +276,6 @@ private function retrieveElements(array $config, string $key): array
];
}

/**
* @return array{string[], string[], string[]}
*/
private static function retrieveAllExcludedSymbols(array $config): array
{
return [
self::retrieveExcludedSymbols($config, ConfigurationKeys::CLASSES_INTERNAL_SYMBOLS_KEYWORD),
self::retrieveExcludedSymbols($config, ConfigurationKeys::FUNCTIONS_INTERNAL_SYMBOLS_KEYWORD),
self::retrieveExcludedSymbols($config, ConfigurationKeys::CONSTANTS_INTERNAL_SYMBOLS_KEYWORD),
];
}

/**
* @deprecated
*
Expand Down Expand Up @@ -421,20 +432,4 @@ private static function lowerCaseConstantName(string $name): string

return implode('\\', $parts);
}

/**
* @return string[]
*/
private static function retrieveExcludedSymbols(array $config, string $key): array
{
if (!array_key_exists($key, $config)) {
return [];
}

$symbols = $config[$key];

self::assertIsArrayOfStrings($symbols, $key);

return $symbols;
}
}
8 changes: 4 additions & 4 deletions src/Symbol/EnrichedReflectorFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ public function __construct(Reflector $reflector)

public function create(SymbolsConfiguration $symbolsConfiguration): EnrichedReflector
{
$configuredReflector = $this->reflector->withSymbols(
$symbolsConfiguration->getExcludedClassNames(),
$symbolsConfiguration->getExcludedFunctionNames(),
$symbolsConfiguration->getExcludedConstantNames(),
$configuredReflector = $this->reflector->withAdditionalSymbols(
$symbolsConfiguration->getExcludedClasses(),
$symbolsConfiguration->getExcludedFunctions(),
$symbolsConfiguration->getExcludedConstants(),
);

return new EnrichedReflector(
Expand Down
19 changes: 7 additions & 12 deletions src/Symbol/Reflector.php
Original file line number Diff line number Diff line change
Expand Up @@ -633,21 +633,16 @@ private function __construct(
$this->constants = $constants;
}

/**
* @param string[] $classNames
* @param string[] $functionNames
* @param string[] $constantNames
*/
public function withSymbols(
array $classNames,
array $functionNames,
array $constantNames
public function withAdditionalSymbols(
SymbolRegistry $classNames,
SymbolRegistry $functionNames,
SymbolRegistry $constantNames
): self
{
return new self(
$this->classes->withAdditionalSymbols($classNames),
$this->functions->withAdditionalSymbols($functionNames),
$this->constants->withAdditionalSymbols($constantNames),
$this->classes->merge($classNames),
$this->functions->merge($functionNames),
$this->constants->merge($constantNames),
);
}

Expand Down
15 changes: 8 additions & 7 deletions src/Symbol/SymbolRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Humbug\PhpScoper\Symbol;

use InvalidArgumentException;
use function array_key_exists;
use function array_keys;
use function array_map;
Expand Down Expand Up @@ -107,20 +108,20 @@ public function matches(string $symbol): bool
return false;
}

/**
* @param string[] $names
* @param string[] $regexes
*/
public function withAdditionalSymbols(array $names = [], array $regexes = []): self
public function merge(SymbolRegistry $registry): self
{
if ($this->constants !== $registry->constants) {
throw new InvalidArgumentException('Cannot merge registries of different symbol types');
}

$args = [
[
...$this->getNames(),
...$names,
...$registry->getNames(),
],
[
...$this->getRegexes(),
...$regexes,
...$registry->getRegexes(),
],
];

Expand Down
2 changes: 0 additions & 2 deletions src/scoper.inc.php.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,6 @@ return [
// '~^$~', // The root namespace only
// '', // Any namespace
],
// Warning: regexes are not supported there (yet)
// See https://github.com/humbug/php-scoper/issues/634
'exclude-classes' => [
// 'ReflectionClassConstant',
],
Expand Down
2 changes: 1 addition & 1 deletion tests/Console/Command/AddPrefixCommandIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
use function Safe\file_put_contents;
use function Safe\preg_replace;
use function Safe\realpath;
use function str_replace;
use function Safe\sprintf;
use function str_replace;
use const DIRECTORY_SEPARATOR;

/**
Expand Down
14 changes: 7 additions & 7 deletions tests/Scoper/PhpScoperSpecTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,10 @@ private static function createScoper(

$reflector = Reflector
::createWithPhpStormStubs()
->withSymbols(
$symbolsConfiguration->getExcludedClassNames(),
$symbolsConfiguration->getExcludedFunctionNames(),
$symbolsConfiguration->getExcludedConstantNames(),
->withAdditionalSymbols(
$symbolsConfiguration->getExcludedClasses(),
$symbolsConfiguration->getExcludedFunctions(),
$symbolsConfiguration->getExcludedConstants(),
);

$enrichedReflector = new EnrichedReflector(
Expand Down Expand Up @@ -451,9 +451,9 @@ private static function createSpecMessage(
$formattedFunctionsToExpose = self::formatSymbolRegistry($symbolsConfiguration->getExposedFunctions());
$formattedConstantsToExpose = self::formatSymbolRegistry($symbolsConfiguration->getExposedConstants());

$formattedInternalClasses = self::formatSimpleList($symbolsConfiguration->getExcludedClassNames());
$formattedInternalFunctions = self::formatSimpleList($symbolsConfiguration->getExcludedFunctionNames());
$formattedInternalConstants = self::formatSimpleList($symbolsConfiguration->getExcludedConstantNames());
$formattedInternalClasses = self::formatSymbolRegistry($symbolsConfiguration->getExcludedClasses());
$formattedInternalFunctions = self::formatSymbolRegistry($symbolsConfiguration->getExcludedFunctions());
$formattedInternalConstants = self::formatSymbolRegistry($symbolsConfiguration->getExcludedConstants());

$formattedExpectedRegisteredClasses = self::formatTupleList($expectedRegisteredClasses);
$formattedExpectedRegisteredFunctions = self::formatTupleList($expectedRegisteredFunctions);
Expand Down
8 changes: 5 additions & 3 deletions tests/Symbol/ConstantSymbolRegistryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,11 @@ public function test_it_can_create_an_augmented_instance(): void
['/^Acme\\\\Foo$/'],
);

$augmentedRegistry = $registry->withAdditionalSymbols(
['Acme\Bar'],
['/^Acme\\\\Bar/'],
$augmentedRegistry = $registry->merge(
SymbolRegistry::createForConstants(
['Acme\Bar'],
['/^Acme\\\\Bar/'],
),
);

SymbolRegistryAssertions::assertStateIs(
Expand Down
Loading

0 comments on commit cb23986

Please sign in to comment.