Completed
Push — master ( 6a75cd...52cfd5 )
by Joas
25:57
created
lib/private/AppFramework/Utility/ControllerMethodReflector.php 1 patch
Indentation   +133 added lines, -133 removed lines patch added patch discarded remove patch
@@ -14,137 +14,137 @@
 block discarded – undo
14 14
  * Reads and parses annotations from doc comments
15 15
  */
16 16
 class ControllerMethodReflector implements IControllerMethodReflector {
17
-	public $annotations = [];
18
-	private $types = [];
19
-	private $parameters = [];
20
-	private array $ranges = [];
21
-	private int $startLine = 0;
22
-	private string $file = '';
23
-
24
-	/**
25
-	 * @param object $object an object or classname
26
-	 * @param string $method the method which we want to inspect
27
-	 */
28
-	public function reflect($object, string $method) {
29
-		$reflection = new \ReflectionMethod($object, $method);
30
-		$this->startLine = $reflection->getStartLine();
31
-		$this->file = $reflection->getFileName();
32
-
33
-		$docs = $reflection->getDocComment();
34
-
35
-		if ($docs !== false) {
36
-			// extract everything prefixed by @ and first letter uppercase
37
-			preg_match_all('/^\h+\*\h+@(?P<annotation>[A-Z]\w+)((?P<parameter>.*))?$/m', $docs, $matches);
38
-			foreach ($matches['annotation'] as $key => $annotation) {
39
-				$annotation = strtolower($annotation);
40
-				$annotationValue = $matches['parameter'][$key];
41
-				if (str_starts_with($annotationValue, '(') && str_ends_with($annotationValue, ')')) {
42
-					$cutString = substr($annotationValue, 1, -1);
43
-					$cutString = str_replace(' ', '', $cutString);
44
-					$splitArray = explode(',', $cutString);
45
-					foreach ($splitArray as $annotationValues) {
46
-						[$key, $value] = explode('=', $annotationValues);
47
-						$this->annotations[$annotation][$key] = $value;
48
-					}
49
-					continue;
50
-				}
51
-
52
-				$this->annotations[$annotation] = [$annotationValue];
53
-			}
54
-
55
-			// extract type parameter information
56
-			preg_match_all('/@param\h+(?P<type>\w+)\h+\$(?P<var>\w+)/', $docs, $matches);
57
-			$this->types = array_combine($matches['var'], $matches['type']);
58
-			preg_match_all('/@(?:psalm-)?param\h+(\?)?(?P<type>\w+)<(?P<rangeMin>(-?\d+|min)),\h*(?P<rangeMax>(-?\d+|max))>(\|null)?\h+\$(?P<var>\w+)/', $docs, $matches);
59
-			foreach ($matches['var'] as $index => $varName) {
60
-				if ($matches['type'][$index] !== 'int') {
61
-					// only int ranges are possible at the moment
62
-					// @see https://psalm.dev/docs/annotating_code/type_syntax/scalar_types
63
-					continue;
64
-				}
65
-				$this->ranges[$varName] = [
66
-					'min' => $matches['rangeMin'][$index] === 'min' ? PHP_INT_MIN : (int)$matches['rangeMin'][$index],
67
-					'max' => $matches['rangeMax'][$index] === 'max' ? PHP_INT_MAX : (int)$matches['rangeMax'][$index],
68
-				];
69
-			}
70
-		}
71
-
72
-		foreach ($reflection->getParameters() as $param) {
73
-			// extract type information from PHP 7 scalar types and prefer them over phpdoc annotations
74
-			$type = $param->getType();
75
-			if ($type instanceof \ReflectionNamedType) {
76
-				$this->types[$param->getName()] = $type->getName();
77
-			}
78
-
79
-			$default = null;
80
-			if ($param->isOptional()) {
81
-				$default = $param->getDefaultValue();
82
-			}
83
-			$this->parameters[$param->name] = $default;
84
-		}
85
-	}
86
-
87
-	/**
88
-	 * Inspects the PHPDoc parameters for types
89
-	 * @param string $parameter the parameter whose type comments should be
90
-	 *                          parsed
91
-	 * @return string|null type in the type parameters (@param int $something)
92
-	 *                     would return int or null if not existing
93
-	 */
94
-	public function getType(string $parameter) {
95
-		if (array_key_exists($parameter, $this->types)) {
96
-			return $this->types[$parameter];
97
-		}
98
-
99
-		return null;
100
-	}
101
-
102
-	public function getRange(string $parameter): ?array {
103
-		if (array_key_exists($parameter, $this->ranges)) {
104
-			return $this->ranges[$parameter];
105
-		}
106
-
107
-		return null;
108
-	}
109
-
110
-	/**
111
-	 * @return array the arguments of the method with key => default value
112
-	 */
113
-	public function getParameters(): array {
114
-		return $this->parameters;
115
-	}
116
-
117
-	/**
118
-	 * Check if a method contains an annotation
119
-	 * @param string $name the name of the annotation
120
-	 * @return bool true if the annotation is found
121
-	 */
122
-	public function hasAnnotation(string $name): bool {
123
-		$name = strtolower($name);
124
-		return array_key_exists($name, $this->annotations);
125
-	}
126
-
127
-	/**
128
-	 * Get optional annotation parameter by key
129
-	 *
130
-	 * @param string $name the name of the annotation
131
-	 * @param string $key the string of the annotation
132
-	 * @return string
133
-	 */
134
-	public function getAnnotationParameter(string $name, string $key): string {
135
-		$name = strtolower($name);
136
-		if (isset($this->annotations[$name][$key])) {
137
-			return $this->annotations[$name][$key];
138
-		}
139
-
140
-		return '';
141
-	}
142
-
143
-	public function getStartLine(): int {
144
-		return $this->startLine;
145
-	}
146
-
147
-	public function getFile(): string {
148
-		return $this->file;
149
-	}
17
+    public $annotations = [];
18
+    private $types = [];
19
+    private $parameters = [];
20
+    private array $ranges = [];
21
+    private int $startLine = 0;
22
+    private string $file = '';
23
+
24
+    /**
25
+     * @param object $object an object or classname
26
+     * @param string $method the method which we want to inspect
27
+     */
28
+    public function reflect($object, string $method) {
29
+        $reflection = new \ReflectionMethod($object, $method);
30
+        $this->startLine = $reflection->getStartLine();
31
+        $this->file = $reflection->getFileName();
32
+
33
+        $docs = $reflection->getDocComment();
34
+
35
+        if ($docs !== false) {
36
+            // extract everything prefixed by @ and first letter uppercase
37
+            preg_match_all('/^\h+\*\h+@(?P<annotation>[A-Z]\w+)((?P<parameter>.*))?$/m', $docs, $matches);
38
+            foreach ($matches['annotation'] as $key => $annotation) {
39
+                $annotation = strtolower($annotation);
40
+                $annotationValue = $matches['parameter'][$key];
41
+                if (str_starts_with($annotationValue, '(') && str_ends_with($annotationValue, ')')) {
42
+                    $cutString = substr($annotationValue, 1, -1);
43
+                    $cutString = str_replace(' ', '', $cutString);
44
+                    $splitArray = explode(',', $cutString);
45
+                    foreach ($splitArray as $annotationValues) {
46
+                        [$key, $value] = explode('=', $annotationValues);
47
+                        $this->annotations[$annotation][$key] = $value;
48
+                    }
49
+                    continue;
50
+                }
51
+
52
+                $this->annotations[$annotation] = [$annotationValue];
53
+            }
54
+
55
+            // extract type parameter information
56
+            preg_match_all('/@param\h+(?P<type>\w+)\h+\$(?P<var>\w+)/', $docs, $matches);
57
+            $this->types = array_combine($matches['var'], $matches['type']);
58
+            preg_match_all('/@(?:psalm-)?param\h+(\?)?(?P<type>\w+)<(?P<rangeMin>(-?\d+|min)),\h*(?P<rangeMax>(-?\d+|max))>(\|null)?\h+\$(?P<var>\w+)/', $docs, $matches);
59
+            foreach ($matches['var'] as $index => $varName) {
60
+                if ($matches['type'][$index] !== 'int') {
61
+                    // only int ranges are possible at the moment
62
+                    // @see https://psalm.dev/docs/annotating_code/type_syntax/scalar_types
63
+                    continue;
64
+                }
65
+                $this->ranges[$varName] = [
66
+                    'min' => $matches['rangeMin'][$index] === 'min' ? PHP_INT_MIN : (int)$matches['rangeMin'][$index],
67
+                    'max' => $matches['rangeMax'][$index] === 'max' ? PHP_INT_MAX : (int)$matches['rangeMax'][$index],
68
+                ];
69
+            }
70
+        }
71
+
72
+        foreach ($reflection->getParameters() as $param) {
73
+            // extract type information from PHP 7 scalar types and prefer them over phpdoc annotations
74
+            $type = $param->getType();
75
+            if ($type instanceof \ReflectionNamedType) {
76
+                $this->types[$param->getName()] = $type->getName();
77
+            }
78
+
79
+            $default = null;
80
+            if ($param->isOptional()) {
81
+                $default = $param->getDefaultValue();
82
+            }
83
+            $this->parameters[$param->name] = $default;
84
+        }
85
+    }
86
+
87
+    /**
88
+     * Inspects the PHPDoc parameters for types
89
+     * @param string $parameter the parameter whose type comments should be
90
+     *                          parsed
91
+     * @return string|null type in the type parameters (@param int $something)
92
+     *                     would return int or null if not existing
93
+     */
94
+    public function getType(string $parameter) {
95
+        if (array_key_exists($parameter, $this->types)) {
96
+            return $this->types[$parameter];
97
+        }
98
+
99
+        return null;
100
+    }
101
+
102
+    public function getRange(string $parameter): ?array {
103
+        if (array_key_exists($parameter, $this->ranges)) {
104
+            return $this->ranges[$parameter];
105
+        }
106
+
107
+        return null;
108
+    }
109
+
110
+    /**
111
+     * @return array the arguments of the method with key => default value
112
+     */
113
+    public function getParameters(): array {
114
+        return $this->parameters;
115
+    }
116
+
117
+    /**
118
+     * Check if a method contains an annotation
119
+     * @param string $name the name of the annotation
120
+     * @return bool true if the annotation is found
121
+     */
122
+    public function hasAnnotation(string $name): bool {
123
+        $name = strtolower($name);
124
+        return array_key_exists($name, $this->annotations);
125
+    }
126
+
127
+    /**
128
+     * Get optional annotation parameter by key
129
+     *
130
+     * @param string $name the name of the annotation
131
+     * @param string $key the string of the annotation
132
+     * @return string
133
+     */
134
+    public function getAnnotationParameter(string $name, string $key): string {
135
+        $name = strtolower($name);
136
+        if (isset($this->annotations[$name][$key])) {
137
+            return $this->annotations[$name][$key];
138
+        }
139
+
140
+        return '';
141
+    }
142
+
143
+    public function getStartLine(): int {
144
+        return $this->startLine;
145
+    }
146
+
147
+    public function getFile(): string {
148
+        return $this->file;
149
+    }
150 150
 }
Please login to merge, or discard this patch.
tests/lib/AppFramework/Utility/ControllerMethodReflectorTest.php 1 patch
Indentation   +255 added lines, -255 removed lines patch added patch discarded remove patch
@@ -11,271 +11,271 @@
 block discarded – undo
11 11
 use OC\AppFramework\Utility\ControllerMethodReflector;
12 12
 
13 13
 class BaseController {
14
-	/**
15
-	 * @Annotation
16
-	 */
17
-	public function test() {
18
-	}
19
-
20
-	/**
21
-	 * @Annotation
22
-	 */
23
-	public function test2() {
24
-	}
25
-
26
-	/**
27
-	 * @Annotation
28
-	 */
29
-	public function test3() {
30
-	}
14
+    /**
15
+     * @Annotation
16
+     */
17
+    public function test() {
18
+    }
19
+
20
+    /**
21
+     * @Annotation
22
+     */
23
+    public function test2() {
24
+    }
25
+
26
+    /**
27
+     * @Annotation
28
+     */
29
+    public function test3() {
30
+    }
31 31
 }
32 32
 
33 33
 class MiddleController extends BaseController {
34
-	/**
35
-	 * @NoAnnotation
36
-	 */
37
-	public function test2() {
38
-	}
39
-
40
-	public function test3() {
41
-	}
42
-
43
-	/**
44
-	 * @psalm-param int<-4, 42> $rangedOne
45
-	 * @psalm-param int<min, max> $rangedTwo
46
-	 * @psalm-param int<1, 6>|null $rangedThree
47
-	 * @psalm-param ?int<-70, -30> $rangedFour
48
-	 * @return void
49
-	 */
50
-	public function test4(int $rangedOne, int $rangedTwo, ?int $rangedThree, ?int $rangedFour) {
51
-	}
52
-
53
-	/**
54
-	 * @param int<-4, 42> $rangedOne
55
-	 * @param int<min, max> $rangedTwo
56
-	 * @param int<1, 6>|null $rangedThree
57
-	 * @param ?int<-70, -30> $rangedFour
58
-	 * @return void
59
-	 */
60
-	public function test5(int $rangedOne, int $rangedTwo, ?int $rangedThree, ?int $rangedFour) {
61
-	}
34
+    /**
35
+     * @NoAnnotation
36
+     */
37
+    public function test2() {
38
+    }
39
+
40
+    public function test3() {
41
+    }
42
+
43
+    /**
44
+     * @psalm-param int<-4, 42> $rangedOne
45
+     * @psalm-param int<min, max> $rangedTwo
46
+     * @psalm-param int<1, 6>|null $rangedThree
47
+     * @psalm-param ?int<-70, -30> $rangedFour
48
+     * @return void
49
+     */
50
+    public function test4(int $rangedOne, int $rangedTwo, ?int $rangedThree, ?int $rangedFour) {
51
+    }
52
+
53
+    /**
54
+     * @param int<-4, 42> $rangedOne
55
+     * @param int<min, max> $rangedTwo
56
+     * @param int<1, 6>|null $rangedThree
57
+     * @param ?int<-70, -30> $rangedFour
58
+     * @return void
59
+     */
60
+    public function test5(int $rangedOne, int $rangedTwo, ?int $rangedThree, ?int $rangedFour) {
61
+    }
62 62
 }
63 63
 
64 64
 class EndController extends MiddleController {
65 65
 }
66 66
 
67 67
 class ControllerMethodReflectorTest extends \Test\TestCase {
68
-	/**
69
-	 * @Annotation
70
-	 */
71
-	public function testReadAnnotation(): void {
72
-		$reader = new ControllerMethodReflector();
73
-		$reader->reflect(
74
-			'\Test\AppFramework\Utility\ControllerMethodReflectorTest',
75
-			'testReadAnnotation'
76
-		);
77
-
78
-		$this->assertTrue($reader->hasAnnotation('Annotation'));
79
-	}
80
-
81
-	/**
82
-	 * @Annotation(parameter=value)
83
-	 */
84
-	public function testGetAnnotationParameterSingle(): void {
85
-		$reader = new ControllerMethodReflector();
86
-		$reader->reflect(
87
-			self::class,
88
-			__FUNCTION__
89
-		);
90
-
91
-		$this->assertSame('value', $reader->getAnnotationParameter('Annotation', 'parameter'));
92
-	}
93
-
94
-	/**
95
-	 * @Annotation(parameter1=value1, parameter2=value2,parameter3=value3)
96
-	 */
97
-	public function testGetAnnotationParameterMultiple(): void {
98
-		$reader = new ControllerMethodReflector();
99
-		$reader->reflect(
100
-			self::class,
101
-			__FUNCTION__
102
-		);
103
-
104
-		$this->assertSame('value1', $reader->getAnnotationParameter('Annotation', 'parameter1'));
105
-		$this->assertSame('value2', $reader->getAnnotationParameter('Annotation', 'parameter2'));
106
-		$this->assertSame('value3', $reader->getAnnotationParameter('Annotation', 'parameter3'));
107
-	}
108
-
109
-	/**
110
-	 * @Annotation
111
-	 * @param test
112
-	 */
113
-	public function testReadAnnotationNoLowercase(): void {
114
-		$reader = new ControllerMethodReflector();
115
-		$reader->reflect(
116
-			'\Test\AppFramework\Utility\ControllerMethodReflectorTest',
117
-			'testReadAnnotationNoLowercase'
118
-		);
119
-
120
-		$this->assertTrue($reader->hasAnnotation('Annotation'));
121
-		$this->assertFalse($reader->hasAnnotation('param'));
122
-	}
123
-
124
-
125
-	/**
126
-	 * @Annotation
127
-	 * @param int $test
128
-	 */
129
-	public function testReadTypeIntAnnotations(): void {
130
-		$reader = new ControllerMethodReflector();
131
-		$reader->reflect(
132
-			'\Test\AppFramework\Utility\ControllerMethodReflectorTest',
133
-			'testReadTypeIntAnnotations'
134
-		);
135
-
136
-		$this->assertEquals('int', $reader->getType('test'));
137
-	}
138
-
139
-	/**
140
-	 * @Annotation
141
-	 * @param int $a
142
-	 * @param int $b
143
-	 */
144
-	public function arguments3($a, float $b, int $c, $d) {
145
-	}
146
-
147
-	public function testReadTypeIntAnnotationsScalarTypes(): void {
148
-		$reader = new ControllerMethodReflector();
149
-		$reader->reflect(
150
-			'\Test\AppFramework\Utility\ControllerMethodReflectorTest',
151
-			'arguments3'
152
-		);
153
-
154
-		$this->assertEquals('int', $reader->getType('a'));
155
-		$this->assertEquals('float', $reader->getType('b'));
156
-		$this->assertEquals('int', $reader->getType('c'));
157
-		$this->assertNull($reader->getType('d'));
158
-	}
159
-
160
-
161
-	/**
162
-	 * @Annotation
163
-	 * @param double $test something special
164
-	 */
165
-	public function testReadTypeDoubleAnnotations(): void {
166
-		$reader = new ControllerMethodReflector();
167
-		$reader->reflect(
168
-			'\Test\AppFramework\Utility\ControllerMethodReflectorTest',
169
-			'testReadTypeDoubleAnnotations'
170
-		);
171
-
172
-		$this->assertEquals('double', $reader->getType('test'));
173
-	}
174
-
175
-	/**
176
-	 * @Annotation
177
-	 * @param string $foo
178
-	 */
179
-	public function testReadTypeWhitespaceAnnotations(): void {
180
-		$reader = new ControllerMethodReflector();
181
-		$reader->reflect(
182
-			'\Test\AppFramework\Utility\ControllerMethodReflectorTest',
183
-			'testReadTypeWhitespaceAnnotations'
184
-		);
185
-
186
-		$this->assertEquals('string', $reader->getType('foo'));
187
-	}
188
-
189
-
190
-	public function arguments($arg, $arg2 = 'hi') {
191
-	}
192
-	public function testReflectParameters(): void {
193
-		$reader = new ControllerMethodReflector();
194
-		$reader->reflect(
195
-			'\Test\AppFramework\Utility\ControllerMethodReflectorTest',
196
-			'arguments'
197
-		);
198
-
199
-		$this->assertEquals(['arg' => null, 'arg2' => 'hi'], $reader->getParameters());
200
-	}
201
-
202
-
203
-	public function arguments2($arg) {
204
-	}
205
-	public function testReflectParameters2(): void {
206
-		$reader = new ControllerMethodReflector();
207
-		$reader->reflect(
208
-			'\Test\AppFramework\Utility\ControllerMethodReflectorTest',
209
-			'arguments2'
210
-		);
211
-
212
-		$this->assertEquals(['arg' => null], $reader->getParameters());
213
-	}
214
-
215
-
216
-	public function testInheritance(): void {
217
-		$reader = new ControllerMethodReflector();
218
-		$reader->reflect('Test\AppFramework\Utility\EndController', 'test');
219
-
220
-		$this->assertTrue($reader->hasAnnotation('Annotation'));
221
-	}
222
-
223
-
224
-	public function testInheritanceOverride(): void {
225
-		$reader = new ControllerMethodReflector();
226
-		$reader->reflect('Test\AppFramework\Utility\EndController', 'test2');
227
-
228
-		$this->assertTrue($reader->hasAnnotation('NoAnnotation'));
229
-		$this->assertFalse($reader->hasAnnotation('Annotation'));
230
-	}
231
-
232
-
233
-	public function testInheritanceOverrideNoDocblock(): void {
234
-		$reader = new ControllerMethodReflector();
235
-		$reader->reflect('Test\AppFramework\Utility\EndController', 'test3');
236
-
237
-		$this->assertFalse($reader->hasAnnotation('Annotation'));
238
-	}
239
-
240
-	public function testRangeDetectionPsalm(): void {
241
-		$reader = new ControllerMethodReflector();
242
-		$reader->reflect('Test\AppFramework\Utility\EndController', 'test4');
243
-
244
-		$rangeInfo1 = $reader->getRange('rangedOne');
245
-		$this->assertSame(-4, $rangeInfo1['min']);
246
-		$this->assertSame(42, $rangeInfo1['max']);
247
-
248
-		$rangeInfo2 = $reader->getRange('rangedTwo');
249
-		$this->assertSame(PHP_INT_MIN, $rangeInfo2['min']);
250
-		$this->assertSame(PHP_INT_MAX, $rangeInfo2['max']);
251
-
252
-		$rangeInfo3 = $reader->getRange('rangedThree');
253
-		$this->assertSame(1, $rangeInfo3['min']);
254
-		$this->assertSame(6, $rangeInfo3['max']);
255
-
256
-		$rangeInfo3 = $reader->getRange('rangedFour');
257
-		$this->assertSame(-70, $rangeInfo3['min']);
258
-		$this->assertSame(-30, $rangeInfo3['max']);
259
-	}
260
-
261
-	public function testRangeDetectionNative(): void {
262
-		$reader = new ControllerMethodReflector();
263
-		$reader->reflect('Test\AppFramework\Utility\EndController', 'test5');
264
-
265
-		$rangeInfo1 = $reader->getRange('rangedOne');
266
-		$this->assertSame(-4, $rangeInfo1['min']);
267
-		$this->assertSame(42, $rangeInfo1['max']);
68
+    /**
69
+     * @Annotation
70
+     */
71
+    public function testReadAnnotation(): void {
72
+        $reader = new ControllerMethodReflector();
73
+        $reader->reflect(
74
+            '\Test\AppFramework\Utility\ControllerMethodReflectorTest',
75
+            'testReadAnnotation'
76
+        );
77
+
78
+        $this->assertTrue($reader->hasAnnotation('Annotation'));
79
+    }
80
+
81
+    /**
82
+     * @Annotation(parameter=value)
83
+     */
84
+    public function testGetAnnotationParameterSingle(): void {
85
+        $reader = new ControllerMethodReflector();
86
+        $reader->reflect(
87
+            self::class,
88
+            __FUNCTION__
89
+        );
90
+
91
+        $this->assertSame('value', $reader->getAnnotationParameter('Annotation', 'parameter'));
92
+    }
93
+
94
+    /**
95
+     * @Annotation(parameter1=value1, parameter2=value2,parameter3=value3)
96
+     */
97
+    public function testGetAnnotationParameterMultiple(): void {
98
+        $reader = new ControllerMethodReflector();
99
+        $reader->reflect(
100
+            self::class,
101
+            __FUNCTION__
102
+        );
103
+
104
+        $this->assertSame('value1', $reader->getAnnotationParameter('Annotation', 'parameter1'));
105
+        $this->assertSame('value2', $reader->getAnnotationParameter('Annotation', 'parameter2'));
106
+        $this->assertSame('value3', $reader->getAnnotationParameter('Annotation', 'parameter3'));
107
+    }
108
+
109
+    /**
110
+     * @Annotation
111
+     * @param test
112
+     */
113
+    public function testReadAnnotationNoLowercase(): void {
114
+        $reader = new ControllerMethodReflector();
115
+        $reader->reflect(
116
+            '\Test\AppFramework\Utility\ControllerMethodReflectorTest',
117
+            'testReadAnnotationNoLowercase'
118
+        );
119
+
120
+        $this->assertTrue($reader->hasAnnotation('Annotation'));
121
+        $this->assertFalse($reader->hasAnnotation('param'));
122
+    }
123
+
124
+
125
+    /**
126
+     * @Annotation
127
+     * @param int $test
128
+     */
129
+    public function testReadTypeIntAnnotations(): void {
130
+        $reader = new ControllerMethodReflector();
131
+        $reader->reflect(
132
+            '\Test\AppFramework\Utility\ControllerMethodReflectorTest',
133
+            'testReadTypeIntAnnotations'
134
+        );
135
+
136
+        $this->assertEquals('int', $reader->getType('test'));
137
+    }
138
+
139
+    /**
140
+     * @Annotation
141
+     * @param int $a
142
+     * @param int $b
143
+     */
144
+    public function arguments3($a, float $b, int $c, $d) {
145
+    }
146
+
147
+    public function testReadTypeIntAnnotationsScalarTypes(): void {
148
+        $reader = new ControllerMethodReflector();
149
+        $reader->reflect(
150
+            '\Test\AppFramework\Utility\ControllerMethodReflectorTest',
151
+            'arguments3'
152
+        );
153
+
154
+        $this->assertEquals('int', $reader->getType('a'));
155
+        $this->assertEquals('float', $reader->getType('b'));
156
+        $this->assertEquals('int', $reader->getType('c'));
157
+        $this->assertNull($reader->getType('d'));
158
+    }
159
+
160
+
161
+    /**
162
+     * @Annotation
163
+     * @param double $test something special
164
+     */
165
+    public function testReadTypeDoubleAnnotations(): void {
166
+        $reader = new ControllerMethodReflector();
167
+        $reader->reflect(
168
+            '\Test\AppFramework\Utility\ControllerMethodReflectorTest',
169
+            'testReadTypeDoubleAnnotations'
170
+        );
171
+
172
+        $this->assertEquals('double', $reader->getType('test'));
173
+    }
174
+
175
+    /**
176
+     * @Annotation
177
+     * @param string $foo
178
+     */
179
+    public function testReadTypeWhitespaceAnnotations(): void {
180
+        $reader = new ControllerMethodReflector();
181
+        $reader->reflect(
182
+            '\Test\AppFramework\Utility\ControllerMethodReflectorTest',
183
+            'testReadTypeWhitespaceAnnotations'
184
+        );
185
+
186
+        $this->assertEquals('string', $reader->getType('foo'));
187
+    }
188
+
189
+
190
+    public function arguments($arg, $arg2 = 'hi') {
191
+    }
192
+    public function testReflectParameters(): void {
193
+        $reader = new ControllerMethodReflector();
194
+        $reader->reflect(
195
+            '\Test\AppFramework\Utility\ControllerMethodReflectorTest',
196
+            'arguments'
197
+        );
198
+
199
+        $this->assertEquals(['arg' => null, 'arg2' => 'hi'], $reader->getParameters());
200
+    }
201
+
202
+
203
+    public function arguments2($arg) {
204
+    }
205
+    public function testReflectParameters2(): void {
206
+        $reader = new ControllerMethodReflector();
207
+        $reader->reflect(
208
+            '\Test\AppFramework\Utility\ControllerMethodReflectorTest',
209
+            'arguments2'
210
+        );
211
+
212
+        $this->assertEquals(['arg' => null], $reader->getParameters());
213
+    }
214
+
215
+
216
+    public function testInheritance(): void {
217
+        $reader = new ControllerMethodReflector();
218
+        $reader->reflect('Test\AppFramework\Utility\EndController', 'test');
219
+
220
+        $this->assertTrue($reader->hasAnnotation('Annotation'));
221
+    }
222
+
223
+
224
+    public function testInheritanceOverride(): void {
225
+        $reader = new ControllerMethodReflector();
226
+        $reader->reflect('Test\AppFramework\Utility\EndController', 'test2');
227
+
228
+        $this->assertTrue($reader->hasAnnotation('NoAnnotation'));
229
+        $this->assertFalse($reader->hasAnnotation('Annotation'));
230
+    }
231
+
232
+
233
+    public function testInheritanceOverrideNoDocblock(): void {
234
+        $reader = new ControllerMethodReflector();
235
+        $reader->reflect('Test\AppFramework\Utility\EndController', 'test3');
236
+
237
+        $this->assertFalse($reader->hasAnnotation('Annotation'));
238
+    }
239
+
240
+    public function testRangeDetectionPsalm(): void {
241
+        $reader = new ControllerMethodReflector();
242
+        $reader->reflect('Test\AppFramework\Utility\EndController', 'test4');
243
+
244
+        $rangeInfo1 = $reader->getRange('rangedOne');
245
+        $this->assertSame(-4, $rangeInfo1['min']);
246
+        $this->assertSame(42, $rangeInfo1['max']);
247
+
248
+        $rangeInfo2 = $reader->getRange('rangedTwo');
249
+        $this->assertSame(PHP_INT_MIN, $rangeInfo2['min']);
250
+        $this->assertSame(PHP_INT_MAX, $rangeInfo2['max']);
251
+
252
+        $rangeInfo3 = $reader->getRange('rangedThree');
253
+        $this->assertSame(1, $rangeInfo3['min']);
254
+        $this->assertSame(6, $rangeInfo3['max']);
255
+
256
+        $rangeInfo3 = $reader->getRange('rangedFour');
257
+        $this->assertSame(-70, $rangeInfo3['min']);
258
+        $this->assertSame(-30, $rangeInfo3['max']);
259
+    }
260
+
261
+    public function testRangeDetectionNative(): void {
262
+        $reader = new ControllerMethodReflector();
263
+        $reader->reflect('Test\AppFramework\Utility\EndController', 'test5');
264
+
265
+        $rangeInfo1 = $reader->getRange('rangedOne');
266
+        $this->assertSame(-4, $rangeInfo1['min']);
267
+        $this->assertSame(42, $rangeInfo1['max']);
268 268
 
269
-		$rangeInfo2 = $reader->getRange('rangedTwo');
270
-		$this->assertSame(PHP_INT_MIN, $rangeInfo2['min']);
271
-		$this->assertSame(PHP_INT_MAX, $rangeInfo2['max']);
269
+        $rangeInfo2 = $reader->getRange('rangedTwo');
270
+        $this->assertSame(PHP_INT_MIN, $rangeInfo2['min']);
271
+        $this->assertSame(PHP_INT_MAX, $rangeInfo2['max']);
272 272
 
273
-		$rangeInfo3 = $reader->getRange('rangedThree');
274
-		$this->assertSame(1, $rangeInfo3['min']);
275
-		$this->assertSame(6, $rangeInfo3['max']);
273
+        $rangeInfo3 = $reader->getRange('rangedThree');
274
+        $this->assertSame(1, $rangeInfo3['min']);
275
+        $this->assertSame(6, $rangeInfo3['max']);
276 276
 
277
-		$rangeInfo3 = $reader->getRange('rangedFour');
278
-		$this->assertSame(-70, $rangeInfo3['min']);
279
-		$this->assertSame(-30, $rangeInfo3['max']);
280
-	}
277
+        $rangeInfo3 = $reader->getRange('rangedFour');
278
+        $this->assertSame(-70, $rangeInfo3['min']);
279
+        $this->assertSame(-30, $rangeInfo3['max']);
280
+    }
281 281
 }
Please login to merge, or discard this patch.