Skip to content

Commit 98edbfa

Browse files
committed
Detect global user functions (e.g. polyfills)
1 parent 96321e0 commit 98edbfa

File tree

4 files changed

+20
-16
lines changed

4 files changed

+20
-16
lines changed

src/Analyser.php

+6-5
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ class Analyser
123123
*
124124
* @var array<string, SymbolKind::*>
125125
*/
126-
private $extensionSymbolKinds = [];
126+
private $knownSymbolKinds = [];
127127

128128
/**
129129
* @param array<string, ClassLoader> $classLoaders vendorDir => ClassLoader (e.g. result of \Composer\Autoload\ClassLoader::getRegisteredLoaders())
@@ -392,7 +392,7 @@ private function getUsedSymbolsInFile(string $filePath): array
392392
}
393393

394394
return (new UsedSymbolExtractor($code))->parseUsedSymbols(
395-
$this->extensionSymbolKinds
395+
$this->knownSymbolKinds
396396
);
397397
}
398398

@@ -553,7 +553,7 @@ private function initExistingSymbols(Configuration $config): void
553553
$this->ignoredSymbols[$constantName] = true;
554554
} else {
555555
$this->extensionSymbols[SymbolKind::CONSTANT][$constantName] = $extensionName;
556-
$this->extensionSymbolKinds[strtolower($constantName)] = SymbolKind::CONSTANT;
556+
$this->knownSymbolKinds[strtolower($constantName)] = SymbolKind::CONSTANT;
557557
}
558558
}
559559
}
@@ -567,6 +567,7 @@ private function initExistingSymbols(Configuration $config): void
567567
if ($reflectionFunction->getExtension() === null) {
568568
if (is_string($functionFilePath)) {
569569
$this->definedFunctions[$functionName] = Path::normalize($functionFilePath);
570+
$this->knownSymbolKinds[$functionName] = SymbolKind::FUNCTION;
570571
}
571572
} else {
572573
$extensionName = $this->getNormalizedExtensionName($reflectionFunction->getExtension()->name);
@@ -575,7 +576,7 @@ private function initExistingSymbols(Configuration $config): void
575576
$this->ignoredSymbols[$functionName] = true;
576577
} else {
577578
$this->extensionSymbols[SymbolKind::FUNCTION][$functionName] = $extensionName;
578-
$this->extensionSymbolKinds[$functionName] = SymbolKind::FUNCTION;
579+
$this->knownSymbolKinds[$functionName] = SymbolKind::FUNCTION;
579580
}
580581
}
581582
}
@@ -598,7 +599,7 @@ private function initExistingSymbols(Configuration $config): void
598599
$this->ignoredSymbols[$classLikeName] = true;
599600
} else {
600601
$this->extensionSymbols[SymbolKind::CLASSLIKE][$classLikeName] = $extensionName;
601-
$this->extensionSymbolKinds[strtolower($classLikeName)] = SymbolKind::CLASSLIKE;
602+
$this->knownSymbolKinds[strtolower($classLikeName)] = SymbolKind::CLASSLIKE;
602603
}
603604
}
604605
}

src/UsedSymbolExtractor.php

+9-9
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,12 @@ public function __construct(string $code)
6767
* It does not produce any local names in current namespace
6868
* - this results in very limited functionality in files without namespace
6969
*
70-
* @param array<string, SymbolKind::*> $extensionSymbols
70+
* @param array<string, SymbolKind::*> $knownSymbols
7171
* @return array<SymbolKind::*, array<string, list<int>>>
7272
* @license Inspired by https://github.com/doctrine/annotations/blob/2.0.0/lib/Doctrine/Common/Annotations/TokenParser.php
7373
*/
7474
public function parseUsedSymbols(
75-
array $extensionSymbols
75+
array $knownSymbols
7676
): array
7777
{
7878
$usedSymbols = [];
@@ -124,7 +124,7 @@ public function parseUsedSymbols(
124124
case PHP_VERSION_ID >= 80000 ? T_NAME_FULLY_QUALIFIED : -1:
125125
$symbolName = $this->normalizeBackslash($token[1]);
126126
$lowerSymbolName = strtolower($symbolName);
127-
$kind = $extensionSymbols[$lowerSymbolName] ?? $this->getFqnSymbolKind($this->pointer - 2, $this->pointer, $inAttributeSquareLevel !== null);
127+
$kind = $knownSymbols[$lowerSymbolName] ?? $this->getFqnSymbolKind($this->pointer - 2, $this->pointer, $inAttributeSquareLevel !== null);
128128
$usedSymbols[$kind][$symbolName][] = $token[2];
129129
break;
130130

@@ -140,7 +140,7 @@ public function parseUsedSymbols(
140140
}
141141

142142
$lowerSymbolName = strtolower($symbolName);
143-
$kind = $extensionSymbols[$lowerSymbolName] ?? $this->getFqnSymbolKind($this->pointer - 2, $this->pointer, $inAttributeSquareLevel !== null);
143+
$kind = $knownSymbols[$lowerSymbolName] ?? $this->getFqnSymbolKind($this->pointer - 2, $this->pointer, $inAttributeSquareLevel !== null);
144144
$usedSymbols[$kind][$symbolName][] = $token[2];
145145

146146
break;
@@ -160,9 +160,9 @@ public function parseUsedSymbols(
160160
$kind = $useStatementKinds[$name];
161161
$usedSymbols[$kind][$symbolName][] = $token[2];
162162

163-
} elseif (isset($extensionSymbols[$lowerName])) {
163+
} elseif (isset($knownSymbols[$lowerName])) {
164164
$symbolName = $name;
165-
$kind = $extensionSymbols[$lowerName];
165+
$kind = $knownSymbols[$lowerName];
166166

167167
if (!$inGlobalScope && $kind === SymbolKind::CLASSLIKE) {
168168
break; // cannot use class-like symbols in non-global scope when not imported
@@ -192,7 +192,7 @@ public function parseUsedSymbols(
192192
$lowerSymbolName = strtolower($symbolName);
193193

194194
if ($symbolName !== '') { // e.g. \array (NS separator followed by not-a-name)
195-
$kind = $extensionSymbols[$lowerSymbolName] ?? $this->getFqnSymbolKind($pointerBeforeName, $this->pointer - 1, false);
195+
$kind = $knownSymbols[$lowerSymbolName] ?? $this->getFqnSymbolKind($pointerBeforeName, $this->pointer - 1, false);
196196
$usedSymbols[$kind][$symbolName][] = $token[2];
197197
}
198198

@@ -213,9 +213,9 @@ public function parseUsedSymbols(
213213
$kind = $useStatementKinds[$name];
214214
$usedSymbols[$kind][$symbolName][] = $token[2];
215215

216-
} elseif (isset($extensionSymbols[$lowerName])) {
216+
} elseif (isset($knownSymbols[$lowerName])) {
217217
$symbolName = $name;
218-
$kind = $extensionSymbols[$lowerName];
218+
$kind = $knownSymbols[$lowerName];
219219

220220
if (!$inGlobalScope && $kind === SymbolKind::CLASSLIKE) {
221221
break; // cannot use class-like symbols in non-global scope when not imported

tests/UsedSymbolExtractorTest.php

+4-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ public function provideVariants(): iterable
113113
];
114114

115115
yield 'global namespace' => [
116-
117116
__DIR__ . '/data/not-autoloaded/used-symbols/global-namespace.php',
118117
[
119118
SymbolKind::CLASSLIKE => [
@@ -122,8 +121,12 @@ public function provideVariants(): iterable
122121
],
123122
SymbolKind::FUNCTION => [
124123
'PHPUnit\Framework\assertSame' => [7],
124+
'user_defined_function' => [12],
125125
],
126126
],
127+
[
128+
strtolower('user_defined_function') => SymbolKind::FUNCTION,
129+
],
127130
];
128131

129132
yield 'curly braces' => [

tests/data/not-autoloaded/used-symbols/global-namespace.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99
class Foo {
1010
public function someFunction(string $foo): void
1111
{
12-
12+
user_defined_function();
1313
}
1414
}

0 commit comments

Comments
 (0)