Skip to content

Commit dc4c51e

Browse files
committed
Implementation notes
1 parent 4d900a5 commit dc4c51e

File tree

1 file changed

+126
-0
lines changed

1 file changed

+126
-0
lines changed

src/TextUI/Configuration/README.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
SourceMapper Implementation Notes
2+
=================================
3+
4+
Currently the `<directory>` element in `<include>` and `<exclude>` has the
5+
attributes `prefix` and `suffix` and we also have `<file>` which specifies a
6+
single file.
7+
8+
Our primary goal is to ensure that the source mapper needn't iterate over all
9+
included files recursively whenever the source map is required (for example
10+
when a deprecation is encountered PHPUnit needs to know if the deprecation was
11+
issued from source code within the project's responsiblity - i.e. source that
12+
is mapped). We can determine if a file is within the included source by
13+
converting the glob-patterns in the `<directory>` element to regexes.
14+
15+
This is more complicated than it could be as the current matching logic
16+
depends on PHP's `glob` function - the implementation of which is not
17+
consistent across platforms and which has a number of rarely-used operators
18+
which while not common, would present a B/C break if they were removed.
19+
20+
How it works currently
21+
----------------------
22+
23+
```php
24+
# src/TextUI/Configuration/SourceMapper.php
25+
foreach ($includeDirectories as $path => [$prefixes, $suffixes]) {
26+
foreach ((new FileIteratorFacade)->getFilesAsArray($path, $suffixes, $prefixes) as $file) {
27+
```
28+
29+
```php
30+
# vendor/phpunit/php-file-iterator/src/Facade.php
31+
public function getFilesAsArray(array|string $paths, array|string $suffixes = '', array|string $prefixes = '', array $exclude = []): array
32+
{
33+
$iterator = (new Factory)->getFileIterator($paths, $suffixes, $prefixes, $exclude);
34+
```
35+
36+
```php
37+
# vendor/phpunit/php-file-iterator/src/Factory.php
38+
```
39+
40+
The Factory:
41+
42+
- resolves (expands) any wildcards to concrete **file** paths
43+
- iterates over the paths, ignoring any directories (by checking `is_dir`)[1]
44+
- create a new PHPUnit `Iterator` passing a recursive iterator iterator
45+
directory iterator... (the iterator that iterates over the directories) that
46+
**follows symlinks and skips dots**.
47+
48+
The Iterator:
49+
50+
- Filters out paths if `realpath` returns `false`.
51+
- Filters out hidden paths at the root of the resovled path.
52+
- Filters out concretee paths based on the `basename` and any given suffix or
53+
prefix.
54+
55+
Features
56+
--------
57+
58+
- Symlinks:
59+
- Skips hidden files
60+
61+
Assumptions (to verify)
62+
-----------------------
63+
64+
The meaning of `<directory prefix="Test" suffix=".phpt">tests/</directory>`
65+
means "all files in the `tests` directory whose (base)names begin with `Test` and
66+
end with `.phpt`, for example `tests/Foobar/Barfoo/TestBar.phpt` would be a
67+
match.
68+
69+
While `<file>tests/Bar/Foo.php</file>` would be a literal reference to a
70+
single file.
71+
72+
Option 1: Simplify
73+
------------------
74+
75+
Instead of having `<file>` and `<directory>` elements we can simplify them to
76+
a single element that has no attributes:
77+
78+
```xml
79+
<include>
80+
<pattern>tests/**/Test*.php</pattern>
81+
<pattern>tests/Bar/Foo.php</pattern>
82+
</include>
83+
```
84+
85+
Would be equivalent to:
86+
87+
```xml
88+
<include>
89+
<directory prefix="Test" suffix=".php">tests/</directory>
90+
<file>tests/Bar/Foo.php</file>
91+
</include>
92+
```
93+
94+
Option 2: Preserve
95+
------------------
96+
97+
In this case we preserve the existing API (but accept that the glob
98+
implementation has changed, though it will work in 99% of cases the behavior
99+
will change vs. the current implementation).
100+
101+
```xml
102+
<directory prefix="Test" suffix=".php">tests/</directory>
103+
```
104+
105+
Would be: `tests/**/Test*.php`
106+
107+
```xml
108+
<directory>tests/</directory>
109+
```
110+
111+
Would be: `tests/**/*`
112+
113+
```xml
114+
<directory>tests</directory>
115+
```
116+
117+
Would be: `tests/**/*`
118+
119+
```xml
120+
<directory>tests/**/Command/*.php</directory>
121+
```
122+
123+
Is _probably_ a user mistake and would translate to: `tests/**/Command/*.php/`
124+
(they'd probably intended `<directory suffix=".php">tests/**/Command`).
125+
126+

0 commit comments

Comments
 (0)