Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
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
25 changes: 0 additions & 25 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -85,36 +85,11 @@ parameters:
count: 1
path: src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php

-
message: "#^Parameter \\#3 \\$subject of function preg_replace expects array\\|string, string\\|null given\\.$#"
count: 4
path: src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php

-
message: "#^Parameter \\#1 \\$str of function substr expects string, string\\|null given\\.$#"
count: 3
path: src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php

-
message: "#^Parameter \\#1 \\$haystack of function strrpos expects string, string\\|null given\\.$#"
count: 1
path: src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php

-
message: "#^Only booleans are allowed in an if condition, int\\|false given\\.$#"
count: 1
path: src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php

-
message: "#^Parameter \\#2 \\$subject of function preg_match expects string, string\\|null given\\.$#"
count: 1
path: src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php

-
message: "#^Parameter \\#2 \\$subject of function preg_match_all expects string, string\\|null given\\.$#"
count: 1
path: src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php

-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,39 +198,75 @@ private function findSymbols(string $file): array
return ['classes' => [], 'functions' => []];
}

if (!preg_match('{\b(?:class|interface|trait|function)\s}i', $contents)) {
$found = [];
if (stripos($contents, 'class') !== false) {
$found[] = 'class';
}
if (stripos($contents, 'interface') !== false) {
$found[] = 'interface';
}
if (stripos($contents, 'trait') !== false) {
$found[] = 'trait';
}
if (stripos($contents, 'function') !== false) {
$found[] = 'function';
}
if ($found === []) {
return ['classes' => [], 'functions' => []];
}
if (!preg_match('{\b(?:' . \implode('|', $found) . ')\s}i', $contents)) {
return ['classes' => [], 'functions' => []];
}

// strip heredocs/nowdocs
$contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)(?:\s*)\\2(?=\s+|[;,.)])}s', 'null', $contents);
if (strpos($contents, '<<<') !== false) {
$contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)(?:\s*)\\2(?=\s+|[;,.)])}s', 'null', $contents);
assert(is_string($contents));
}

// strip strings
$contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
$contents = preg_replace('{"[^"]*+(?:[^"]*+)*+"|\'[^\']*+(?:[^\']*+)*+\'}', 'null', $contents);
assert(is_string($contents));

// strip leading non-php code if needed
if (substr($contents, 0, 2) !== '<?') {
if (strpos($contents, '<?') !== 0) {
$contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
assert(is_string($contents));
if ($replacements === 0) {
return ['classes' => [], 'functions' => []];
}
}

// strip non-php blocks in the file
$contents = preg_replace('{\?>(?:[^<]++|<(?!\?))*+<\?}s', '?><?', $contents);
if (strpos($contents, '?>') !== false) {
$contents = preg_replace('{\?>(?:[^<]++|<(?!\?))*+<\?}', '?><?', $contents);
assert(is_string($contents));
}

// strip trailing non-php code if needed
$pos = strrpos($contents, '?>');
if ($pos !== false && strpos(substr($contents, $pos), '<?') === false) {
$contents = substr($contents, 0, $pos);
}

// strip comments if short open tags are in the file
if (preg_match('{(<\?)(?!(php|hh))}i', $contents)) {
if (preg_match('{(?:<\?)(?!(?:php|hh))}i', $contents)) {
$contents = preg_replace('{//.* | /\*(?:[^*]++|\*(?!/))*\*/}x', '', $contents);
assert(is_string($contents));
}

if (strpos($contents, 'namespace') !== false) {
$namespaceRegex = '| \b(?<![\$:>])(?P<ns>namespace) (?P<nsname>\s++[a-z_\x7f-\xff][a-z0-9_\x7f-\xff]*+(?:\s*+\\\\\s*+[a-z_\x7f-\xff][a-z0-9_\x7f-\xff]*+)*+)? \s*+ [\{;]';
} else {
$namespaceRegex = '';
}

preg_match_all('{
(?:
\b(?<![\$:>])(?P<type>class|interface|trait|function) \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
| \b(?<![\$:>])(?P<ns>namespace) (?P<nsname>\s++[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\s*+\\\\\s*+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+)? \s*+ [\{;]
)
}ix', $contents, $matches);
(?:
\b(?<![\$:>])(?P<type>' . \implode('|', $found) . ') \s+ (?P<name>[a-z_\x7f-\xff:][a-z0-9_\x7f-\xff:\-]*+)
' . $namespaceRegex . '
)
}ix', $contents, $matches);

$classes = [];
$functions = [];
Expand Down