Completed
Push — master ( 52755b...6c4366 )
by smiley
02:13
created
vendor/phpunit/phpunit/tests/Regression/GitHub/1351/Issue1351Test.php 1 patch
Indentation   +39 added lines, -39 removed lines patch added patch discarded remove patch
@@ -3,48 +3,48 @@
 block discarded – undo
3 3
 
4 4
 class Issue1351Test extends TestCase
5 5
 {
6
-    protected $instance;
6
+	protected $instance;
7 7
 
8
-    /**
9
-     * @runInSeparateProcess
10
-     */
11
-    public function testFailurePre()
12
-    {
13
-        $this->instance = new ChildProcessClass1351();
14
-        $this->assertFalse(true, 'Expected failure.');
15
-    }
8
+	/**
9
+	 * @runInSeparateProcess
10
+	 */
11
+	public function testFailurePre()
12
+	{
13
+		$this->instance = new ChildProcessClass1351();
14
+		$this->assertFalse(true, 'Expected failure.');
15
+	}
16 16
 
17
-    public function testFailurePost()
18
-    {
19
-        $this->assertNull($this->instance);
20
-        $this->assertFalse(class_exists(ChildProcessClass1351::class, false), 'ChildProcessClass1351 is not loaded.');
21
-    }
17
+	public function testFailurePost()
18
+	{
19
+		$this->assertNull($this->instance);
20
+		$this->assertFalse(class_exists(ChildProcessClass1351::class, false), 'ChildProcessClass1351 is not loaded.');
21
+	}
22 22
 
23
-    /**
24
-     * @runInSeparateProcess
25
-     */
26
-    public function testExceptionPre()
27
-    {
28
-        $this->instance = new ChildProcessClass1351();
29
-        try {
30
-            throw new LogicException('Expected exception.');
31
-        } catch (LogicException $e) {
32
-            throw new RuntimeException('Expected rethrown exception.', 0, $e);
33
-        }
34
-    }
23
+	/**
24
+	 * @runInSeparateProcess
25
+	 */
26
+	public function testExceptionPre()
27
+	{
28
+		$this->instance = new ChildProcessClass1351();
29
+		try {
30
+			throw new LogicException('Expected exception.');
31
+		} catch (LogicException $e) {
32
+			throw new RuntimeException('Expected rethrown exception.', 0, $e);
33
+		}
34
+	}
35 35
 
36
-    public function testExceptionPost()
37
-    {
38
-        $this->assertNull($this->instance);
39
-        $this->assertFalse(class_exists(ChildProcessClass1351::class, false), 'ChildProcessClass1351 is not loaded.');
40
-    }
36
+	public function testExceptionPost()
37
+	{
38
+		$this->assertNull($this->instance);
39
+		$this->assertFalse(class_exists(ChildProcessClass1351::class, false), 'ChildProcessClass1351 is not loaded.');
40
+	}
41 41
 
42
-    public function testPhpCoreLanguageException()
43
-    {
44
-        // User-space code cannot instantiate a PDOException with a string code,
45
-        // so trigger a real one.
46
-        $connection = new PDO('sqlite::memory:');
47
-        $connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
48
-        $connection->query("DELETE FROM php_wtf WHERE exception_code = 'STRING'");
49
-    }
42
+	public function testPhpCoreLanguageException()
43
+	{
44
+		// User-space code cannot instantiate a PDOException with a string code,
45
+		// so trigger a real one.
46
+		$connection = new PDO('sqlite::memory:');
47
+		$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
48
+		$connection->query("DELETE FROM php_wtf WHERE exception_code = 'STRING'");
49
+	}
50 50
 }
Please login to merge, or discard this patch.
vendor/phpunit/phpunit/tests/Regression/Trac/1021/Issue1021Test.php 1 patch
Indentation   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -3,24 +3,24 @@
 block discarded – undo
3 3
 
4 4
 class Issue1021Test extends TestCase
5 5
 {
6
-    /**
7
-     * @dataProvider provider
8
-     */
9
-    public function testSomething($data)
10
-    {
11
-        $this->assertTrue($data);
12
-    }
6
+	/**
7
+	 * @dataProvider provider
8
+	 */
9
+	public function testSomething($data)
10
+	{
11
+		$this->assertTrue($data);
12
+	}
13 13
 
14
-    /**
15
-     * @depends testSomething
16
-     */
17
-    public function testSomethingElse()
18
-    {
19
-        $this->assertTrue(true);
20
-    }
14
+	/**
15
+	 * @depends testSomething
16
+	 */
17
+	public function testSomethingElse()
18
+	{
19
+		$this->assertTrue(true);
20
+	}
21 21
 
22
-    public function provider()
23
-    {
24
-        return [[true]];
25
-    }
22
+	public function provider()
23
+	{
24
+		return [[true]];
25
+	}
26 26
 }
Please login to merge, or discard this patch.
vendor/phpunit/phpunit/tests/Regression/Trac/523/Issue523Test.php 1 patch
Indentation   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -3,13 +3,13 @@
 block discarded – undo
3 3
 
4 4
 class Issue523Test extends TestCase
5 5
 {
6
-    public function testAttributeEquals()
7
-    {
8
-        $this->assertAttributeEquals('foo', 'field', new Issue523());
9
-    }
6
+	public function testAttributeEquals()
7
+	{
8
+		$this->assertAttributeEquals('foo', 'field', new Issue523());
9
+	}
10 10
 }
11 11
 
12 12
 class Issue523 extends ArrayIterator
13 13
 {
14
-    protected $field = 'foo';
14
+	protected $field = 'foo';
15 15
 }
Please login to merge, or discard this patch.
vendor/phpunit/phpunit/tests/Regression/Trac/578/Issue578Test.php 1 patch
Indentation   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -3,20 +3,20 @@
 block discarded – undo
3 3
 
4 4
 class Issue578Test extends TestCase
5 5
 {
6
-    public function testNoticesDoublePrintStackTrace()
7
-    {
8
-        $this->iniSet('error_reporting', E_ALL | E_NOTICE);
9
-        trigger_error('Stack Trace Test Notice', E_NOTICE);
10
-    }
6
+	public function testNoticesDoublePrintStackTrace()
7
+	{
8
+		$this->iniSet('error_reporting', E_ALL | E_NOTICE);
9
+		trigger_error('Stack Trace Test Notice', E_NOTICE);
10
+	}
11 11
 
12
-    public function testWarningsDoublePrintStackTrace()
13
-    {
14
-        $this->iniSet('error_reporting', E_ALL | E_NOTICE);
15
-        trigger_error('Stack Trace Test Notice', E_WARNING);
16
-    }
12
+	public function testWarningsDoublePrintStackTrace()
13
+	{
14
+		$this->iniSet('error_reporting', E_ALL | E_NOTICE);
15
+		trigger_error('Stack Trace Test Notice', E_WARNING);
16
+	}
17 17
 
18
-    public function testUnexpectedExceptionsPrintsCorrectly()
19
-    {
20
-        throw new Exception('Double printed exception');
21
-    }
18
+	public function testUnexpectedExceptionsPrintsCorrectly()
19
+	{
20
+		throw new Exception('Double printed exception');
21
+	}
22 22
 }
Please login to merge, or discard this patch.
vendor/phpunit/phpunit/tests/Regression/Trac/783/TwoTest.php 1 patch
Indentation   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -6,8 +6,8 @@
 block discarded – undo
6 6
  */
7 7
 class TwoTest extends TestCase
8 8
 {
9
-    public function testSomething()
10
-    {
11
-        $this->assertTrue(true);
12
-    }
9
+	public function testSomething()
10
+	{
11
+		$this->assertTrue(true);
12
+	}
13 13
 }
Please login to merge, or discard this patch.
vendor/phpunit/phpunit/tests/Regression/Trac/783/OneTest.php 1 patch
Indentation   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -6,8 +6,8 @@
 block discarded – undo
6 6
  */
7 7
 class OneTest extends TestCase
8 8
 {
9
-    public function testSomething()
10
-    {
11
-        $this->assertTrue(true);
12
-    }
9
+	public function testSomething()
10
+	{
11
+		$this->assertTrue(true);
12
+	}
13 13
 }
Please login to merge, or discard this patch.
vendor/phpunit/phpunit/tests/Regression/Trac/783/ChildSuite.php 1 patch
Indentation   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -6,12 +6,12 @@
 block discarded – undo
6 6
 
7 7
 class ChildSuite
8 8
 {
9
-    public static function suite()
10
-    {
11
-        $suite = new TestSuite('Child');
12
-        $suite->addTestSuite(OneTest::class);
13
-        $suite->addTestSuite(TwoTest::class);
9
+	public static function suite()
10
+	{
11
+		$suite = new TestSuite('Child');
12
+		$suite->addTestSuite(OneTest::class);
13
+		$suite->addTestSuite(TwoTest::class);
14 14
 
15
-        return $suite;
16
-    }
15
+		return $suite;
16
+	}
17 17
 }
Please login to merge, or discard this patch.
vendor/phpunit/phpunit/tests/Regression/Trac/783/ParentSuite.php 1 patch
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -5,11 +5,11 @@
 block discarded – undo
5 5
 
6 6
 class ParentSuite
7 7
 {
8
-    public static function suite()
9
-    {
10
-        $suite = new TestSuite('Parent');
11
-        $suite->addTest(ChildSuite::suite());
8
+	public static function suite()
9
+	{
10
+		$suite = new TestSuite('Parent');
11
+		$suite->addTest(ChildSuite::suite());
12 12
 
13
-        return $suite;
14
-    }
13
+		return $suite;
14
+	}
15 15
 }
Please login to merge, or discard this patch.
vendor/phpunit/phpunit/src/Util/Test.php 2 patches
Indentation   +1151 added lines, -1151 removed lines patch added patch discarded remove patch
@@ -31,1155 +31,1155 @@
 block discarded – undo
31 31
  */
32 32
 class Test
33 33
 {
34
-    const REGEX_DATA_PROVIDER               = '/@dataProvider\s+([a-zA-Z0-9._:-\\\\x7f-\xff]+)/';
35
-    const REGEX_TEST_WITH                   = '/@testWith\s+/';
36
-    const REGEX_EXPECTED_EXCEPTION          = '(@expectedException\s+([:.\w\\\\x7f-\xff]+)(?:[\t ]+(\S*))?(?:[\t ]+(\S*))?\s*$)m';
37
-    const REGEX_REQUIRES_VERSION            = '/@requires\s+(?P<name>PHP(?:Unit)?)\s+(?P<operator>[<>=!]{0,2})\s*(?P<version>[\d\.-]+(dev|(RC|alpha|beta)[\d\.])?)[ \t]*\r?$/m';
38
-    const REGEX_REQUIRES_VERSION_CONSTRAINT = '/@requires\s+(?P<name>PHP(?:Unit)?)\s+(?P<constraint>[\d\t -.|~^]+)[ \t]*\r?$/m';
39
-    const REGEX_REQUIRES_OS                 = '/@requires\s+(?P<name>OS(?:FAMILY)?)\s+(?P<value>.+?)[ \t]*\r?$/m';
40
-    const REGEX_REQUIRES                    = '/@requires\s+(?P<name>function|extension)\s+(?P<value>([^ ]+?))\s*(?P<operator>[<>=!]{0,2})\s*(?P<version>[\d\.-]+[\d\.]?)?[ \t]*\r?$/m';
41
-
42
-    const UNKNOWN = -1;
43
-    const SMALL   = 0;
44
-    const MEDIUM  = 1;
45
-    const LARGE   = 2;
46
-
47
-    private static $annotationCache = [];
48
-
49
-    private static $hookMethods = [];
50
-
51
-    /**
52
-     * @param \PHPUnit\Framework\Test $test
53
-     * @param bool                    $asString
54
-     *
55
-     * @return mixed
56
-     */
57
-    public static function describe(\PHPUnit\Framework\Test $test, $asString = true)
58
-    {
59
-        if ($asString) {
60
-            if ($test instanceof SelfDescribing) {
61
-                return $test->toString();
62
-            }
63
-
64
-            return \get_class($test);
65
-        }
66
-
67
-        if ($test instanceof TestCase) {
68
-            return [
69
-                \get_class($test), $test->getName()
70
-            ];
71
-        }
72
-
73
-        if ($test instanceof SelfDescribing) {
74
-            return ['', $test->toString()];
75
-        }
76
-
77
-        return ['', \get_class($test)];
78
-    }
79
-
80
-    /**
81
-     * @param string $className
82
-     * @param string $methodName
83
-     *
84
-     * @return array|bool
85
-     *
86
-     * @throws CodeCoverageException
87
-     */
88
-    public static function getLinesToBeCovered($className, $methodName)
89
-    {
90
-        $annotations = self::parseTestMethodAnnotations(
91
-            $className,
92
-            $methodName
93
-        );
94
-
95
-        if (isset($annotations['class']['coversNothing']) || isset($annotations['method']['coversNothing'])) {
96
-            return false;
97
-        }
98
-
99
-        return self::getLinesToBeCoveredOrUsed($className, $methodName, 'covers');
100
-    }
101
-
102
-    /**
103
-     * Returns lines of code specified with the @uses annotation.
104
-     *
105
-     * @param string $className
106
-     * @param string $methodName
107
-     *
108
-     * @return array
109
-     */
110
-    public static function getLinesToBeUsed($className, $methodName)
111
-    {
112
-        return self::getLinesToBeCoveredOrUsed($className, $methodName, 'uses');
113
-    }
114
-
115
-    /**
116
-     * @param string $className
117
-     * @param string $methodName
118
-     * @param string $mode
119
-     *
120
-     * @return array
121
-     *
122
-     * @throws CodeCoverageException
123
-     */
124
-    private static function getLinesToBeCoveredOrUsed($className, $methodName, $mode)
125
-    {
126
-        $annotations = self::parseTestMethodAnnotations(
127
-            $className,
128
-            $methodName
129
-        );
130
-
131
-        $classShortcut = null;
132
-
133
-        if (!empty($annotations['class'][$mode . 'DefaultClass'])) {
134
-            if (\count($annotations['class'][$mode . 'DefaultClass']) > 1) {
135
-                throw new CodeCoverageException(
136
-                    \sprintf(
137
-                        'More than one @%sClass annotation in class or interface "%s".',
138
-                        $mode,
139
-                        $className
140
-                    )
141
-                );
142
-            }
143
-
144
-            $classShortcut = $annotations['class'][$mode . 'DefaultClass'][0];
145
-        }
146
-
147
-        $list = [];
148
-
149
-        if (isset($annotations['class'][$mode])) {
150
-            $list = $annotations['class'][$mode];
151
-        }
152
-
153
-        if (isset($annotations['method'][$mode])) {
154
-            $list = \array_merge($list, $annotations['method'][$mode]);
155
-        }
156
-
157
-        $codeList = [];
158
-
159
-        foreach (\array_unique($list) as $element) {
160
-            if ($classShortcut && \strncmp($element, '::', 2) === 0) {
161
-                $element = $classShortcut . $element;
162
-            }
163
-
164
-            $element = \preg_replace('/[\s()]+$/', '', $element);
165
-            $element = \explode(' ', $element);
166
-            $element = $element[0];
167
-
168
-            $codeList = \array_merge(
169
-                $codeList,
170
-                self::resolveElementToReflectionObjects($element)
171
-            );
172
-        }
173
-
174
-        return self::resolveReflectionObjectsToLines($codeList);
175
-    }
176
-
177
-    /**
178
-     * Returns the requirements for a test.
179
-     *
180
-     * @param string $className
181
-     * @param string $methodName
182
-     *
183
-     * @return array
184
-     */
185
-    public static function getRequirements($className, $methodName)
186
-    {
187
-        $reflector  = new ReflectionClass($className);
188
-        $docComment = $reflector->getDocComment();
189
-        $reflector  = new ReflectionMethod($className, $methodName);
190
-        $docComment .= "\n" . $reflector->getDocComment();
191
-        $requires = [];
192
-
193
-        if ($count = \preg_match_all(self::REGEX_REQUIRES_OS, $docComment, $matches)) {
194
-            foreach (\range(0, $count - 1) as $i) {
195
-                $requires[$matches['name'][$i]] = $matches['value'][$i];
196
-            }
197
-        }
198
-
199
-        if ($count = \preg_match_all(self::REGEX_REQUIRES_VERSION, $docComment, $matches)) {
200
-            foreach (\range(0, $count - 1) as $i) {
201
-                $requires[$matches['name'][$i]] = [
202
-                    'version'  => $matches['version'][$i],
203
-                    'operator' => $matches['operator'][$i]
204
-                ];
205
-            }
206
-        }
207
-        if ($count = \preg_match_all(self::REGEX_REQUIRES_VERSION_CONSTRAINT, $docComment, $matches)) {
208
-            foreach (\range(0, $count - 1) as $i) {
209
-                if (!empty($requires[$matches['name'][$i]])) {
210
-                    continue;
211
-                }
212
-
213
-                try {
214
-                    $versionConstraintParser = new VersionConstraintParser;
215
-
216
-                    $requires[$matches['name'][$i] . '_constraint'] = [
217
-                        'constraint' => $versionConstraintParser->parse(\trim($matches['constraint'][$i]))
218
-                    ];
219
-                } catch (\PharIo\Version\Exception $e) {
220
-                    throw new Warning($e->getMessage(), $e->getCode(), $e);
221
-                }
222
-            }
223
-        }
224
-
225
-        if ($count = \preg_match_all(self::REGEX_REQUIRES, $docComment, $matches)) {
226
-            foreach (\range(0, $count - 1) as $i) {
227
-                $name = $matches['name'][$i] . 's';
228
-
229
-                if (!isset($requires[$name])) {
230
-                    $requires[$name] = [];
231
-                }
232
-
233
-                $requires[$name][] = $matches['value'][$i];
234
-
235
-                if (empty($matches['version'][$i]) || $name != 'extensions') {
236
-                    continue;
237
-                }
238
-
239
-                $requires['extension_versions'][$matches['value'][$i]] = [
240
-                    'version'  => $matches['version'][$i],
241
-                    'operator' => $matches['operator'][$i]
242
-                ];
243
-            }
244
-        }
245
-
246
-        return $requires;
247
-    }
248
-
249
-    /**
250
-     * Returns the missing requirements for a test.
251
-     *
252
-     * @param string $className
253
-     * @param string $methodName
254
-     *
255
-     * @return string[]
256
-     */
257
-    public static function getMissingRequirements($className, $methodName)
258
-    {
259
-        $required = static::getRequirements($className, $methodName);
260
-        $missing  = [];
261
-
262
-        if (!empty($required['PHP'])) {
263
-            $operator = empty($required['PHP']['operator']) ? '>=' : $required['PHP']['operator'];
264
-
265
-            if (!\version_compare(PHP_VERSION, $required['PHP']['version'], $operator)) {
266
-                $missing[] = \sprintf('PHP %s %s is required.', $operator, $required['PHP']['version']);
267
-            }
268
-        } elseif (!empty($required['PHP_constraint'])) {
269
-            $version = new \PharIo\Version\Version(self::sanitizeVersionNumber(PHP_VERSION));
270
-
271
-            if (!$required['PHP_constraint']['constraint']->complies($version)) {
272
-                $missing[] = \sprintf(
273
-                    'PHP version does not match the required constraint %s.',
274
-                    $required['PHP_constraint']['constraint']->asString()
275
-                );
276
-            }
277
-        }
278
-
279
-        if (!empty($required['PHPUnit'])) {
280
-            $phpunitVersion = Version::id();
281
-
282
-            $operator = empty($required['PHPUnit']['operator']) ? '>=' : $required['PHPUnit']['operator'];
283
-
284
-            if (!\version_compare($phpunitVersion, $required['PHPUnit']['version'], $operator)) {
285
-                $missing[] = \sprintf('PHPUnit %s %s is required.', $operator, $required['PHPUnit']['version']);
286
-            }
287
-        } elseif (!empty($required['PHPUnit_constraint'])) {
288
-            $phpunitVersion = new \PharIo\Version\Version(self::sanitizeVersionNumber(Version::id()));
289
-
290
-            if (!$required['PHPUnit_constraint']['constraint']->complies($phpunitVersion)) {
291
-                $missing[] = \sprintf(
292
-                    'PHPUnit version does not match the required constraint %s.',
293
-                    $required['PHPUnit_constraint']['constraint']->asString()
294
-                );
295
-            }
296
-        }
297
-
298
-        if (!empty($required['OSFAMILY']) && $required['OSFAMILY'] !== (new OperatingSystem())->getFamily()) {
299
-            $missing[] = \sprintf('Operating system %s is required.', $required['OSFAMILY']);
300
-        }
301
-
302
-        if (!empty($required['OS'])) {
303
-            $requiredOsPattern = \sprintf('/%s/i', \addcslashes($required['OS'], '/'));
304
-            if (!\preg_match($requiredOsPattern, PHP_OS)) {
305
-                $missing[] = \sprintf('Operating system matching %s is required.', $requiredOsPattern);
306
-            }
307
-        }
308
-
309
-        if (!empty($required['functions'])) {
310
-            foreach ($required['functions'] as $function) {
311
-                $pieces = \explode('::', $function);
312
-
313
-                if (2 === \count($pieces) && \method_exists($pieces[0], $pieces[1])) {
314
-                    continue;
315
-                }
316
-
317
-                if (\function_exists($function)) {
318
-                    continue;
319
-                }
320
-
321
-                $missing[] = \sprintf('Function %s is required.', $function);
322
-            }
323
-        }
324
-
325
-        if (!empty($required['extensions'])) {
326
-            foreach ($required['extensions'] as $extension) {
327
-                if (isset($required['extension_versions'][$extension])) {
328
-                    continue;
329
-                }
330
-
331
-                if (!\extension_loaded($extension)) {
332
-                    $missing[] = \sprintf('Extension %s is required.', $extension);
333
-                }
334
-            }
335
-        }
336
-
337
-        if (!empty($required['extension_versions'])) {
338
-            foreach ($required['extension_versions'] as $extension => $required) {
339
-                $actualVersion = \phpversion($extension);
340
-
341
-                $operator = empty($required['operator']) ? '>=' : $required['operator'];
342
-
343
-                if (false === $actualVersion || !\version_compare($actualVersion, $required['version'], $operator)) {
344
-                    $missing[] = \sprintf('Extension %s %s %s is required.', $extension, $operator, $required['version']);
345
-                }
346
-            }
347
-        }
348
-
349
-        return $missing;
350
-    }
351
-
352
-    /**
353
-     * Returns the expected exception for a test.
354
-     *
355
-     * @param string $className
356
-     * @param string $methodName
357
-     *
358
-     * @return array|false
359
-     */
360
-    public static function getExpectedException($className, $methodName)
361
-    {
362
-        $reflector  = new ReflectionMethod($className, $methodName);
363
-        $docComment = $reflector->getDocComment();
364
-        $docComment = \substr($docComment, 3, -2);
365
-
366
-        if (\preg_match(self::REGEX_EXPECTED_EXCEPTION, $docComment, $matches)) {
367
-            $annotations = self::parseTestMethodAnnotations(
368
-                $className,
369
-                $methodName
370
-            );
371
-
372
-            $class         = $matches[1];
373
-            $code          = null;
374
-            $message       = '';
375
-            $messageRegExp = '';
376
-
377
-            if (isset($matches[2])) {
378
-                $message = \trim($matches[2]);
379
-            } elseif (isset($annotations['method']['expectedExceptionMessage'])) {
380
-                $message = self::parseAnnotationContent(
381
-                    $annotations['method']['expectedExceptionMessage'][0]
382
-                );
383
-            }
384
-
385
-            if (isset($annotations['method']['expectedExceptionMessageRegExp'])) {
386
-                $messageRegExp = self::parseAnnotationContent(
387
-                    $annotations['method']['expectedExceptionMessageRegExp'][0]
388
-                );
389
-            }
390
-
391
-            if (isset($matches[3])) {
392
-                $code = $matches[3];
393
-            } elseif (isset($annotations['method']['expectedExceptionCode'])) {
394
-                $code = self::parseAnnotationContent(
395
-                    $annotations['method']['expectedExceptionCode'][0]
396
-                );
397
-            }
398
-
399
-            if (\is_numeric($code)) {
400
-                $code = (int) $code;
401
-            } elseif (\is_string($code) && \defined($code)) {
402
-                $code = (int) \constant($code);
403
-            }
404
-
405
-            return [
406
-                'class' => $class, 'code' => $code, 'message' => $message, 'message_regex' => $messageRegExp
407
-            ];
408
-        }
409
-
410
-        return false;
411
-    }
412
-
413
-    /**
414
-     * Parse annotation content to use constant/class constant values
415
-     *
416
-     * Constants are specified using a starting '@'. For example: @ClassName::CONST_NAME
417
-     *
418
-     * If the constant is not found the string is used as is to ensure maximum BC.
419
-     *
420
-     * @param string $message
421
-     *
422
-     * @return string
423
-     */
424
-    private static function parseAnnotationContent($message)
425
-    {
426
-        if ((\strpos($message, '::') !== false && \count(\explode('::', $message)) == 2) && \defined($message)) {
427
-            $message = \constant($message);
428
-        }
429
-
430
-        return $message;
431
-    }
432
-
433
-    /**
434
-     * Returns the provided data for a method.
435
-     *
436
-     * @param string $className
437
-     * @param string $methodName
438
-     *
439
-     * @return array When a data provider is specified and exists
440
-     *               null  When no data provider is specified
441
-     *
442
-     * @throws Exception
443
-     */
444
-    public static function getProvidedData($className, $methodName)
445
-    {
446
-        $reflector  = new ReflectionMethod($className, $methodName);
447
-        $docComment = $reflector->getDocComment();
448
-
449
-        $data = self::getDataFromDataProviderAnnotation($docComment, $className, $methodName);
450
-
451
-        if ($data === null) {
452
-            $data = self::getDataFromTestWithAnnotation($docComment);
453
-        }
454
-
455
-        if (\is_array($data) && empty($data)) {
456
-            throw new SkippedTestError;
457
-        }
458
-
459
-        if ($data !== null) {
460
-            foreach ($data as $key => $value) {
461
-                if (!\is_array($value)) {
462
-                    throw new Exception(
463
-                        \sprintf(
464
-                            'Data set %s is invalid.',
465
-                            \is_int($key) ? '#' . $key : '"' . $key . '"'
466
-                        )
467
-                    );
468
-                }
469
-            }
470
-        }
471
-
472
-        return $data;
473
-    }
474
-
475
-    /**
476
-     * Returns the provided data for a method.
477
-     *
478
-     * @param string $docComment
479
-     * @param string $className
480
-     * @param string $methodName
481
-     *
482
-     * @return array|Iterator when a data provider is specified and exists
483
-     *                        null           when no data provider is specified
484
-     *
485
-     * @throws Exception
486
-     */
487
-    private static function getDataFromDataProviderAnnotation($docComment, $className, $methodName)
488
-    {
489
-        if (\preg_match_all(self::REGEX_DATA_PROVIDER, $docComment, $matches)) {
490
-            $result = [];
491
-
492
-            foreach ($matches[1] as $match) {
493
-                $dataProviderMethodNameNamespace = \explode('\\', $match);
494
-                $leaf                            = \explode('::', \array_pop($dataProviderMethodNameNamespace));
495
-                $dataProviderMethodName          = \array_pop($leaf);
496
-
497
-                if (!empty($dataProviderMethodNameNamespace)) {
498
-                    $dataProviderMethodNameNamespace = \implode('\\', $dataProviderMethodNameNamespace) . '\\';
499
-                } else {
500
-                    $dataProviderMethodNameNamespace = '';
501
-                }
502
-
503
-                if (!empty($leaf)) {
504
-                    $dataProviderClassName = $dataProviderMethodNameNamespace . \array_pop($leaf);
505
-                } else {
506
-                    $dataProviderClassName = $className;
507
-                }
508
-
509
-                $dataProviderClass  = new ReflectionClass($dataProviderClassName);
510
-                $dataProviderMethod = $dataProviderClass->getMethod(
511
-                    $dataProviderMethodName
512
-                );
513
-
514
-                if ($dataProviderMethod->isStatic()) {
515
-                    $object = null;
516
-                } else {
517
-                    $object = $dataProviderClass->newInstance();
518
-                }
519
-
520
-                if ($dataProviderMethod->getNumberOfParameters() == 0) {
521
-                    $data = $dataProviderMethod->invoke($object);
522
-                } else {
523
-                    $data = $dataProviderMethod->invoke($object, $methodName);
524
-                }
525
-
526
-                if ($data instanceof Traversable) {
527
-                    $data = \iterator_to_array($data, false);
528
-                }
529
-
530
-                if (\is_array($data)) {
531
-                    $result = \array_merge($result, $data);
532
-                }
533
-            }
534
-
535
-            return $result;
536
-        }
537
-    }
538
-
539
-    /**
540
-     * @param string $docComment full docComment string
541
-     *
542
-     * @return array|null array when @testWith annotation is defined,
543
-     *                    null when @testWith annotation is omitted
544
-     *
545
-     * @throws Exception when @testWith annotation is defined but cannot be parsed
546
-     */
547
-    public static function getDataFromTestWithAnnotation($docComment)
548
-    {
549
-        $docComment = self::cleanUpMultiLineAnnotation($docComment);
550
-
551
-        if (\preg_match(self::REGEX_TEST_WITH, $docComment, $matches, PREG_OFFSET_CAPTURE)) {
552
-            $offset            = \strlen($matches[0][0]) + $matches[0][1];
553
-            $annotationContent = \substr($docComment, $offset);
554
-            $data              = [];
555
-
556
-            foreach (\explode("\n", $annotationContent) as $candidateRow) {
557
-                $candidateRow = \trim($candidateRow);
558
-
559
-                if ($candidateRow[0] !== '[') {
560
-                    break;
561
-                }
562
-
563
-                $dataSet = \json_decode($candidateRow, true);
564
-
565
-                if (\json_last_error() != JSON_ERROR_NONE) {
566
-                    throw new Exception(
567
-                        'The dataset for the @testWith annotation cannot be parsed: ' . \json_last_error_msg()
568
-                    );
569
-                }
570
-
571
-                $data[] = $dataSet;
572
-            }
573
-
574
-            if (!$data) {
575
-                throw new Exception('The dataset for the @testWith annotation cannot be parsed.');
576
-            }
577
-
578
-            return $data;
579
-        }
580
-    }
581
-
582
-    private static function cleanUpMultiLineAnnotation($docComment)
583
-    {
584
-        //removing initial '   * ' for docComment
585
-        $docComment = \str_replace("\r\n", "\n", $docComment);
586
-        $docComment = \preg_replace('/' . '\n' . '\s*' . '\*' . '\s?' . '/', "\n", $docComment);
587
-        $docComment = \substr($docComment, 0, -1);
588
-        $docComment = \rtrim($docComment, "\n");
589
-
590
-        return $docComment;
591
-    }
592
-
593
-    /**
594
-     * @param string $className
595
-     * @param string $methodName
596
-     *
597
-     * @return array
598
-     *
599
-     * @throws ReflectionException
600
-     */
601
-    public static function parseTestMethodAnnotations($className, $methodName = '')
602
-    {
603
-        if (!isset(self::$annotationCache[$className])) {
604
-            $class       = new ReflectionClass($className);
605
-            $traits      = $class->getTraits();
606
-            $annotations = [];
607
-
608
-            foreach ($traits as $trait) {
609
-                $annotations = \array_merge(
610
-                    $annotations,
611
-                    self::parseAnnotations($trait->getDocComment())
612
-                );
613
-            }
614
-
615
-            self::$annotationCache[$className] = \array_merge(
616
-                $annotations,
617
-                self::parseAnnotations($class->getDocComment())
618
-            );
619
-        }
620
-
621
-        if (!empty($methodName) && !isset(self::$annotationCache[$className . '::' . $methodName])) {
622
-            try {
623
-                $method      = new ReflectionMethod($className, $methodName);
624
-                $annotations = self::parseAnnotations($method->getDocComment());
625
-            } catch (ReflectionException $e) {
626
-                $annotations = [];
627
-            }
628
-
629
-            self::$annotationCache[$className . '::' . $methodName] = $annotations;
630
-        }
631
-
632
-        return [
633
-            'class'  => self::$annotationCache[$className],
634
-            'method' => !empty($methodName) ? self::$annotationCache[$className . '::' . $methodName] : []
635
-        ];
636
-    }
637
-
638
-    /**
639
-     * @param string $className
640
-     * @param string $methodName
641
-     *
642
-     * @return array
643
-     */
644
-    public static function getInlineAnnotations($className, $methodName)
645
-    {
646
-        $method      = new ReflectionMethod($className, $methodName);
647
-        $code        = \file($method->getFileName());
648
-        $lineNumber  = $method->getStartLine();
649
-        $startLine   = $method->getStartLine() - 1;
650
-        $endLine     = $method->getEndLine() - 1;
651
-        $methodLines = \array_slice($code, $startLine, $endLine - $startLine + 1);
652
-        $annotations = [];
653
-
654
-        foreach ($methodLines as $line) {
655
-            if (\preg_match('#/\*\*?\s*@(?P<name>[A-Za-z_-]+)(?:[ \t]+(?P<value>.*?))?[ \t]*\r?\*/$#m', $line, $matches)) {
656
-                $annotations[\strtolower($matches['name'])] = [
657
-                    'line'  => $lineNumber,
658
-                    'value' => $matches['value']
659
-                ];
660
-            }
661
-
662
-            $lineNumber++;
663
-        }
664
-
665
-        return $annotations;
666
-    }
667
-
668
-    /**
669
-     * @param string $docblock
670
-     *
671
-     * @return array
672
-     */
673
-    private static function parseAnnotations($docblock)
674
-    {
675
-        $annotations = [];
676
-        // Strip away the docblock header and footer to ease parsing of one line annotations
677
-        $docblock = \substr($docblock, 3, -2);
678
-
679
-        if (\preg_match_all('/@(?P<name>[A-Za-z_-]+)(?:[ \t]+(?P<value>.*?))?[ \t]*\r?$/m', $docblock, $matches)) {
680
-            $numMatches = \count($matches[0]);
681
-
682
-            for ($i = 0; $i < $numMatches; ++$i) {
683
-                $annotations[$matches['name'][$i]][] = (string) $matches['value'][$i];
684
-            }
685
-        }
686
-
687
-        return $annotations;
688
-    }
689
-
690
-    /**
691
-     * Returns the backup settings for a test.
692
-     *
693
-     * @param string $className
694
-     * @param string $methodName
695
-     *
696
-     * @return array<string, bool|null>
697
-     */
698
-    public static function getBackupSettings($className, $methodName)
699
-    {
700
-        return [
701
-            'backupGlobals' => self::getBooleanAnnotationSetting(
702
-                $className,
703
-                $methodName,
704
-                'backupGlobals'
705
-            ),
706
-            'backupStaticAttributes' => self::getBooleanAnnotationSetting(
707
-                $className,
708
-                $methodName,
709
-                'backupStaticAttributes'
710
-            )
711
-        ];
712
-    }
713
-
714
-    /**
715
-     * Returns the dependencies for a test class or method.
716
-     *
717
-     * @param string $className
718
-     * @param string $methodName
719
-     *
720
-     * @return array
721
-     */
722
-    public static function getDependencies($className, $methodName)
723
-    {
724
-        $annotations = self::parseTestMethodAnnotations(
725
-            $className,
726
-            $methodName
727
-        );
728
-
729
-        $dependencies = [];
730
-
731
-        if (isset($annotations['class']['depends'])) {
732
-            $dependencies = $annotations['class']['depends'];
733
-        }
734
-
735
-        if (isset($annotations['method']['depends'])) {
736
-            $dependencies = \array_merge(
737
-                $dependencies,
738
-                $annotations['method']['depends']
739
-            );
740
-        }
741
-
742
-        return \array_unique($dependencies);
743
-    }
744
-
745
-    /**
746
-     * Returns the error handler settings for a test.
747
-     *
748
-     * @param string $className
749
-     * @param string $methodName
750
-     *
751
-     * @return ?bool
752
-     */
753
-    public static function getErrorHandlerSettings($className, $methodName)
754
-    {
755
-        return self::getBooleanAnnotationSetting(
756
-            $className,
757
-            $methodName,
758
-            'errorHandler'
759
-        );
760
-    }
761
-
762
-    /**
763
-     * Returns the groups for a test class or method.
764
-     *
765
-     * @param string $className
766
-     * @param string $methodName
767
-     *
768
-     * @return array
769
-     */
770
-    public static function getGroups($className, $methodName = '')
771
-    {
772
-        $annotations = self::parseTestMethodAnnotations(
773
-            $className,
774
-            $methodName
775
-        );
776
-
777
-        $groups = [];
778
-
779
-        if (isset($annotations['method']['author'])) {
780
-            $groups = $annotations['method']['author'];
781
-        } elseif (isset($annotations['class']['author'])) {
782
-            $groups = $annotations['class']['author'];
783
-        }
784
-
785
-        if (isset($annotations['class']['group'])) {
786
-            $groups = \array_merge($groups, $annotations['class']['group']);
787
-        }
788
-
789
-        if (isset($annotations['method']['group'])) {
790
-            $groups = \array_merge($groups, $annotations['method']['group']);
791
-        }
792
-
793
-        if (isset($annotations['class']['ticket'])) {
794
-            $groups = \array_merge($groups, $annotations['class']['ticket']);
795
-        }
796
-
797
-        if (isset($annotations['method']['ticket'])) {
798
-            $groups = \array_merge($groups, $annotations['method']['ticket']);
799
-        }
800
-
801
-        foreach (['method', 'class'] as $element) {
802
-            foreach (['small', 'medium', 'large'] as $size) {
803
-                if (isset($annotations[$element][$size])) {
804
-                    $groups[] = $size;
805
-
806
-                    break 2;
807
-                }
808
-            }
809
-        }
810
-
811
-        return \array_unique($groups);
812
-    }
813
-
814
-    /**
815
-     * Returns the size of the test.
816
-     *
817
-     * @param string $className
818
-     * @param string $methodName
819
-     *
820
-     * @return int
821
-     */
822
-    public static function getSize($className, $methodName)
823
-    {
824
-        $groups = \array_flip(self::getGroups($className, $methodName));
825
-        $class  = new ReflectionClass($className);
826
-
827
-        if (isset($groups['large']) ||
828
-            (\class_exists('PHPUnit\DbUnit\TestCase', false) && $class->isSubclassOf('PHPUnit\DbUnit\TestCase'))) {
829
-            return self::LARGE;
830
-        }
831
-
832
-        if (isset($groups['medium'])) {
833
-            return self::MEDIUM;
834
-        }
835
-
836
-        if (isset($groups['small'])) {
837
-            return self::SMALL;
838
-        }
839
-
840
-        return self::UNKNOWN;
841
-    }
842
-
843
-    /**
844
-     * Returns the process isolation settings for a test.
845
-     *
846
-     * @param string $className
847
-     * @param string $methodName
848
-     *
849
-     * @return bool
850
-     */
851
-    public static function getProcessIsolationSettings($className, $methodName)
852
-    {
853
-        $annotations = self::parseTestMethodAnnotations(
854
-            $className,
855
-            $methodName
856
-        );
857
-
858
-        return isset($annotations['class']['runTestsInSeparateProcesses']) || isset($annotations['method']['runInSeparateProcess']);
859
-    }
860
-
861
-    public static function getClassProcessIsolationSettings($className, $methodName)
862
-    {
863
-        $annotations = self::parseTestMethodAnnotations(
864
-            $className,
865
-            $methodName
866
-        );
867
-
868
-        return isset($annotations['class']['runClassInSeparateProcess']);
869
-    }
870
-
871
-    /**
872
-     * Returns the preserve global state settings for a test.
873
-     *
874
-     * @param string $className
875
-     * @param string $methodName
876
-     *
877
-     * @return ?bool
878
-     */
879
-    public static function getPreserveGlobalStateSettings($className, $methodName)
880
-    {
881
-        return self::getBooleanAnnotationSetting(
882
-            $className,
883
-            $methodName,
884
-            'preserveGlobalState'
885
-        );
886
-    }
887
-
888
-    /**
889
-     * @param string $className
890
-     *
891
-     * @return array
892
-     */
893
-    public static function getHookMethods($className)
894
-    {
895
-        if (!\class_exists($className, false)) {
896
-            return self::emptyHookMethodsArray();
897
-        }
898
-
899
-        if (!isset(self::$hookMethods[$className])) {
900
-            self::$hookMethods[$className] = self::emptyHookMethodsArray();
901
-
902
-            try {
903
-                $class = new ReflectionClass($className);
904
-
905
-                foreach ($class->getMethods() as $method) {
906
-                    if (self::isBeforeClassMethod($method)) {
907
-                        \array_unshift(
908
-                            self::$hookMethods[$className]['beforeClass'],
909
-                            $method->getName()
910
-                        );
911
-                    }
912
-
913
-                    if (self::isBeforeMethod($method)) {
914
-                        \array_unshift(
915
-                            self::$hookMethods[$className]['before'],
916
-                            $method->getName()
917
-                        );
918
-                    }
919
-
920
-                    if (self::isAfterMethod($method)) {
921
-                        self::$hookMethods[$className]['after'][] = $method->getName();
922
-                    }
923
-
924
-                    if (self::isAfterClassMethod($method)) {
925
-                        self::$hookMethods[$className]['afterClass'][] = $method->getName();
926
-                    }
927
-                }
928
-            } catch (ReflectionException $e) {
929
-            }
930
-        }
931
-
932
-        return self::$hookMethods[$className];
933
-    }
934
-
935
-    /**
936
-     * @return array
937
-     */
938
-    private static function emptyHookMethodsArray()
939
-    {
940
-        return [
941
-            'beforeClass' => ['setUpBeforeClass'],
942
-            'before'      => ['setUp'],
943
-            'after'       => ['tearDown'],
944
-            'afterClass'  => ['tearDownAfterClass']
945
-        ];
946
-    }
947
-
948
-    /**
949
-     * @param string $className
950
-     * @param string $methodName
951
-     * @param string $settingName
952
-     *
953
-     * @return ?bool
954
-     */
955
-    private static function getBooleanAnnotationSetting($className, $methodName, $settingName)
956
-    {
957
-        $annotations = self::parseTestMethodAnnotations(
958
-            $className,
959
-            $methodName
960
-        );
961
-
962
-        if (isset($annotations['class'][$settingName])) {
963
-            if ($annotations['class'][$settingName][0] == 'enabled') {
964
-                return true;
965
-            }
966
-
967
-            if ($annotations['class'][$settingName][0] == 'disabled') {
968
-                return false;
969
-            }
970
-        }
971
-
972
-        if (isset($annotations['method'][$settingName])) {
973
-            if ($annotations['method'][$settingName][0] == 'enabled') {
974
-                return true;
975
-            }
976
-
977
-            if ($annotations['method'][$settingName][0] == 'disabled') {
978
-                return false;
979
-            }
980
-        }
981
-    }
982
-
983
-    /**
984
-     * @param string $element
985
-     *
986
-     * @return array
987
-     *
988
-     * @throws InvalidCoversTargetException
989
-     */
990
-    private static function resolveElementToReflectionObjects($element)
991
-    {
992
-        $codeToCoverList = [];
993
-
994
-        if (\strpos($element, '\\') !== false && \function_exists($element)) {
995
-            $codeToCoverList[] = new ReflectionFunction($element);
996
-        } elseif (\strpos($element, '::') !== false) {
997
-            list($className, $methodName) = \explode('::', $element);
998
-
999
-            if (isset($methodName[0]) && $methodName[0] == '<') {
1000
-                $classes = [$className];
1001
-
1002
-                foreach ($classes as $className) {
1003
-                    if (!\class_exists($className) &&
1004
-                        !\interface_exists($className) &&
1005
-                        !\trait_exists($className)) {
1006
-                        throw new InvalidCoversTargetException(
1007
-                            \sprintf(
1008
-                                'Trying to @cover or @use not existing class or ' .
1009
-                                'interface "%s".',
1010
-                                $className
1011
-                            )
1012
-                        );
1013
-                    }
1014
-
1015
-                    $class   = new ReflectionClass($className);
1016
-                    $methods = $class->getMethods();
1017
-                    $inverse = isset($methodName[1]) && $methodName[1] == '!';
1018
-
1019
-                    if (\strpos($methodName, 'protected')) {
1020
-                        $visibility = 'isProtected';
1021
-                    } elseif (\strpos($methodName, 'private')) {
1022
-                        $visibility = 'isPrivate';
1023
-                    } elseif (\strpos($methodName, 'public')) {
1024
-                        $visibility = 'isPublic';
1025
-                    }
1026
-
1027
-                    foreach ($methods as $method) {
1028
-                        if ($inverse && !$method->$visibility()) {
1029
-                            $codeToCoverList[] = $method;
1030
-                        } elseif (!$inverse && $method->$visibility()) {
1031
-                            $codeToCoverList[] = $method;
1032
-                        }
1033
-                    }
1034
-                }
1035
-            } else {
1036
-                $classes = [$className];
1037
-
1038
-                foreach ($classes as $className) {
1039
-                    if ($className == '' && \function_exists($methodName)) {
1040
-                        $codeToCoverList[] = new ReflectionFunction(
1041
-                            $methodName
1042
-                        );
1043
-                    } else {
1044
-                        if (!((\class_exists($className) || \interface_exists($className) || \trait_exists($className)) &&
1045
-                            \method_exists($className, $methodName))) {
1046
-                            throw new InvalidCoversTargetException(
1047
-                                \sprintf(
1048
-                                    'Trying to @cover or @use not existing method "%s::%s".',
1049
-                                    $className,
1050
-                                    $methodName
1051
-                                )
1052
-                            );
1053
-                        }
1054
-
1055
-                        $codeToCoverList[] = new ReflectionMethod(
1056
-                            $className,
1057
-                            $methodName
1058
-                        );
1059
-                    }
1060
-                }
1061
-            }
1062
-        } else {
1063
-            $extended = false;
1064
-
1065
-            if (\strpos($element, '<extended>') !== false) {
1066
-                $element  = \str_replace('<extended>', '', $element);
1067
-                $extended = true;
1068
-            }
1069
-
1070
-            $classes = [$element];
1071
-
1072
-            if ($extended) {
1073
-                $classes = \array_merge(
1074
-                    $classes,
1075
-                    \class_implements($element),
1076
-                    \class_parents($element)
1077
-                );
1078
-            }
1079
-
1080
-            foreach ($classes as $className) {
1081
-                if (!\class_exists($className) &&
1082
-                    !\interface_exists($className) &&
1083
-                    !\trait_exists($className)) {
1084
-                    throw new InvalidCoversTargetException(
1085
-                        \sprintf(
1086
-                            'Trying to @cover or @use not existing class or ' .
1087
-                            'interface "%s".',
1088
-                            $className
1089
-                        )
1090
-                    );
1091
-                }
1092
-
1093
-                $codeToCoverList[] = new ReflectionClass($className);
1094
-            }
1095
-        }
1096
-
1097
-        return $codeToCoverList;
1098
-    }
1099
-
1100
-    /**
1101
-     * @param array $reflectors
1102
-     *
1103
-     * @return array
1104
-     */
1105
-    private static function resolveReflectionObjectsToLines(array $reflectors)
1106
-    {
1107
-        $result = [];
1108
-
1109
-        foreach ($reflectors as $reflector) {
1110
-            $filename = $reflector->getFileName();
1111
-
1112
-            if (!isset($result[$filename])) {
1113
-                $result[$filename] = [];
1114
-            }
1115
-
1116
-            $result[$filename] = \array_merge(
1117
-                $result[$filename],
1118
-                \range($reflector->getStartLine(), $reflector->getEndLine())
1119
-            );
1120
-        }
1121
-
1122
-        foreach ($result as $filename => $lineNumbers) {
1123
-            $result[$filename] = \array_keys(\array_flip($lineNumbers));
1124
-        }
1125
-
1126
-        return $result;
1127
-    }
1128
-
1129
-    /**
1130
-     * @param ReflectionMethod $method
1131
-     *
1132
-     * @return bool
1133
-     */
1134
-    private static function isBeforeClassMethod(ReflectionMethod $method)
1135
-    {
1136
-        return $method->isStatic() && \strpos($method->getDocComment(), '@beforeClass') !== false;
1137
-    }
1138
-
1139
-    /**
1140
-     * @param ReflectionMethod $method
1141
-     *
1142
-     * @return bool
1143
-     */
1144
-    private static function isBeforeMethod(ReflectionMethod $method)
1145
-    {
1146
-        return \preg_match('/@before\b/', $method->getDocComment()) > 0;
1147
-    }
1148
-
1149
-    /**
1150
-     * @param ReflectionMethod $method
1151
-     *
1152
-     * @return bool
1153
-     */
1154
-    private static function isAfterClassMethod(ReflectionMethod $method)
1155
-    {
1156
-        return $method->isStatic() && \strpos($method->getDocComment(), '@afterClass') !== false;
1157
-    }
1158
-
1159
-    /**
1160
-     * @param ReflectionMethod $method
1161
-     *
1162
-     * @return bool
1163
-     */
1164
-    private static function isAfterMethod(ReflectionMethod $method)
1165
-    {
1166
-        return \preg_match('/@after\b/', $method->getDocComment()) > 0;
1167
-    }
1168
-
1169
-    /**
1170
-     * Trims any extensions from version string that follows after
1171
-     * the <major>.<minor>[.<patch>] format
1172
-     *
1173
-     * @param $version (Optional)
1174
-     *
1175
-     * @return mixed
1176
-     */
1177
-    private static function sanitizeVersionNumber($version)
1178
-    {
1179
-        return \preg_replace(
1180
-            '/^(\d+\.\d+(?:.\d+)?).*$/',
1181
-            '$1',
1182
-            $version
1183
-        );
1184
-    }
34
+	const REGEX_DATA_PROVIDER               = '/@dataProvider\s+([a-zA-Z0-9._:-\\\\x7f-\xff]+)/';
35
+	const REGEX_TEST_WITH                   = '/@testWith\s+/';
36
+	const REGEX_EXPECTED_EXCEPTION          = '(@expectedException\s+([:.\w\\\\x7f-\xff]+)(?:[\t ]+(\S*))?(?:[\t ]+(\S*))?\s*$)m';
37
+	const REGEX_REQUIRES_VERSION            = '/@requires\s+(?P<name>PHP(?:Unit)?)\s+(?P<operator>[<>=!]{0,2})\s*(?P<version>[\d\.-]+(dev|(RC|alpha|beta)[\d\.])?)[ \t]*\r?$/m';
38
+	const REGEX_REQUIRES_VERSION_CONSTRAINT = '/@requires\s+(?P<name>PHP(?:Unit)?)\s+(?P<constraint>[\d\t -.|~^]+)[ \t]*\r?$/m';
39
+	const REGEX_REQUIRES_OS                 = '/@requires\s+(?P<name>OS(?:FAMILY)?)\s+(?P<value>.+?)[ \t]*\r?$/m';
40
+	const REGEX_REQUIRES                    = '/@requires\s+(?P<name>function|extension)\s+(?P<value>([^ ]+?))\s*(?P<operator>[<>=!]{0,2})\s*(?P<version>[\d\.-]+[\d\.]?)?[ \t]*\r?$/m';
41
+
42
+	const UNKNOWN = -1;
43
+	const SMALL   = 0;
44
+	const MEDIUM  = 1;
45
+	const LARGE   = 2;
46
+
47
+	private static $annotationCache = [];
48
+
49
+	private static $hookMethods = [];
50
+
51
+	/**
52
+	 * @param \PHPUnit\Framework\Test $test
53
+	 * @param bool                    $asString
54
+	 *
55
+	 * @return mixed
56
+	 */
57
+	public static function describe(\PHPUnit\Framework\Test $test, $asString = true)
58
+	{
59
+		if ($asString) {
60
+			if ($test instanceof SelfDescribing) {
61
+				return $test->toString();
62
+			}
63
+
64
+			return \get_class($test);
65
+		}
66
+
67
+		if ($test instanceof TestCase) {
68
+			return [
69
+				\get_class($test), $test->getName()
70
+			];
71
+		}
72
+
73
+		if ($test instanceof SelfDescribing) {
74
+			return ['', $test->toString()];
75
+		}
76
+
77
+		return ['', \get_class($test)];
78
+	}
79
+
80
+	/**
81
+	 * @param string $className
82
+	 * @param string $methodName
83
+	 *
84
+	 * @return array|bool
85
+	 *
86
+	 * @throws CodeCoverageException
87
+	 */
88
+	public static function getLinesToBeCovered($className, $methodName)
89
+	{
90
+		$annotations = self::parseTestMethodAnnotations(
91
+			$className,
92
+			$methodName
93
+		);
94
+
95
+		if (isset($annotations['class']['coversNothing']) || isset($annotations['method']['coversNothing'])) {
96
+			return false;
97
+		}
98
+
99
+		return self::getLinesToBeCoveredOrUsed($className, $methodName, 'covers');
100
+	}
101
+
102
+	/**
103
+	 * Returns lines of code specified with the @uses annotation.
104
+	 *
105
+	 * @param string $className
106
+	 * @param string $methodName
107
+	 *
108
+	 * @return array
109
+	 */
110
+	public static function getLinesToBeUsed($className, $methodName)
111
+	{
112
+		return self::getLinesToBeCoveredOrUsed($className, $methodName, 'uses');
113
+	}
114
+
115
+	/**
116
+	 * @param string $className
117
+	 * @param string $methodName
118
+	 * @param string $mode
119
+	 *
120
+	 * @return array
121
+	 *
122
+	 * @throws CodeCoverageException
123
+	 */
124
+	private static function getLinesToBeCoveredOrUsed($className, $methodName, $mode)
125
+	{
126
+		$annotations = self::parseTestMethodAnnotations(
127
+			$className,
128
+			$methodName
129
+		);
130
+
131
+		$classShortcut = null;
132
+
133
+		if (!empty($annotations['class'][$mode . 'DefaultClass'])) {
134
+			if (\count($annotations['class'][$mode . 'DefaultClass']) > 1) {
135
+				throw new CodeCoverageException(
136
+					\sprintf(
137
+						'More than one @%sClass annotation in class or interface "%s".',
138
+						$mode,
139
+						$className
140
+					)
141
+				);
142
+			}
143
+
144
+			$classShortcut = $annotations['class'][$mode . 'DefaultClass'][0];
145
+		}
146
+
147
+		$list = [];
148
+
149
+		if (isset($annotations['class'][$mode])) {
150
+			$list = $annotations['class'][$mode];
151
+		}
152
+
153
+		if (isset($annotations['method'][$mode])) {
154
+			$list = \array_merge($list, $annotations['method'][$mode]);
155
+		}
156
+
157
+		$codeList = [];
158
+
159
+		foreach (\array_unique($list) as $element) {
160
+			if ($classShortcut && \strncmp($element, '::', 2) === 0) {
161
+				$element = $classShortcut . $element;
162
+			}
163
+
164
+			$element = \preg_replace('/[\s()]+$/', '', $element);
165
+			$element = \explode(' ', $element);
166
+			$element = $element[0];
167
+
168
+			$codeList = \array_merge(
169
+				$codeList,
170
+				self::resolveElementToReflectionObjects($element)
171
+			);
172
+		}
173
+
174
+		return self::resolveReflectionObjectsToLines($codeList);
175
+	}
176
+
177
+	/**
178
+	 * Returns the requirements for a test.
179
+	 *
180
+	 * @param string $className
181
+	 * @param string $methodName
182
+	 *
183
+	 * @return array
184
+	 */
185
+	public static function getRequirements($className, $methodName)
186
+	{
187
+		$reflector  = new ReflectionClass($className);
188
+		$docComment = $reflector->getDocComment();
189
+		$reflector  = new ReflectionMethod($className, $methodName);
190
+		$docComment .= "\n" . $reflector->getDocComment();
191
+		$requires = [];
192
+
193
+		if ($count = \preg_match_all(self::REGEX_REQUIRES_OS, $docComment, $matches)) {
194
+			foreach (\range(0, $count - 1) as $i) {
195
+				$requires[$matches['name'][$i]] = $matches['value'][$i];
196
+			}
197
+		}
198
+
199
+		if ($count = \preg_match_all(self::REGEX_REQUIRES_VERSION, $docComment, $matches)) {
200
+			foreach (\range(0, $count - 1) as $i) {
201
+				$requires[$matches['name'][$i]] = [
202
+					'version'  => $matches['version'][$i],
203
+					'operator' => $matches['operator'][$i]
204
+				];
205
+			}
206
+		}
207
+		if ($count = \preg_match_all(self::REGEX_REQUIRES_VERSION_CONSTRAINT, $docComment, $matches)) {
208
+			foreach (\range(0, $count - 1) as $i) {
209
+				if (!empty($requires[$matches['name'][$i]])) {
210
+					continue;
211
+				}
212
+
213
+				try {
214
+					$versionConstraintParser = new VersionConstraintParser;
215
+
216
+					$requires[$matches['name'][$i] . '_constraint'] = [
217
+						'constraint' => $versionConstraintParser->parse(\trim($matches['constraint'][$i]))
218
+					];
219
+				} catch (\PharIo\Version\Exception $e) {
220
+					throw new Warning($e->getMessage(), $e->getCode(), $e);
221
+				}
222
+			}
223
+		}
224
+
225
+		if ($count = \preg_match_all(self::REGEX_REQUIRES, $docComment, $matches)) {
226
+			foreach (\range(0, $count - 1) as $i) {
227
+				$name = $matches['name'][$i] . 's';
228
+
229
+				if (!isset($requires[$name])) {
230
+					$requires[$name] = [];
231
+				}
232
+
233
+				$requires[$name][] = $matches['value'][$i];
234
+
235
+				if (empty($matches['version'][$i]) || $name != 'extensions') {
236
+					continue;
237
+				}
238
+
239
+				$requires['extension_versions'][$matches['value'][$i]] = [
240
+					'version'  => $matches['version'][$i],
241
+					'operator' => $matches['operator'][$i]
242
+				];
243
+			}
244
+		}
245
+
246
+		return $requires;
247
+	}
248
+
249
+	/**
250
+	 * Returns the missing requirements for a test.
251
+	 *
252
+	 * @param string $className
253
+	 * @param string $methodName
254
+	 *
255
+	 * @return string[]
256
+	 */
257
+	public static function getMissingRequirements($className, $methodName)
258
+	{
259
+		$required = static::getRequirements($className, $methodName);
260
+		$missing  = [];
261
+
262
+		if (!empty($required['PHP'])) {
263
+			$operator = empty($required['PHP']['operator']) ? '>=' : $required['PHP']['operator'];
264
+
265
+			if (!\version_compare(PHP_VERSION, $required['PHP']['version'], $operator)) {
266
+				$missing[] = \sprintf('PHP %s %s is required.', $operator, $required['PHP']['version']);
267
+			}
268
+		} elseif (!empty($required['PHP_constraint'])) {
269
+			$version = new \PharIo\Version\Version(self::sanitizeVersionNumber(PHP_VERSION));
270
+
271
+			if (!$required['PHP_constraint']['constraint']->complies($version)) {
272
+				$missing[] = \sprintf(
273
+					'PHP version does not match the required constraint %s.',
274
+					$required['PHP_constraint']['constraint']->asString()
275
+				);
276
+			}
277
+		}
278
+
279
+		if (!empty($required['PHPUnit'])) {
280
+			$phpunitVersion = Version::id();
281
+
282
+			$operator = empty($required['PHPUnit']['operator']) ? '>=' : $required['PHPUnit']['operator'];
283
+
284
+			if (!\version_compare($phpunitVersion, $required['PHPUnit']['version'], $operator)) {
285
+				$missing[] = \sprintf('PHPUnit %s %s is required.', $operator, $required['PHPUnit']['version']);
286
+			}
287
+		} elseif (!empty($required['PHPUnit_constraint'])) {
288
+			$phpunitVersion = new \PharIo\Version\Version(self::sanitizeVersionNumber(Version::id()));
289
+
290
+			if (!$required['PHPUnit_constraint']['constraint']->complies($phpunitVersion)) {
291
+				$missing[] = \sprintf(
292
+					'PHPUnit version does not match the required constraint %s.',
293
+					$required['PHPUnit_constraint']['constraint']->asString()
294
+				);
295
+			}
296
+		}
297
+
298
+		if (!empty($required['OSFAMILY']) && $required['OSFAMILY'] !== (new OperatingSystem())->getFamily()) {
299
+			$missing[] = \sprintf('Operating system %s is required.', $required['OSFAMILY']);
300
+		}
301
+
302
+		if (!empty($required['OS'])) {
303
+			$requiredOsPattern = \sprintf('/%s/i', \addcslashes($required['OS'], '/'));
304
+			if (!\preg_match($requiredOsPattern, PHP_OS)) {
305
+				$missing[] = \sprintf('Operating system matching %s is required.', $requiredOsPattern);
306
+			}
307
+		}
308
+
309
+		if (!empty($required['functions'])) {
310
+			foreach ($required['functions'] as $function) {
311
+				$pieces = \explode('::', $function);
312
+
313
+				if (2 === \count($pieces) && \method_exists($pieces[0], $pieces[1])) {
314
+					continue;
315
+				}
316
+
317
+				if (\function_exists($function)) {
318
+					continue;
319
+				}
320
+
321
+				$missing[] = \sprintf('Function %s is required.', $function);
322
+			}
323
+		}
324
+
325
+		if (!empty($required['extensions'])) {
326
+			foreach ($required['extensions'] as $extension) {
327
+				if (isset($required['extension_versions'][$extension])) {
328
+					continue;
329
+				}
330
+
331
+				if (!\extension_loaded($extension)) {
332
+					$missing[] = \sprintf('Extension %s is required.', $extension);
333
+				}
334
+			}
335
+		}
336
+
337
+		if (!empty($required['extension_versions'])) {
338
+			foreach ($required['extension_versions'] as $extension => $required) {
339
+				$actualVersion = \phpversion($extension);
340
+
341
+				$operator = empty($required['operator']) ? '>=' : $required['operator'];
342
+
343
+				if (false === $actualVersion || !\version_compare($actualVersion, $required['version'], $operator)) {
344
+					$missing[] = \sprintf('Extension %s %s %s is required.', $extension, $operator, $required['version']);
345
+				}
346
+			}
347
+		}
348
+
349
+		return $missing;
350
+	}
351
+
352
+	/**
353
+	 * Returns the expected exception for a test.
354
+	 *
355
+	 * @param string $className
356
+	 * @param string $methodName
357
+	 *
358
+	 * @return array|false
359
+	 */
360
+	public static function getExpectedException($className, $methodName)
361
+	{
362
+		$reflector  = new ReflectionMethod($className, $methodName);
363
+		$docComment = $reflector->getDocComment();
364
+		$docComment = \substr($docComment, 3, -2);
365
+
366
+		if (\preg_match(self::REGEX_EXPECTED_EXCEPTION, $docComment, $matches)) {
367
+			$annotations = self::parseTestMethodAnnotations(
368
+				$className,
369
+				$methodName
370
+			);
371
+
372
+			$class         = $matches[1];
373
+			$code          = null;
374
+			$message       = '';
375
+			$messageRegExp = '';
376
+
377
+			if (isset($matches[2])) {
378
+				$message = \trim($matches[2]);
379
+			} elseif (isset($annotations['method']['expectedExceptionMessage'])) {
380
+				$message = self::parseAnnotationContent(
381
+					$annotations['method']['expectedExceptionMessage'][0]
382
+				);
383
+			}
384
+
385
+			if (isset($annotations['method']['expectedExceptionMessageRegExp'])) {
386
+				$messageRegExp = self::parseAnnotationContent(
387
+					$annotations['method']['expectedExceptionMessageRegExp'][0]
388
+				);
389
+			}
390
+
391
+			if (isset($matches[3])) {
392
+				$code = $matches[3];
393
+			} elseif (isset($annotations['method']['expectedExceptionCode'])) {
394
+				$code = self::parseAnnotationContent(
395
+					$annotations['method']['expectedExceptionCode'][0]
396
+				);
397
+			}
398
+
399
+			if (\is_numeric($code)) {
400
+				$code = (int) $code;
401
+			} elseif (\is_string($code) && \defined($code)) {
402
+				$code = (int) \constant($code);
403
+			}
404
+
405
+			return [
406
+				'class' => $class, 'code' => $code, 'message' => $message, 'message_regex' => $messageRegExp
407
+			];
408
+		}
409
+
410
+		return false;
411
+	}
412
+
413
+	/**
414
+	 * Parse annotation content to use constant/class constant values
415
+	 *
416
+	 * Constants are specified using a starting '@'. For example: @ClassName::CONST_NAME
417
+	 *
418
+	 * If the constant is not found the string is used as is to ensure maximum BC.
419
+	 *
420
+	 * @param string $message
421
+	 *
422
+	 * @return string
423
+	 */
424
+	private static function parseAnnotationContent($message)
425
+	{
426
+		if ((\strpos($message, '::') !== false && \count(\explode('::', $message)) == 2) && \defined($message)) {
427
+			$message = \constant($message);
428
+		}
429
+
430
+		return $message;
431
+	}
432
+
433
+	/**
434
+	 * Returns the provided data for a method.
435
+	 *
436
+	 * @param string $className
437
+	 * @param string $methodName
438
+	 *
439
+	 * @return array When a data provider is specified and exists
440
+	 *               null  When no data provider is specified
441
+	 *
442
+	 * @throws Exception
443
+	 */
444
+	public static function getProvidedData($className, $methodName)
445
+	{
446
+		$reflector  = new ReflectionMethod($className, $methodName);
447
+		$docComment = $reflector->getDocComment();
448
+
449
+		$data = self::getDataFromDataProviderAnnotation($docComment, $className, $methodName);
450
+
451
+		if ($data === null) {
452
+			$data = self::getDataFromTestWithAnnotation($docComment);
453
+		}
454
+
455
+		if (\is_array($data) && empty($data)) {
456
+			throw new SkippedTestError;
457
+		}
458
+
459
+		if ($data !== null) {
460
+			foreach ($data as $key => $value) {
461
+				if (!\is_array($value)) {
462
+					throw new Exception(
463
+						\sprintf(
464
+							'Data set %s is invalid.',
465
+							\is_int($key) ? '#' . $key : '"' . $key . '"'
466
+						)
467
+					);
468
+				}
469
+			}
470
+		}
471
+
472
+		return $data;
473
+	}
474
+
475
+	/**
476
+	 * Returns the provided data for a method.
477
+	 *
478
+	 * @param string $docComment
479
+	 * @param string $className
480
+	 * @param string $methodName
481
+	 *
482
+	 * @return array|Iterator when a data provider is specified and exists
483
+	 *                        null           when no data provider is specified
484
+	 *
485
+	 * @throws Exception
486
+	 */
487
+	private static function getDataFromDataProviderAnnotation($docComment, $className, $methodName)
488
+	{
489
+		if (\preg_match_all(self::REGEX_DATA_PROVIDER, $docComment, $matches)) {
490
+			$result = [];
491
+
492
+			foreach ($matches[1] as $match) {
493
+				$dataProviderMethodNameNamespace = \explode('\\', $match);
494
+				$leaf                            = \explode('::', \array_pop($dataProviderMethodNameNamespace));
495
+				$dataProviderMethodName          = \array_pop($leaf);
496
+
497
+				if (!empty($dataProviderMethodNameNamespace)) {
498
+					$dataProviderMethodNameNamespace = \implode('\\', $dataProviderMethodNameNamespace) . '\\';
499
+				} else {
500
+					$dataProviderMethodNameNamespace = '';
501
+				}
502
+
503
+				if (!empty($leaf)) {
504
+					$dataProviderClassName = $dataProviderMethodNameNamespace . \array_pop($leaf);
505
+				} else {
506
+					$dataProviderClassName = $className;
507
+				}
508
+
509
+				$dataProviderClass  = new ReflectionClass($dataProviderClassName);
510
+				$dataProviderMethod = $dataProviderClass->getMethod(
511
+					$dataProviderMethodName
512
+				);
513
+
514
+				if ($dataProviderMethod->isStatic()) {
515
+					$object = null;
516
+				} else {
517
+					$object = $dataProviderClass->newInstance();
518
+				}
519
+
520
+				if ($dataProviderMethod->getNumberOfParameters() == 0) {
521
+					$data = $dataProviderMethod->invoke($object);
522
+				} else {
523
+					$data = $dataProviderMethod->invoke($object, $methodName);
524
+				}
525
+
526
+				if ($data instanceof Traversable) {
527
+					$data = \iterator_to_array($data, false);
528
+				}
529
+
530
+				if (\is_array($data)) {
531
+					$result = \array_merge($result, $data);
532
+				}
533
+			}
534
+
535
+			return $result;
536
+		}
537
+	}
538
+
539
+	/**
540
+	 * @param string $docComment full docComment string
541
+	 *
542
+	 * @return array|null array when @testWith annotation is defined,
543
+	 *                    null when @testWith annotation is omitted
544
+	 *
545
+	 * @throws Exception when @testWith annotation is defined but cannot be parsed
546
+	 */
547
+	public static function getDataFromTestWithAnnotation($docComment)
548
+	{
549
+		$docComment = self::cleanUpMultiLineAnnotation($docComment);
550
+
551
+		if (\preg_match(self::REGEX_TEST_WITH, $docComment, $matches, PREG_OFFSET_CAPTURE)) {
552
+			$offset            = \strlen($matches[0][0]) + $matches[0][1];
553
+			$annotationContent = \substr($docComment, $offset);
554
+			$data              = [];
555
+
556
+			foreach (\explode("\n", $annotationContent) as $candidateRow) {
557
+				$candidateRow = \trim($candidateRow);
558
+
559
+				if ($candidateRow[0] !== '[') {
560
+					break;
561
+				}
562
+
563
+				$dataSet = \json_decode($candidateRow, true);
564
+
565
+				if (\json_last_error() != JSON_ERROR_NONE) {
566
+					throw new Exception(
567
+						'The dataset for the @testWith annotation cannot be parsed: ' . \json_last_error_msg()
568
+					);
569
+				}
570
+
571
+				$data[] = $dataSet;
572
+			}
573
+
574
+			if (!$data) {
575
+				throw new Exception('The dataset for the @testWith annotation cannot be parsed.');
576
+			}
577
+
578
+			return $data;
579
+		}
580
+	}
581
+
582
+	private static function cleanUpMultiLineAnnotation($docComment)
583
+	{
584
+		//removing initial '   * ' for docComment
585
+		$docComment = \str_replace("\r\n", "\n", $docComment);
586
+		$docComment = \preg_replace('/' . '\n' . '\s*' . '\*' . '\s?' . '/', "\n", $docComment);
587
+		$docComment = \substr($docComment, 0, -1);
588
+		$docComment = \rtrim($docComment, "\n");
589
+
590
+		return $docComment;
591
+	}
592
+
593
+	/**
594
+	 * @param string $className
595
+	 * @param string $methodName
596
+	 *
597
+	 * @return array
598
+	 *
599
+	 * @throws ReflectionException
600
+	 */
601
+	public static function parseTestMethodAnnotations($className, $methodName = '')
602
+	{
603
+		if (!isset(self::$annotationCache[$className])) {
604
+			$class       = new ReflectionClass($className);
605
+			$traits      = $class->getTraits();
606
+			$annotations = [];
607
+
608
+			foreach ($traits as $trait) {
609
+				$annotations = \array_merge(
610
+					$annotations,
611
+					self::parseAnnotations($trait->getDocComment())
612
+				);
613
+			}
614
+
615
+			self::$annotationCache[$className] = \array_merge(
616
+				$annotations,
617
+				self::parseAnnotations($class->getDocComment())
618
+			);
619
+		}
620
+
621
+		if (!empty($methodName) && !isset(self::$annotationCache[$className . '::' . $methodName])) {
622
+			try {
623
+				$method      = new ReflectionMethod($className, $methodName);
624
+				$annotations = self::parseAnnotations($method->getDocComment());
625
+			} catch (ReflectionException $e) {
626
+				$annotations = [];
627
+			}
628
+
629
+			self::$annotationCache[$className . '::' . $methodName] = $annotations;
630
+		}
631
+
632
+		return [
633
+			'class'  => self::$annotationCache[$className],
634
+			'method' => !empty($methodName) ? self::$annotationCache[$className . '::' . $methodName] : []
635
+		];
636
+	}
637
+
638
+	/**
639
+	 * @param string $className
640
+	 * @param string $methodName
641
+	 *
642
+	 * @return array
643
+	 */
644
+	public static function getInlineAnnotations($className, $methodName)
645
+	{
646
+		$method      = new ReflectionMethod($className, $methodName);
647
+		$code        = \file($method->getFileName());
648
+		$lineNumber  = $method->getStartLine();
649
+		$startLine   = $method->getStartLine() - 1;
650
+		$endLine     = $method->getEndLine() - 1;
651
+		$methodLines = \array_slice($code, $startLine, $endLine - $startLine + 1);
652
+		$annotations = [];
653
+
654
+		foreach ($methodLines as $line) {
655
+			if (\preg_match('#/\*\*?\s*@(?P<name>[A-Za-z_-]+)(?:[ \t]+(?P<value>.*?))?[ \t]*\r?\*/$#m', $line, $matches)) {
656
+				$annotations[\strtolower($matches['name'])] = [
657
+					'line'  => $lineNumber,
658
+					'value' => $matches['value']
659
+				];
660
+			}
661
+
662
+			$lineNumber++;
663
+		}
664
+
665
+		return $annotations;
666
+	}
667
+
668
+	/**
669
+	 * @param string $docblock
670
+	 *
671
+	 * @return array
672
+	 */
673
+	private static function parseAnnotations($docblock)
674
+	{
675
+		$annotations = [];
676
+		// Strip away the docblock header and footer to ease parsing of one line annotations
677
+		$docblock = \substr($docblock, 3, -2);
678
+
679
+		if (\preg_match_all('/@(?P<name>[A-Za-z_-]+)(?:[ \t]+(?P<value>.*?))?[ \t]*\r?$/m', $docblock, $matches)) {
680
+			$numMatches = \count($matches[0]);
681
+
682
+			for ($i = 0; $i < $numMatches; ++$i) {
683
+				$annotations[$matches['name'][$i]][] = (string) $matches['value'][$i];
684
+			}
685
+		}
686
+
687
+		return $annotations;
688
+	}
689
+
690
+	/**
691
+	 * Returns the backup settings for a test.
692
+	 *
693
+	 * @param string $className
694
+	 * @param string $methodName
695
+	 *
696
+	 * @return array<string, bool|null>
697
+	 */
698
+	public static function getBackupSettings($className, $methodName)
699
+	{
700
+		return [
701
+			'backupGlobals' => self::getBooleanAnnotationSetting(
702
+				$className,
703
+				$methodName,
704
+				'backupGlobals'
705
+			),
706
+			'backupStaticAttributes' => self::getBooleanAnnotationSetting(
707
+				$className,
708
+				$methodName,
709
+				'backupStaticAttributes'
710
+			)
711
+		];
712
+	}
713
+
714
+	/**
715
+	 * Returns the dependencies for a test class or method.
716
+	 *
717
+	 * @param string $className
718
+	 * @param string $methodName
719
+	 *
720
+	 * @return array
721
+	 */
722
+	public static function getDependencies($className, $methodName)
723
+	{
724
+		$annotations = self::parseTestMethodAnnotations(
725
+			$className,
726
+			$methodName
727
+		);
728
+
729
+		$dependencies = [];
730
+
731
+		if (isset($annotations['class']['depends'])) {
732
+			$dependencies = $annotations['class']['depends'];
733
+		}
734
+
735
+		if (isset($annotations['method']['depends'])) {
736
+			$dependencies = \array_merge(
737
+				$dependencies,
738
+				$annotations['method']['depends']
739
+			);
740
+		}
741
+
742
+		return \array_unique($dependencies);
743
+	}
744
+
745
+	/**
746
+	 * Returns the error handler settings for a test.
747
+	 *
748
+	 * @param string $className
749
+	 * @param string $methodName
750
+	 *
751
+	 * @return ?bool
752
+	 */
753
+	public static function getErrorHandlerSettings($className, $methodName)
754
+	{
755
+		return self::getBooleanAnnotationSetting(
756
+			$className,
757
+			$methodName,
758
+			'errorHandler'
759
+		);
760
+	}
761
+
762
+	/**
763
+	 * Returns the groups for a test class or method.
764
+	 *
765
+	 * @param string $className
766
+	 * @param string $methodName
767
+	 *
768
+	 * @return array
769
+	 */
770
+	public static function getGroups($className, $methodName = '')
771
+	{
772
+		$annotations = self::parseTestMethodAnnotations(
773
+			$className,
774
+			$methodName
775
+		);
776
+
777
+		$groups = [];
778
+
779
+		if (isset($annotations['method']['author'])) {
780
+			$groups = $annotations['method']['author'];
781
+		} elseif (isset($annotations['class']['author'])) {
782
+			$groups = $annotations['class']['author'];
783
+		}
784
+
785
+		if (isset($annotations['class']['group'])) {
786
+			$groups = \array_merge($groups, $annotations['class']['group']);
787
+		}
788
+
789
+		if (isset($annotations['method']['group'])) {
790
+			$groups = \array_merge($groups, $annotations['method']['group']);
791
+		}
792
+
793
+		if (isset($annotations['class']['ticket'])) {
794
+			$groups = \array_merge($groups, $annotations['class']['ticket']);
795
+		}
796
+
797
+		if (isset($annotations['method']['ticket'])) {
798
+			$groups = \array_merge($groups, $annotations['method']['ticket']);
799
+		}
800
+
801
+		foreach (['method', 'class'] as $element) {
802
+			foreach (['small', 'medium', 'large'] as $size) {
803
+				if (isset($annotations[$element][$size])) {
804
+					$groups[] = $size;
805
+
806
+					break 2;
807
+				}
808
+			}
809
+		}
810
+
811
+		return \array_unique($groups);
812
+	}
813
+
814
+	/**
815
+	 * Returns the size of the test.
816
+	 *
817
+	 * @param string $className
818
+	 * @param string $methodName
819
+	 *
820
+	 * @return int
821
+	 */
822
+	public static function getSize($className, $methodName)
823
+	{
824
+		$groups = \array_flip(self::getGroups($className, $methodName));
825
+		$class  = new ReflectionClass($className);
826
+
827
+		if (isset($groups['large']) ||
828
+			(\class_exists('PHPUnit\DbUnit\TestCase', false) && $class->isSubclassOf('PHPUnit\DbUnit\TestCase'))) {
829
+			return self::LARGE;
830
+		}
831
+
832
+		if (isset($groups['medium'])) {
833
+			return self::MEDIUM;
834
+		}
835
+
836
+		if (isset($groups['small'])) {
837
+			return self::SMALL;
838
+		}
839
+
840
+		return self::UNKNOWN;
841
+	}
842
+
843
+	/**
844
+	 * Returns the process isolation settings for a test.
845
+	 *
846
+	 * @param string $className
847
+	 * @param string $methodName
848
+	 *
849
+	 * @return bool
850
+	 */
851
+	public static function getProcessIsolationSettings($className, $methodName)
852
+	{
853
+		$annotations = self::parseTestMethodAnnotations(
854
+			$className,
855
+			$methodName
856
+		);
857
+
858
+		return isset($annotations['class']['runTestsInSeparateProcesses']) || isset($annotations['method']['runInSeparateProcess']);
859
+	}
860
+
861
+	public static function getClassProcessIsolationSettings($className, $methodName)
862
+	{
863
+		$annotations = self::parseTestMethodAnnotations(
864
+			$className,
865
+			$methodName
866
+		);
867
+
868
+		return isset($annotations['class']['runClassInSeparateProcess']);
869
+	}
870
+
871
+	/**
872
+	 * Returns the preserve global state settings for a test.
873
+	 *
874
+	 * @param string $className
875
+	 * @param string $methodName
876
+	 *
877
+	 * @return ?bool
878
+	 */
879
+	public static function getPreserveGlobalStateSettings($className, $methodName)
880
+	{
881
+		return self::getBooleanAnnotationSetting(
882
+			$className,
883
+			$methodName,
884
+			'preserveGlobalState'
885
+		);
886
+	}
887
+
888
+	/**
889
+	 * @param string $className
890
+	 *
891
+	 * @return array
892
+	 */
893
+	public static function getHookMethods($className)
894
+	{
895
+		if (!\class_exists($className, false)) {
896
+			return self::emptyHookMethodsArray();
897
+		}
898
+
899
+		if (!isset(self::$hookMethods[$className])) {
900
+			self::$hookMethods[$className] = self::emptyHookMethodsArray();
901
+
902
+			try {
903
+				$class = new ReflectionClass($className);
904
+
905
+				foreach ($class->getMethods() as $method) {
906
+					if (self::isBeforeClassMethod($method)) {
907
+						\array_unshift(
908
+							self::$hookMethods[$className]['beforeClass'],
909
+							$method->getName()
910
+						);
911
+					}
912
+
913
+					if (self::isBeforeMethod($method)) {
914
+						\array_unshift(
915
+							self::$hookMethods[$className]['before'],
916
+							$method->getName()
917
+						);
918
+					}
919
+
920
+					if (self::isAfterMethod($method)) {
921
+						self::$hookMethods[$className]['after'][] = $method->getName();
922
+					}
923
+
924
+					if (self::isAfterClassMethod($method)) {
925
+						self::$hookMethods[$className]['afterClass'][] = $method->getName();
926
+					}
927
+				}
928
+			} catch (ReflectionException $e) {
929
+			}
930
+		}
931
+
932
+		return self::$hookMethods[$className];
933
+	}
934
+
935
+	/**
936
+	 * @return array
937
+	 */
938
+	private static function emptyHookMethodsArray()
939
+	{
940
+		return [
941
+			'beforeClass' => ['setUpBeforeClass'],
942
+			'before'      => ['setUp'],
943
+			'after'       => ['tearDown'],
944
+			'afterClass'  => ['tearDownAfterClass']
945
+		];
946
+	}
947
+
948
+	/**
949
+	 * @param string $className
950
+	 * @param string $methodName
951
+	 * @param string $settingName
952
+	 *
953
+	 * @return ?bool
954
+	 */
955
+	private static function getBooleanAnnotationSetting($className, $methodName, $settingName)
956
+	{
957
+		$annotations = self::parseTestMethodAnnotations(
958
+			$className,
959
+			$methodName
960
+		);
961
+
962
+		if (isset($annotations['class'][$settingName])) {
963
+			if ($annotations['class'][$settingName][0] == 'enabled') {
964
+				return true;
965
+			}
966
+
967
+			if ($annotations['class'][$settingName][0] == 'disabled') {
968
+				return false;
969
+			}
970
+		}
971
+
972
+		if (isset($annotations['method'][$settingName])) {
973
+			if ($annotations['method'][$settingName][0] == 'enabled') {
974
+				return true;
975
+			}
976
+
977
+			if ($annotations['method'][$settingName][0] == 'disabled') {
978
+				return false;
979
+			}
980
+		}
981
+	}
982
+
983
+	/**
984
+	 * @param string $element
985
+	 *
986
+	 * @return array
987
+	 *
988
+	 * @throws InvalidCoversTargetException
989
+	 */
990
+	private static function resolveElementToReflectionObjects($element)
991
+	{
992
+		$codeToCoverList = [];
993
+
994
+		if (\strpos($element, '\\') !== false && \function_exists($element)) {
995
+			$codeToCoverList[] = new ReflectionFunction($element);
996
+		} elseif (\strpos($element, '::') !== false) {
997
+			list($className, $methodName) = \explode('::', $element);
998
+
999
+			if (isset($methodName[0]) && $methodName[0] == '<') {
1000
+				$classes = [$className];
1001
+
1002
+				foreach ($classes as $className) {
1003
+					if (!\class_exists($className) &&
1004
+						!\interface_exists($className) &&
1005
+						!\trait_exists($className)) {
1006
+						throw new InvalidCoversTargetException(
1007
+							\sprintf(
1008
+								'Trying to @cover or @use not existing class or ' .
1009
+								'interface "%s".',
1010
+								$className
1011
+							)
1012
+						);
1013
+					}
1014
+
1015
+					$class   = new ReflectionClass($className);
1016
+					$methods = $class->getMethods();
1017
+					$inverse = isset($methodName[1]) && $methodName[1] == '!';
1018
+
1019
+					if (\strpos($methodName, 'protected')) {
1020
+						$visibility = 'isProtected';
1021
+					} elseif (\strpos($methodName, 'private')) {
1022
+						$visibility = 'isPrivate';
1023
+					} elseif (\strpos($methodName, 'public')) {
1024
+						$visibility = 'isPublic';
1025
+					}
1026
+
1027
+					foreach ($methods as $method) {
1028
+						if ($inverse && !$method->$visibility()) {
1029
+							$codeToCoverList[] = $method;
1030
+						} elseif (!$inverse && $method->$visibility()) {
1031
+							$codeToCoverList[] = $method;
1032
+						}
1033
+					}
1034
+				}
1035
+			} else {
1036
+				$classes = [$className];
1037
+
1038
+				foreach ($classes as $className) {
1039
+					if ($className == '' && \function_exists($methodName)) {
1040
+						$codeToCoverList[] = new ReflectionFunction(
1041
+							$methodName
1042
+						);
1043
+					} else {
1044
+						if (!((\class_exists($className) || \interface_exists($className) || \trait_exists($className)) &&
1045
+							\method_exists($className, $methodName))) {
1046
+							throw new InvalidCoversTargetException(
1047
+								\sprintf(
1048
+									'Trying to @cover or @use not existing method "%s::%s".',
1049
+									$className,
1050
+									$methodName
1051
+								)
1052
+							);
1053
+						}
1054
+
1055
+						$codeToCoverList[] = new ReflectionMethod(
1056
+							$className,
1057
+							$methodName
1058
+						);
1059
+					}
1060
+				}
1061
+			}
1062
+		} else {
1063
+			$extended = false;
1064
+
1065
+			if (\strpos($element, '<extended>') !== false) {
1066
+				$element  = \str_replace('<extended>', '', $element);
1067
+				$extended = true;
1068
+			}
1069
+
1070
+			$classes = [$element];
1071
+
1072
+			if ($extended) {
1073
+				$classes = \array_merge(
1074
+					$classes,
1075
+					\class_implements($element),
1076
+					\class_parents($element)
1077
+				);
1078
+			}
1079
+
1080
+			foreach ($classes as $className) {
1081
+				if (!\class_exists($className) &&
1082
+					!\interface_exists($className) &&
1083
+					!\trait_exists($className)) {
1084
+					throw new InvalidCoversTargetException(
1085
+						\sprintf(
1086
+							'Trying to @cover or @use not existing class or ' .
1087
+							'interface "%s".',
1088
+							$className
1089
+						)
1090
+					);
1091
+				}
1092
+
1093
+				$codeToCoverList[] = new ReflectionClass($className);
1094
+			}
1095
+		}
1096
+
1097
+		return $codeToCoverList;
1098
+	}
1099
+
1100
+	/**
1101
+	 * @param array $reflectors
1102
+	 *
1103
+	 * @return array
1104
+	 */
1105
+	private static function resolveReflectionObjectsToLines(array $reflectors)
1106
+	{
1107
+		$result = [];
1108
+
1109
+		foreach ($reflectors as $reflector) {
1110
+			$filename = $reflector->getFileName();
1111
+
1112
+			if (!isset($result[$filename])) {
1113
+				$result[$filename] = [];
1114
+			}
1115
+
1116
+			$result[$filename] = \array_merge(
1117
+				$result[$filename],
1118
+				\range($reflector->getStartLine(), $reflector->getEndLine())
1119
+			);
1120
+		}
1121
+
1122
+		foreach ($result as $filename => $lineNumbers) {
1123
+			$result[$filename] = \array_keys(\array_flip($lineNumbers));
1124
+		}
1125
+
1126
+		return $result;
1127
+	}
1128
+
1129
+	/**
1130
+	 * @param ReflectionMethod $method
1131
+	 *
1132
+	 * @return bool
1133
+	 */
1134
+	private static function isBeforeClassMethod(ReflectionMethod $method)
1135
+	{
1136
+		return $method->isStatic() && \strpos($method->getDocComment(), '@beforeClass') !== false;
1137
+	}
1138
+
1139
+	/**
1140
+	 * @param ReflectionMethod $method
1141
+	 *
1142
+	 * @return bool
1143
+	 */
1144
+	private static function isBeforeMethod(ReflectionMethod $method)
1145
+	{
1146
+		return \preg_match('/@before\b/', $method->getDocComment()) > 0;
1147
+	}
1148
+
1149
+	/**
1150
+	 * @param ReflectionMethod $method
1151
+	 *
1152
+	 * @return bool
1153
+	 */
1154
+	private static function isAfterClassMethod(ReflectionMethod $method)
1155
+	{
1156
+		return $method->isStatic() && \strpos($method->getDocComment(), '@afterClass') !== false;
1157
+	}
1158
+
1159
+	/**
1160
+	 * @param ReflectionMethod $method
1161
+	 *
1162
+	 * @return bool
1163
+	 */
1164
+	private static function isAfterMethod(ReflectionMethod $method)
1165
+	{
1166
+		return \preg_match('/@after\b/', $method->getDocComment()) > 0;
1167
+	}
1168
+
1169
+	/**
1170
+	 * Trims any extensions from version string that follows after
1171
+	 * the <major>.<minor>[.<patch>] format
1172
+	 *
1173
+	 * @param $version (Optional)
1174
+	 *
1175
+	 * @return mixed
1176
+	 */
1177
+	private static function sanitizeVersionNumber($version)
1178
+	{
1179
+		return \preg_replace(
1180
+			'/^(\d+\.\d+(?:.\d+)?).*$/',
1181
+			'$1',
1182
+			$version
1183
+		);
1184
+	}
1185 1185
 }
Please login to merge, or discard this patch.
Spacing   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -130,8 +130,8 @@  discard block
 block discarded – undo
130 130
 
131 131
         $classShortcut = null;
132 132
 
133
-        if (!empty($annotations['class'][$mode . 'DefaultClass'])) {
134
-            if (\count($annotations['class'][$mode . 'DefaultClass']) > 1) {
133
+        if (!empty($annotations['class'][$mode.'DefaultClass'])) {
134
+            if (\count($annotations['class'][$mode.'DefaultClass']) > 1) {
135 135
                 throw new CodeCoverageException(
136 136
                     \sprintf(
137 137
                         'More than one @%sClass annotation in class or interface "%s".',
@@ -141,7 +141,7 @@  discard block
 block discarded – undo
141 141
                 );
142 142
             }
143 143
 
144
-            $classShortcut = $annotations['class'][$mode . 'DefaultClass'][0];
144
+            $classShortcut = $annotations['class'][$mode.'DefaultClass'][0];
145 145
         }
146 146
 
147 147
         $list = [];
@@ -158,7 +158,7 @@  discard block
 block discarded – undo
158 158
 
159 159
         foreach (\array_unique($list) as $element) {
160 160
             if ($classShortcut && \strncmp($element, '::', 2) === 0) {
161
-                $element = $classShortcut . $element;
161
+                $element = $classShortcut.$element;
162 162
             }
163 163
 
164 164
             $element = \preg_replace('/[\s()]+$/', '', $element);
@@ -187,7 +187,7 @@  discard block
 block discarded – undo
187 187
         $reflector  = new ReflectionClass($className);
188 188
         $docComment = $reflector->getDocComment();
189 189
         $reflector  = new ReflectionMethod($className, $methodName);
190
-        $docComment .= "\n" . $reflector->getDocComment();
190
+        $docComment .= "\n".$reflector->getDocComment();
191 191
         $requires = [];
192 192
 
193 193
         if ($count = \preg_match_all(self::REGEX_REQUIRES_OS, $docComment, $matches)) {
@@ -213,7 +213,7 @@  discard block
 block discarded – undo
213 213
                 try {
214 214
                     $versionConstraintParser = new VersionConstraintParser;
215 215
 
216
-                    $requires[$matches['name'][$i] . '_constraint'] = [
216
+                    $requires[$matches['name'][$i].'_constraint'] = [
217 217
                         'constraint' => $versionConstraintParser->parse(\trim($matches['constraint'][$i]))
218 218
                     ];
219 219
                 } catch (\PharIo\Version\Exception $e) {
@@ -224,7 +224,7 @@  discard block
 block discarded – undo
224 224
 
225 225
         if ($count = \preg_match_all(self::REGEX_REQUIRES, $docComment, $matches)) {
226 226
             foreach (\range(0, $count - 1) as $i) {
227
-                $name = $matches['name'][$i] . 's';
227
+                $name = $matches['name'][$i].'s';
228 228
 
229 229
                 if (!isset($requires[$name])) {
230 230
                     $requires[$name] = [];
@@ -462,7 +462,7 @@  discard block
 block discarded – undo
462 462
                     throw new Exception(
463 463
                         \sprintf(
464 464
                             'Data set %s is invalid.',
465
-                            \is_int($key) ? '#' . $key : '"' . $key . '"'
465
+                            \is_int($key) ? '#'.$key : '"'.$key.'"'
466 466
                         )
467 467
                     );
468 468
                 }
@@ -495,13 +495,13 @@  discard block
 block discarded – undo
495 495
                 $dataProviderMethodName          = \array_pop($leaf);
496 496
 
497 497
                 if (!empty($dataProviderMethodNameNamespace)) {
498
-                    $dataProviderMethodNameNamespace = \implode('\\', $dataProviderMethodNameNamespace) . '\\';
498
+                    $dataProviderMethodNameNamespace = \implode('\\', $dataProviderMethodNameNamespace).'\\';
499 499
                 } else {
500 500
                     $dataProviderMethodNameNamespace = '';
501 501
                 }
502 502
 
503 503
                 if (!empty($leaf)) {
504
-                    $dataProviderClassName = $dataProviderMethodNameNamespace . \array_pop($leaf);
504
+                    $dataProviderClassName = $dataProviderMethodNameNamespace.\array_pop($leaf);
505 505
                 } else {
506 506
                     $dataProviderClassName = $className;
507 507
                 }
@@ -564,7 +564,7 @@  discard block
 block discarded – undo
564 564
 
565 565
                 if (\json_last_error() != JSON_ERROR_NONE) {
566 566
                     throw new Exception(
567
-                        'The dataset for the @testWith annotation cannot be parsed: ' . \json_last_error_msg()
567
+                        'The dataset for the @testWith annotation cannot be parsed: '.\json_last_error_msg()
568 568
                     );
569 569
                 }
570 570
 
@@ -583,7 +583,7 @@  discard block
 block discarded – undo
583 583
     {
584 584
         //removing initial '   * ' for docComment
585 585
         $docComment = \str_replace("\r\n", "\n", $docComment);
586
-        $docComment = \preg_replace('/' . '\n' . '\s*' . '\*' . '\s?' . '/', "\n", $docComment);
586
+        $docComment = \preg_replace('/'.'\n'.'\s*'.'\*'.'\s?'.'/', "\n", $docComment);
587 587
         $docComment = \substr($docComment, 0, -1);
588 588
         $docComment = \rtrim($docComment, "\n");
589 589
 
@@ -618,7 +618,7 @@  discard block
 block discarded – undo
618 618
             );
619 619
         }
620 620
 
621
-        if (!empty($methodName) && !isset(self::$annotationCache[$className . '::' . $methodName])) {
621
+        if (!empty($methodName) && !isset(self::$annotationCache[$className.'::'.$methodName])) {
622 622
             try {
623 623
                 $method      = new ReflectionMethod($className, $methodName);
624 624
                 $annotations = self::parseAnnotations($method->getDocComment());
@@ -626,12 +626,12 @@  discard block
 block discarded – undo
626 626
                 $annotations = [];
627 627
             }
628 628
 
629
-            self::$annotationCache[$className . '::' . $methodName] = $annotations;
629
+            self::$annotationCache[$className.'::'.$methodName] = $annotations;
630 630
         }
631 631
 
632 632
         return [
633 633
             'class'  => self::$annotationCache[$className],
634
-            'method' => !empty($methodName) ? self::$annotationCache[$className . '::' . $methodName] : []
634
+            'method' => !empty($methodName) ? self::$annotationCache[$className.'::'.$methodName] : []
635 635
         ];
636 636
     }
637 637
 
@@ -1005,7 +1005,7 @@  discard block
 block discarded – undo
1005 1005
                         !\trait_exists($className)) {
1006 1006
                         throw new InvalidCoversTargetException(
1007 1007
                             \sprintf(
1008
-                                'Trying to @cover or @use not existing class or ' .
1008
+                                'Trying to @cover or @use not existing class or '.
1009 1009
                                 'interface "%s".',
1010 1010
                                 $className
1011 1011
                             )
@@ -1083,7 +1083,7 @@  discard block
 block discarded – undo
1083 1083
                     !\trait_exists($className)) {
1084 1084
                     throw new InvalidCoversTargetException(
1085 1085
                         \sprintf(
1086
-                            'Trying to @cover or @use not existing class or ' .
1086
+                            'Trying to @cover or @use not existing class or '.
1087 1087
                             'interface "%s".',
1088 1088
                             $className
1089 1089
                         )
Please login to merge, or discard this patch.