From 88908b506c87053f776ffae00162fefef4ce73d9 Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Wed, 15 Nov 2023 23:56:43 -0800 Subject: [PATCH 1/8] Add config --- phpstan.neon | 6 ++++++ phpstanbootstrap.php | 9 +++++++++ 2 files changed, 15 insertions(+) create mode 100644 phpstan.neon create mode 100644 phpstanbootstrap.php diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 00000000..dbaba117 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,6 @@ +parameters: + level: 1 + paths: + - src + bootstrapFiles: + - phpstanbootstrap.php diff --git a/phpstanbootstrap.php b/phpstanbootstrap.php new file mode 100644 index 00000000..192775b4 --- /dev/null +++ b/phpstanbootstrap.php @@ -0,0 +1,9 @@ + Date: Wed, 15 Nov 2023 23:57:19 -0800 Subject: [PATCH 2/8] Fix phpstan level 1 --- src/Autoload.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Autoload.php b/src/Autoload.php index 749a794c..84ddc420 100644 --- a/src/Autoload.php +++ b/src/Autoload.php @@ -100,7 +100,7 @@ protected function generateClassmap(): string array_walk( $dirMap, - function (&$filepath, $_class) use ($dir, $dirname) { + function (&$filepath, $_class) use ($dir) { $filepath = "\$strauss_src . '" . DIRECTORY_SEPARATOR . ltrim(str_replace($dir, '', $filepath), DIRECTORY_SEPARATOR) . "'"; From 8662cb05e8cd6a531e4970451b98e130a14e32be Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Thu, 16 Nov 2023 00:02:34 -0800 Subject: [PATCH 3/8] Fix phpstan level 2 --- phpstan.neon | 2 +- src/Autoload.php | 4 ++-- src/Composer/Extra/StraussConfig.php | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index dbaba117..62f2827c 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,5 @@ parameters: - level: 1 + level: 2 paths: - src bootstrapFiles: diff --git a/src/Autoload.php b/src/Autoload.php index 84ddc420..3aef6171 100644 --- a/src/Autoload.php +++ b/src/Autoload.php @@ -26,7 +26,7 @@ class Autoload * The files autolaoders of packages that have been copied by Strauss. * Keyed by package path. * - * @var array + * @var array> $discoveredFilesAutoloaders Array of packagePath => array of relativeFilePaths. */ protected array $discoveredFilesAutoloaders; @@ -34,7 +34,7 @@ class Autoload * Autoload constructor. * @param StraussConfig $config * @param string $workingDir - * @param array> $files + * @param array> $discoveredFilesAutoloaders */ public function __construct(StraussConfig $config, string $workingDir, array $discoveredFilesAutoloaders) { diff --git a/src/Composer/Extra/StraussConfig.php b/src/Composer/Extra/StraussConfig.php index 6caab7c1..de7f9911 100644 --- a/src/Composer/Extra/StraussConfig.php +++ b/src/Composer/Extra/StraussConfig.php @@ -375,7 +375,7 @@ public function setExcludeFromPrefix(array $excludeFromPrefix): void /** * When prefixing, do not prefix these packages (which have been copied). * - * @var string[] + * @return string[] */ public function getExcludePackagesFromPrefixing(): array { @@ -534,7 +534,7 @@ public function isIncludeAuthor(): bool } /** - * @param bool $includeModifiedDate + * @param bool $includeAuthor */ public function setIncludeAuthor(bool $includeAuthor): void { From f305a3e54854261010623cfda953976414cdbf89 Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Thu, 16 Nov 2023 00:05:02 -0800 Subject: [PATCH 4/8] Fix phpstan level 3 --- phpstan.neon | 2 +- src/Composer/Extra/StraussConfig.php | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index 62f2827c..5d0a0008 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,5 @@ parameters: - level: 2 + level: 3 paths: - src bootstrapFiles: diff --git a/src/Composer/Extra/StraussConfig.php b/src/Composer/Extra/StraussConfig.php index de7f9911..15605df9 100644 --- a/src/Composer/Extra/StraussConfig.php +++ b/src/Composer/Extra/StraussConfig.php @@ -69,7 +69,7 @@ class StraussConfig protected array $excludeFromCopy = array(); /** - * @var array{packages: string[], namespaces: string[], filePatterns: string[]} + * @var array{packages: string[], namespaces: string[], file_patterns: string[]} */ protected array $excludeFromPrefix = array('file_patterns'=>array(),'namespaces'=>array(),'packages'=>array()); @@ -483,11 +483,6 @@ public function setClassmapOutput(bool $classmapOutput): void */ public function setExcludePackages(array $excludePackages) { - - if (! isset($this->excludeFromPrefix)) { - $this->excludeFromPrefix = array(); - } - $this->excludeFromPrefix['packages'] = $excludePackages; } From e6bf44230b73b0559b3697b4d883a0ffbdb7be5c Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Thu, 16 Nov 2023 00:20:21 -0800 Subject: [PATCH 5/8] Fix phpstan level 4 --- phpstan.neon | 6 +++++- src/Composer/Extra/StraussConfig.php | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index 5d0a0008..4816f623 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,6 +1,10 @@ parameters: - level: 3 + level: 4 paths: - src bootstrapFiles: - phpstanbootstrap.php + ignoreErrors: + - + message: '#Property.*excludePackages is unused#' + path: src/Composer/Extra/StraussConfig.php diff --git a/src/Composer/Extra/StraussConfig.php b/src/Composer/Extra/StraussConfig.php index 15605df9..a81d100f 100644 --- a/src/Composer/Extra/StraussConfig.php +++ b/src/Composer/Extra/StraussConfig.php @@ -64,9 +64,9 @@ class StraussConfig private array $excludePackages; /** - * @var array{packages?: string[], namespaces?: string[], filePatterns?: string[]} + * @var array{packages: string[], namespaces: string[], file_patterns: string[]} */ - protected array $excludeFromCopy = array(); + protected array $excludeFromCopy = array('file_patterns'=>array(),'namespaces'=>array(),'packages'=>array()); /** * @var array{packages: string[], namespaces: string[], file_patterns: string[]} From 46979678e112b0b9d5dbd490e56e97b41f776dba Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Thu, 16 Nov 2023 10:54:12 -0800 Subject: [PATCH 6/8] Fix phpstan level 6 --- phpstan.neon | 2 +- src/Autoload.php | 6 +- src/ChangeEnumerator.php | 8 ++- src/Cleanup.php | 4 +- src/Composer/ComposerPackage.php | 17 +++--- src/Composer/Extra/StraussConfig.php | 77 +++++++++++++++++++------ src/Composer/ProjectComposerPackage.php | 6 +- src/Console/Commands/Compose.php | 22 ++++--- src/FileEnumerator.php | 9 ++- src/Licenser.php | 11 +++- src/Prefixer.php | 29 ++++++++-- 11 files changed, 136 insertions(+), 55 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index 4816f623..822bd7b2 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,5 @@ parameters: - level: 4 + level: 6 paths: - src bootstrapFiles: diff --git a/src/Autoload.php b/src/Autoload.php index 3aef6171..83577b96 100644 --- a/src/Autoload.php +++ b/src/Autoload.php @@ -44,7 +44,7 @@ public function __construct(StraussConfig $config, string $workingDir, array $di $this->filesystem = new Filesystem(new Local($workingDir)); } - public function generate() + public function generate(): void { // Do not overwrite Composer's autoload.php. // The correct solution is to add "classmap": ["vendor"] to composer.json, then run composer dump-autoload. @@ -126,7 +126,7 @@ function (&$filepath, $_class) use ($dir) { return $dirname; } - protected function generateFilesAutoloader() + protected function generateFilesAutoloader(): void { // Hyphen used to match WordPress Coding Standards. @@ -166,7 +166,7 @@ protected function generateFilesAutoloader() file_put_contents($targetDirectory . $outputFilename, ob_get_clean()); } - protected function generateAutoloadPhp() + protected function generateAutoloadPhp(): void { $autoloadPhp = <<<'EOD' diff --git a/src/ChangeEnumerator.php b/src/ChangeEnumerator.php index 665607f9..673a02af 100644 --- a/src/ChangeEnumerator.php +++ b/src/ChangeEnumerator.php @@ -20,10 +20,14 @@ class ChangeEnumerator * @var string[] */ protected array $excludePackagesFromPrefixing = array(); + + /** @var string[] */ protected array $excludeNamespacesFromPrefixing = array(); + /** @var string[] */ protected array $excludeFilePatternsFromPrefixing = array(); + /** @var string[] */ protected array $namespaceReplacementPatterns = array(); /** @var string[] */ @@ -88,7 +92,7 @@ public function getDiscoveredConstants(): array * @param string $absoluteTargetDir * @param array $filesArray */ - public function findInFiles($absoluteTargetDir, $filesArray) + public function findInFiles($absoluteTargetDir, $filesArray): void { // $relativeFilepaths = array_keys( $filesArray ); @@ -189,7 +193,7 @@ function ($matches) { ); } - protected function addDiscoveredNamespaceChange(string $namespace) + protected function addDiscoveredNamespaceChange(string $namespace): void { foreach ($this->excludeNamespacesFromPrefixing as $excludeNamespace) { diff --git a/src/Cleanup.php b/src/Cleanup.php index 1814b844..01e6e19d 100644 --- a/src/Cleanup.php +++ b/src/Cleanup.php @@ -36,9 +36,9 @@ public function __construct(StraussConfig $config, string $workingDir) * Maybe delete the source files that were copied (depending on config), * then delete empty directories. * - * @param array $sourceFiles + * @param string[] $sourceFiles Relative filepaths. */ - public function cleanup(array $sourceFiles) + public function cleanup(array $sourceFiles): void { if (!$this->isDeleteVendorPackages && !$this->isDeleteVendorFiles) { return; diff --git a/src/Composer/ComposerPackage.php b/src/Composer/ComposerPackage.php index bd5b4107..f7f8794d 100644 --- a/src/Composer/ComposerPackage.php +++ b/src/Composer/ComposerPackage.php @@ -10,8 +10,10 @@ use Composer\Composer; use Composer\Factory; use Composer\IO\NullIO; -use stdClass; +/** + * @phpstan-type AutoloadKey array{files?:array,classmap?:array,"psr-4"?:array>} + */ class ComposerPackage { /** @@ -57,7 +59,7 @@ class ComposerPackage /** * The names in the composer.json's "requires" field (without versions). * - * @var array + * @var string[] */ protected array $requiresNames = []; @@ -67,7 +69,7 @@ class ComposerPackage * @param string $absolutePath The absolute path to the vendor folder with the composer.json "name", * i.e. the domain/package definition, which is the vendor subdir from where the package's * composer.json should be read. - * @param ?array $overrideAutoload Optional configuration to replace the package's own autoload definition with + * @param ?array{files?:array, classmap?:array, psr?:array>} $overrideAutoload Optional configuration to replace the package's own autoload definition with * another which Strauss can use. * @return ComposerPackage */ @@ -83,9 +85,8 @@ public static function fromFile(string $absolutePath, array $overrideAutoload = } /** - * @param array $jsonArray composer.json decoded to array - * @param ?array $overrideAutoload - * @return ComposerPackage + * @param array{name?:string, license?:string, requires?:array, autoload?:AutoloadKey} $jsonArray composer.json decoded to array + * @param ?AutoloadKey $overrideAutoload New autoload rules to replace the existing ones. */ public static function fromComposerJsonArray($jsonArray, array $overrideAutoload = null): ComposerPackage { @@ -99,8 +100,8 @@ public static function fromComposerJsonArray($jsonArray, array $overrideAutoload /** * Create a PHP object to represent a composer package. * - * @param array $overrideAutoload Optional configuration to replace the package's own autoload definition with - * another which Strauss can use. + * @param Composer $composer + * @param ?AutoloadKey $overrideAutoload Optional configuration to replace the package's own autoload definition with another which Strauss can use. */ public function __construct(Composer $composer, array $overrideAutoload = null) { diff --git a/src/Composer/Extra/StraussConfig.php b/src/Composer/Extra/StraussConfig.php index a81d100f..76b2a3b4 100644 --- a/src/Composer/Extra/StraussConfig.php +++ b/src/Composer/Extra/StraussConfig.php @@ -56,14 +56,20 @@ class StraussConfig * * If this is empty, the "requires" list in the project composer.json is used. * - * @var array + * @var string[] */ protected array $packages = []; - // Back-compatibility with Mozart. + /** + * Back-compatibility with Mozart. + * + * @var string[] + */ private array $excludePackages; /** + * 'exclude_from_copy' in composer/extra config. + * * @var array{packages: string[], namespaces: string[], file_patterns: string[]} */ protected array $excludeFromCopy = array('file_patterns'=>array(),'namespaces'=>array(),'packages'=>array()); @@ -81,28 +87,32 @@ class StraussConfig * * A package specified both a PSR-4 and a classmap but only needs one * ... * - * @var array + * @var array,classmap?:array,"psr-4":array>}>|array{} $overrideAutoload */ - protected $overrideAutoload = []; + protected array $overrideAutoload = []; /** * After completing prefixing should the source files be deleted? * This does not affect symlinked directories. - * - * @var bool */ - protected $deleteVendorFiles = false; + protected bool $deleteVendorFiles = false; /** * After completing prefixing should the source packages be deleted? * This does not affect symlinked directories. - * - * @var bool */ - protected $deleteVendorPackages = false; + protected bool $deleteVendorPackages = false; protected bool $classmapOutput; + /** + * A dictionary of regex captures => regex replacements. + * + * E.g. used to avoid repetition of the plugin vendor name in namespaces. + * `"~BrianHenryIE\\\\(.*)~" : "BrianHenryIE\\WC_Cash_App_Gateway\\\\$1"`. + * + * @var array $namespaceReplacementPatterns + */ protected array $namespaceReplacementPatterns = array(); /** @@ -338,27 +348,45 @@ public function setConstantsPrefix(string $constantsPrefix): void $this->constantsPrefix = $constantsPrefix; } + /** + * @param array{packages?:array, namespaces?:array, file_patterns?:array} $excludeFromCopy + */ public function setExcludeFromCopy(array $excludeFromCopy): void { - $this->excludeFromCopy = $excludeFromCopy; + foreach (array( 'packages', 'namespaces', 'file_patterns' ) as $key) { + if (isset($excludeFromCopy[$key])) { + $this->excludeFromCopy[$key] = $excludeFromCopy[$key]; + } + } } + /** + * @return string[] + */ public function getExcludePackagesFromCopy(): array { return $this->excludeFromCopy['packages'] ?? array(); } + /** + * @return string[] + */ public function getExcludeNamespacesFromCopy(): array { return $this->excludeFromCopy['namespaces'] ?? array(); } + /** + * @return string[] + */ public function getExcludeFilePatternsFromCopy(): array { return $this->excludeFromCopy['file_patterns'] ?? array(); } - + /** + * @param array{packages?:array, namespaces?:array, file_patterns?:array} $excludeFromPrefix + */ public function setExcludeFromPrefix(array $excludeFromPrefix): void { if (isset($excludeFromPrefix['packages'])) { @@ -382,16 +410,25 @@ public function getExcludePackagesFromPrefixing(): array return $this->excludeFromPrefix['packages'] ?? array(); } + /** + * @param string[] $excludePackagesFromPrefixing + */ public function setExcludePackagesFromPrefixing(array $excludePackagesFromPrefixing): void { $this->excludeFromPrefix['packages'] = $excludePackagesFromPrefixing; } + /** + * @return string[] + */ public function getExcludeNamespacesFromPrefixing(): array { return $this->excludeFromPrefix['namespaces'] ?? array(); } + /** + * @return string[] + */ public function getExcludeFilePatternsFromPrefixing(): array { return $this->excludeFromPrefix['file_patterns'] ?? array(); @@ -399,7 +436,7 @@ public function getExcludeFilePatternsFromPrefixing(): array /** - * @return array + * @return array{}|array,classmap?:array,"psr-4":array>}> $overrideAutoload Dictionary of package name: autoload rules. */ public function getOverrideAutoload(): array { @@ -407,7 +444,7 @@ public function getOverrideAutoload(): array } /** - * @param array $overrideAutoload + * @param array,classmap?:array,"psr-4":array>}> $overrideAutoload Dictionary of package name: autoload rules. */ public function setOverrideAutoload(array $overrideAutoload): void { @@ -447,7 +484,7 @@ public function setDeleteVendorPackages(bool $deleteVendorPackages): void } /** - * @return array + * @return string[] */ public function getPackages(): array { @@ -455,7 +492,7 @@ public function getPackages(): array } /** - * @param array $packages + * @param string[] $packages */ public function setPackages(array $packages): void { @@ -480,15 +517,17 @@ public function setClassmapOutput(bool $classmapOutput): void /** * Backwards compatibility with Mozart. + * + * @param string[] $excludePackages */ - public function setExcludePackages(array $excludePackages) + public function setExcludePackages(array $excludePackages): void { $this->excludeFromPrefix['packages'] = $excludePackages; } /** - * @return array + * @return array */ public function getNamespaceReplacementPatterns(): array { @@ -496,7 +535,7 @@ public function getNamespaceReplacementPatterns(): array } /** - * @param array $namespaceReplacementPatterns + * @param array $namespaceReplacementPatterns */ public function setNamespaceReplacementPatterns(array $namespaceReplacementPatterns): void { diff --git a/src/Composer/ProjectComposerPackage.php b/src/Composer/ProjectComposerPackage.php index 325967c2..09459c78 100644 --- a/src/Composer/ProjectComposerPackage.php +++ b/src/Composer/ProjectComposerPackage.php @@ -15,7 +15,11 @@ class ProjectComposerPackage extends ComposerPackage protected string $vendorDirectory; - public function __construct(string $absolutePath, array $overrideAutoload = null) + /** + * @param string $absolutePath + * @param ?array{files?:array,classmap?:array,"psr-4"?:array>} $overrideAutoload + */ + public function __construct(string $absolutePath, ?array $overrideAutoload = null) { if (is_dir($absolutePath)) { $absolutePathDir = $absolutePath; diff --git a/src/Console/Commands/Compose.php b/src/Console/Commands/Compose.php index 068d0cb4..6d5b0c2d 100644 --- a/src/Console/Commands/Compose.php +++ b/src/Console/Commands/Compose.php @@ -93,7 +93,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int * * @throws Exception */ - protected function loadProjectComposerPackage() + protected function loadProjectComposerPackage(): void { $this->projectComposerPackage = new ProjectComposerPackage($this->workingDir); @@ -114,7 +114,7 @@ protected function loadProjectComposerPackage() * * @see Compose::flatDependencyTree */ - protected function buildDependencyList() + protected function buildDependencyList(): void { $requiredPackageNames = $this->config->getPackages(); @@ -122,11 +122,15 @@ protected function buildDependencyList() $this->recursiveGetAllDependencies($requiredPackageNames); } + /** @var string[] */ protected $virtualPackages = array( 'php-http/client-implementation' ); - protected function recursiveGetAllDependencies(array $requiredPackageNames) + /** + * @param string[] $requiredPackageNames + */ + protected function recursiveGetAllDependencies(array $requiredPackageNames): void { $virtualPackages = $this->virtualPackages; @@ -176,7 +180,7 @@ protected function recursiveGetAllDependencies(array $requiredPackageNames) protected FileEnumerator $fileEnumerator; - protected function enumerateFiles() + protected function enumerateFiles(): void { $this->fileEnumerator = new FileEnumerator( @@ -189,7 +193,7 @@ protected function enumerateFiles() } // 3. Copy autoloaded files for each - protected function copyFiles() + protected function copyFiles(): void { if ($this->config->getTargetDirectory() === $this->config->getVendorDirectory()) { // Nothing to do. @@ -209,7 +213,7 @@ protected function copyFiles() } // 4. Determine namespace and classname changes - protected function determineChanges() + protected function determineChanges(): void { $this->changeEnumerator = new ChangeEnumerator($this->config); @@ -221,7 +225,7 @@ protected function determineChanges() // 5. Update namespaces and class names. // Replace references to updated namespaces and classnames throughout the dependencies. - protected function performReplacements() + protected function performReplacements(): void { $this->replacer = new Prefixer($this->config, $this->workingDir); @@ -252,7 +256,7 @@ protected function addLicenses(): void /** * 6. Generate autoloader. */ - protected function generateAutoloader() + protected function generateAutoloader(): void { if ($this->config->getTargetDirectory() === $this->config->getVendorDirectory()) { // Nothing to do. @@ -272,7 +276,7 @@ protected function generateAutoloader() * Delete source files if desired. * Delete empty directories in destination. */ - protected function cleanUp() + protected function cleanUp(): void { if ($this->config->getTargetDirectory() === $this->config->getVendorDirectory()) { // Nothing to do. diff --git a/src/FileEnumerator.php b/src/FileEnumerator.php index 5ce43c4d..7935d22e 100644 --- a/src/FileEnumerator.php +++ b/src/FileEnumerator.php @@ -30,8 +30,13 @@ class FileEnumerator /** @var ComposerPackage[] */ protected array $dependencies; + /** @var string[] */ protected array $excludePackageNames = array(); + + /** @var string[] */ protected array $excludeNamespaces = array(); + + /** @var string[] */ protected array $excludeFilePatterns = array(); /** @var Filesystem */ @@ -47,7 +52,7 @@ class FileEnumerator /** * Record the files autolaoders for later use in building our own autoloader. * - * @var array + * @var array>> */ protected array $filesAutoloaders = []; @@ -76,7 +81,7 @@ public function __construct( /** * Read the autoload keys of the dependencies and generate a list of the files referenced. */ - public function compileFileList() + public function compileFileList(): void { $prefixToRemove = $this->workingDir . $this->vendorDir; diff --git a/src/Licenser.php b/src/Licenser.php index 793b3d64..ce868bf5 100644 --- a/src/Licenser.php +++ b/src/Licenser.php @@ -29,6 +29,7 @@ class Licenser protected string $vendorDir; + /** @var ComposerPackage[] */ protected array $dependencies; // The author of the current project who is running Strauss to make the changes to the required libraries. @@ -57,8 +58,9 @@ class Licenser /** * Licenser constructor. + * * @param string $workingDir - * @param array $dependencies Whose folders are searched for existing license.txt files. + * @param ComposerPackage[] $dependencies Whose folders are searched for existing license.txt files. * @param string $author To add to each modified file's header */ public function __construct(StraussConfig $config, string $workingDir, array $dependencies, string $author) @@ -105,7 +107,7 @@ public function copyLicenses(): void /** * @see https://www.phpliveregex.com/p/A5y */ - public function findLicenseFiles(?Finder $finder = null) + public function findLicenseFiles(?Finder $finder = null): void { // Include all license files in the dependency path. @@ -137,6 +139,9 @@ public function findLicenseFiles(?Finder $finder = null) } } + /** + * @return string[] + */ public function getDiscoveredLicenseFiles(): array { return array_keys($this->discoveredLicenseFiles); @@ -145,7 +150,7 @@ public function getDiscoveredLicenseFiles(): array /** * @param array $modifiedFiles */ - public function addInformationToUpdatedFiles(array $modifiedFiles) + public function addInformationToUpdatedFiles(array $modifiedFiles): void { // e.g. "25-April-2021". diff --git a/src/Prefixer.php b/src/Prefixer.php index 706a49fc..bf900791 100644 --- a/src/Prefixer.php +++ b/src/Prefixer.php @@ -22,8 +22,13 @@ class Prefixer protected string $classmapPrefix; protected ?string $constantsPrefix; + /** @var string[] */ protected array $excludePackageNamesFromPrefixing; + + /** @var string[] */ protected array $excludeNamespacesFromPrefixing; + + /** @var string[] */ protected array $excludeFilePatternsFromPrefixing; /** @var array */ @@ -49,11 +54,12 @@ public function __construct(StraussConfig $config, string $workingDir) /** * @param array $namespaceChanges - * @param array $classChanges + * @param string[] $classChanges + * @param string[] $constants * @param array $phpFileArrays * @throws FileNotFoundException */ - public function replaceInFiles(array $namespaceChanges, array $classChanges, array $constants, array $phpFileArrays) + public function replaceInFiles(array $namespaceChanges, array $classChanges, array $constants, array $phpFileArrays): void { foreach ($phpFileArrays as $targetRelativeFilepath => $fileArray) { @@ -85,6 +91,12 @@ public function replaceInFiles(array $namespaceChanges, array $classChanges, arr } } + /** + * @param array $namespacesChanges + * @param string[] $classes + * @param string[] $originalConstants + * @param string $contents + */ public function replaceInString(array $namespacesChanges, array $classes, array $originalConstants, string $contents): string { @@ -119,10 +131,12 @@ public function replaceInString(array $namespacesChanges, array $classes, array * TODO: Test against traits. * * @param string $contents The text to make replacements in. + * @param string $originalNamespace + * @param string $replacement * * @return string The updated text. */ - public function replaceNamespace($contents, $originalNamespace, $replacement) + public function replaceNamespace(string $contents, string $originalNamespace, string $replacement): string { $searchNamespace = '\\'.rtrim($originalNamespace, '\\') . '\\'; @@ -330,7 +344,12 @@ function ($matches) use ($replacement) { return $contents; } - protected function replaceConstants($contents, $originalConstants, $prefix): string + /** + * @param string $contents + * @param string[] $originalConstants + * @param string $prefix + */ + protected function replaceConstants(string $contents, array $originalConstants, string $prefix): string { foreach ($originalConstants as $constant) { @@ -340,7 +359,7 @@ protected function replaceConstants($contents, $originalConstants, $prefix): str return $contents; } - protected function replaceConstant($contents, $originalConstant, $replacementConstant): string + protected function replaceConstant(string $contents, string $originalConstant, string $replacementConstant): string { return str_replace($originalConstant, $replacementConstant, $contents); } From e023b7aed0154578a5976ae931a6a7855717f657 Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Thu, 16 Nov 2023 11:14:07 -0800 Subject: [PATCH 7/8] Add PhpStan badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8520239e..f58c26ba 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![PHPUnit ](.github/coverage.svg)](https://brianhenryie.github.io/strauss/) +[![PHPUnit ](.github/coverage.svg)](https://brianhenryie.github.io/strauss/) [![PHPStan ](https://img.shields.io/badge/PHPStan-Level%206-2a5ea7.svg)](https://phpstan.org/) # Strauss From 494a19005d901485347ddee0d4b6d01bd2baf31c Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Thu, 16 Nov 2023 11:41:56 -0800 Subject: [PATCH 8/8] Fix phpstan level 7 --- README.md | 2 +- phpstan.neon | 2 +- src/Autoload.php | 10 ++-------- src/ChangeEnumerator.php | 3 +++ src/Composer/ComposerPackage.php | 4 ++-- src/Console/Commands/Compose.php | 6 +++++- src/FileEnumerator.php | 12 ++++++++++-- src/Licenser.php | 3 +++ src/Prefixer.php | 10 ++++++++-- 9 files changed, 35 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index f58c26ba..96670b76 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![PHPUnit ](.github/coverage.svg)](https://brianhenryie.github.io/strauss/) [![PHPStan ](https://img.shields.io/badge/PHPStan-Level%206-2a5ea7.svg)](https://phpstan.org/) +[![PHPUnit ](.github/coverage.svg)](https://brianhenryie.github.io/strauss/) [![PHPStan ](https://img.shields.io/badge/PHPStan-Level%207-2a5ea7.svg)](https://phpstan.org/) # Strauss diff --git a/phpstan.neon b/phpstan.neon index 822bd7b2..e37df627 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,5 @@ parameters: - level: 6 + level: 7 paths: - src bootstrapFiles: diff --git a/src/Autoload.php b/src/Autoload.php index 83577b96..1382ba7b 100644 --- a/src/Autoload.php +++ b/src/Autoload.php @@ -73,7 +73,7 @@ public function generate(): void * @see ClassMapGenerator::dump() * */ - protected function generateClassmap(): string + protected function generateClassmap(): void { // Hyphen used to match WordPress Coding Standards. @@ -87,8 +87,6 @@ protected function generateClassmap(): string $targetDirectory ); - $dirname = ''; - foreach ($dirs as $dir) { if (!is_dir($dir)) { continue; @@ -96,8 +94,6 @@ protected function generateClassmap(): string $dirMap = ClassMapGenerator::createMap($dir); - $dirname = preg_replace('/[^a-z]/i', '', str_replace(getcwd(), '', $dir)); - array_walk( $dirMap, function (&$filepath, $_class) use ($dir) { @@ -122,8 +118,6 @@ function (&$filepath, $_class) use ($dir) { file_put_contents($dir . $output_filename, ob_get_clean()); } - - return $dirname; } protected function generateFilesAutoloader(): void @@ -142,7 +136,7 @@ protected function generateFilesAutoloader(): void . DIRECTORY_SEPARATOR . ltrim($this->config->getTargetDirectory(), DIRECTORY_SEPARATOR); - $dirname = preg_replace('/[^a-z]/i', '', str_replace(getcwd(), '', $targetDirectory)); +// $dirname = preg_replace('/[^a-z]/i', '', str_replace(getcwd(), '', $targetDirectory)); ob_start(); diff --git a/src/ChangeEnumerator.php b/src/ChangeEnumerator.php index 673a02af..85e8b1cc 100644 --- a/src/ChangeEnumerator.php +++ b/src/ChangeEnumerator.php @@ -117,6 +117,9 @@ public function findInFiles($absoluteTargetDir, $filesArray): void // $contents = $this->filesystem->read($targetFile); $contents = file_get_contents($filepath); + if (false === $contents) { + throw new \Exception("Failed to read file at {$filepath}"); + } $this->find($contents); } diff --git a/src/Composer/ComposerPackage.php b/src/Composer/ComposerPackage.php index f7f8794d..f22198b9 100644 --- a/src/Composer/ComposerPackage.php +++ b/src/Composer/ComposerPackage.php @@ -52,7 +52,7 @@ class ComposerPackage /** * The discovered files, classmap, psr0 and psr4 autoload keys discovered (as parsed by Composer). * - * @var array> + * @var AutoloadKey */ protected array $autoload = []; @@ -166,7 +166,7 @@ public function getPackageAbsolutePath(): ?string * e.g. ['psr-4' => [ 'BrianHenryIE\Project' => 'src' ]] * e.g. ['psr-4' => [ 'BrianHenryIE\Project' => ['src','lib] ]] * - * @return array>> + * @return AutoloadKey */ public function getAutoload(): array { diff --git a/src/Console/Commands/Compose.php b/src/Console/Commands/Compose.php index 6d5b0c2d..69a64d38 100644 --- a/src/Console/Commands/Compose.php +++ b/src/Console/Commands/Compose.php @@ -155,7 +155,11 @@ protected function recursiveGetAllDependencies(array $requiredPackageNames): voi if (file_exists($packageComposerFile)) { $requiredComposerPackage = ComposerPackage::fromFile($packageComposerFile, $overrideAutoload); } else { - $composerLock = json_decode(file_get_contents($this->workingDir . 'composer.lock'), true); + $fileContents = file_get_contents($this->workingDir . 'composer.lock'); + if (false === $fileContents) { + throw new Exception('Failed to read contents of ' . $this->workingDir . 'composer.lock'); + } + $composerLock = json_decode($fileContents, true); $requiredPackageComposerJson = null; foreach ($composerLock['packages'] as $packageJson) { if ($requiredPackageName === $packageJson['name']) { diff --git a/src/FileEnumerator.php b/src/FileEnumerator.php index 7935d22e..c2345c44 100644 --- a/src/FileEnumerator.php +++ b/src/FileEnumerator.php @@ -50,9 +50,11 @@ class FileEnumerator protected array $filesWithDependencies = []; /** - * Record the files autolaoders for later use in building our own autoloader. + * Record the files autoloaders for later use in building our own autoloader. * - * @var array>> + * Package-name: [ dir1, file1, file2, ... ]. + * + * @var array */ protected array $filesAutoloaders = []; @@ -128,6 +130,9 @@ public function compileFileList(): void $outputRelativeFilepath = str_replace($prefixToRemove, '', $sourceAbsoluteFilepath); $outputRelativeFilepath = preg_replace('#[\\\/]+#', DIRECTORY_SEPARATOR, $outputRelativeFilepath); + if (is_null($outputRelativeFilepath)) { + throw new \Exception('Error replacing directory separator in outputRelativeFilepath.'); + } $file = array( 'dependency' => $dependency, @@ -165,6 +170,9 @@ public function compileFileList(): void // lines above before being used. // Replace multiple \ and/or / with OS native DIRECTORY_SEPARATOR. $outputRelativeFilepath = preg_replace('#[\\\/]+#', DIRECTORY_SEPARATOR, $outputRelativeFilepath); + if (is_null($outputRelativeFilepath)) { + throw new \Exception('Error replacing directory separator in outputRelativeFilepath.'); + } foreach ($this->excludeFilePatterns as $excludePattern) { if (1 === preg_match($excludePattern, $outputRelativeFilepath)) { diff --git a/src/Licenser.php b/src/Licenser.php index ce868bf5..e21c80ed 100644 --- a/src/Licenser.php +++ b/src/Licenser.php @@ -163,6 +163,9 @@ public function addInformationToUpdatedFiles(array $modifiedFiles): void // Throws an exception, but unlikely to happen. $contents = $this->filesystem->read($filepath); + if (false === $contents) { + throw new \Exception("Could not read file: {$filepath}"); + } $updatedContents = $this->addChangeDeclarationToPhpString($contents, $date, $packageLicense); diff --git a/src/Prefixer.php b/src/Prefixer.php index bf900791..485ecde6 100644 --- a/src/Prefixer.php +++ b/src/Prefixer.php @@ -81,6 +81,9 @@ public function replaceInFiles(array $namespaceChanges, array $classChanges, arr // Throws an exception, but unlikely to happen. $contents = $this->filesystem->read($targetRelativeFilepathFromProject); + if (false === $contents) { + throw new Exception("Failed to read file: {$targetRelativeFilepathFromProject}"); + } $updatedContents = $this->replaceInString($namespaceChanges, $classChanges, $constants, $contents); @@ -235,10 +238,9 @@ public function replaceNamespace(string $contents, string $originalNamespace, st * @param string $contents * @param string $originalClassname * @param string $classnamePrefix - * @return array|string|string[]|null * @throws \Exception */ - public function replaceClassname($contents, $originalClassname, $classnamePrefix) + public function replaceClassname(string $contents, string $originalClassname, string $classnamePrefix): string { $searchClassname = preg_quote($originalClassname, '/'); @@ -287,6 +289,10 @@ public function replaceClassname($contents, $originalClassname, $classnamePrefix $result = preg_replace_callback($pattern, $replacingFunction, $contents); + if (is_null($result)) { + throw new Exception('preg_replace_callback returned null'); + } + $matchingError = preg_last_error(); if (0 !== $matchingError) { $message = "Matching error {$matchingError}";