Skip to content

Commit 160c1c6

Browse files
authored
Detect global user functions (e.g. polyfills) (#210)
1 parent 6d1ad56 commit 160c1c6

File tree

7 files changed

+32
-23
lines changed

7 files changed

+32
-23
lines changed

.github/workflows/e2e.yml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,6 @@ jobs:
147147
repo: mimmi20/ua-device-type
148148
-
149149
repo: mimmi20/ua-normalizer
150-
-
151-
repo: numero2/contao-marketing-suite
152-
cdaArgs: --disable-ext-analysis --config=depcheck.php
153150
-
154151
repo: numero2/contao-opengraph3
155152
cdaArgs: --config=depcheck.php
@@ -176,6 +173,7 @@ jobs:
176173
-
177174
repo: phpstan/phpstan-src
178175
cdaArgs: --disable-ext-analysis --config=build/composer-dependency-analyser.php
176+
php: 8.4
179177
-
180178
repo: qossmic/deptrac-src
181179
-
@@ -208,8 +206,6 @@ jobs:
208206
repo: shipmonk-rnd/phpstan-rules
209207
-
210208
repo: symplify/config-transformer
211-
-
212-
repo: teamneusta/pimcore-testing-framework
213209
-
214210
repo: wallabag/wallabag
215211
cdaArgs: --disable-ext-analysis
@@ -236,7 +232,7 @@ jobs:
236232
name: Setup PHP
237233
uses: shivammathur/setup-php@v2
238234
with:
239-
php-version: 8.3
235+
php-version: ${{ matrix.php || '8.3' }}
240236
ini-file: development
241237

242238
-

scripts/refresh-e2e.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ function outputYaml(array $items): void
8282
$result[] = [
8383
'repo' => 'phpstan/phpstan-src',
8484
'cdaArgs' => '--config=build/composer-dependency-analyser.php',
85+
'php' => '8.4',
8586
];
8687
$result[] = [
8788
'repo' => 'qossmic/deptrac-src',
@@ -109,6 +110,8 @@ function outputYaml(array $items): void
109110
|| $item['repo'] === 'symplify/phpstan-rules'
110111
|| $item['repo'] === 'contao-thememanager/core'
111112
|| $item['repo'] === 'oveleon/contao-recommendation-bundle'
113+
|| $item['repo'] === 'numero2/contao-marketing-suite' // since 1.8.2 (shadow symfony/contracts via trigger_deprecation)
114+
|| $item['repo'] === 'teamneusta/pimcore-testing-framework' // since 1.8.2 (shadow symfony/contracts via trigger_deprecation)
112115
) {
113116
unset($result[$index]); // failing builds
114117
}

src/Analyser.php

Lines changed: 6 additions & 5 deletions
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

Lines changed: 9 additions & 9 deletions
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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ public function provideVariants(): iterable
7272
'PHPUnit\Framework\Error' => [14],
7373
'LogicException' => [15, 20],
7474
],
75+
SymbolKind::FUNCTION => [
76+
'user_defined_function' => [38],
77+
],
78+
],
79+
[
80+
'user_defined_function' => SymbolKind::FUNCTION,
7581
],
7682
];
7783

@@ -113,7 +119,6 @@ public function provideVariants(): iterable
113119
];
114120

115121
yield 'global namespace' => [
116-
117122
__DIR__ . '/data/not-autoloaded/used-symbols/global-namespace.php',
118123
[
119124
SymbolKind::CLASSLIKE => [
@@ -122,8 +127,12 @@ public function provideVariants(): iterable
122127
],
123128
SymbolKind::FUNCTION => [
124129
'PHPUnit\Framework\assertSame' => [7],
130+
'user_defined_function' => [12],
125131
],
126132
],
133+
[
134+
strtolower('user_defined_function') => SymbolKind::FUNCTION,
135+
],
127136
];
128137

129138
yield 'curly braces' => [

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

Lines changed: 1 addition & 1 deletion
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
}

tests/data/not-autoloaded/used-symbols/various-usages.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class Foo {
3535

3636
public function foo(Error $error): void // not PHPUnit\Framework\Error anymore
3737
{
38-
38+
user_defined_function();
3939
}
4040

4141
}

0 commit comments

Comments
 (0)