Skip to content

Commit

Permalink
FileExcluder: Improve performance of isExcludedFromAnalysing
Browse files Browse the repository at this point in the history
  • Loading branch information
dktapps committed Oct 24, 2021
1 parent e42a6d1 commit 669b6cd
Showing 1 changed file with 24 additions and 15 deletions.
39 changes: 24 additions & 15 deletions src/File/FileExcluder.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@ class FileExcluder
*
* @var string[]
*/
private array $analyseExcludes;
private array $literalAnalyseExcludes = [];

/**
* fnmatch() patterns to use for excluding files and directories from analysing
* @var string[]
*/
private array $fnmatchAnalyseExcludes = [];

private int $fnmatchFlags;

/**
* @param FileHelper $fileHelper
Expand All @@ -23,7 +31,7 @@ public function __construct(
array $stubFiles
)
{
$this->analyseExcludes = array_map(function (string $exclude) use ($fileHelper): string {
foreach (array_merge($analyseExcludes, $stubFiles) as $exclude) {
$len = strlen($exclude);
$trailingDirSeparator = ($len > 0 && in_array($exclude[$len - 1], ['\\', '/'], true));

Expand All @@ -34,28 +42,29 @@ public function __construct(
}

if ($this->isFnmatchPattern($normalized)) {
return $normalized;
$this->fnmatchAnalyseExcludes[] = $normalized;
} else {
$this->literalAnalyseExcludes[] = $fileHelper->absolutizePath($normalized);
}
}

return $fileHelper->absolutizePath($normalized);
}, array_merge($analyseExcludes, $stubFiles));
$isWindows = DIRECTORY_SEPARATOR === '\\';
if ($isWindows) {
$this->fnmatchFlags = FNM_NOESCAPE | FNM_CASEFOLD;

This comment has been minimized.

Copy link
@staabm

staabm Oct 24, 2021

Contributor

Why do we need the new property? Could this still be a local variable in isExcludedFromAnalysing?

This comment has been minimized.

Copy link
@dktapps

dktapps Oct 24, 2021

Author Contributor

It's a micro optimisation, but it avoids re-evaluating this logic for every fnmatch pattern for every single call to isExcludedFromAnalysing(). It doesn't really make sense to leave it in the function body since the result isn't going to change.

} else {
$this->fnmatchFlags = 0;
}
}

public function isExcludedFromAnalysing(string $file): bool
{
foreach ($this->analyseExcludes as $exclude) {
foreach ($this->literalAnalyseExcludes as $exclude) {
if (strpos($file, $exclude) === 0) {
return true;
}

$isWindows = DIRECTORY_SEPARATOR === '\\';
if ($isWindows) {
$fnmatchFlags = FNM_NOESCAPE | FNM_CASEFOLD;
} else {
$fnmatchFlags = 0;
}

if ($this->isFnmatchPattern($exclude) && fnmatch($exclude, $file, $fnmatchFlags)) {
}
foreach ($this->fnmatchAnalyseExcludes as $exclude) {
if (fnmatch($exclude, $file, $this->fnmatchFlags)) {
return true;
}
}
Expand Down

0 comments on commit 669b6cd

Please sign in to comment.