├── .editorconfig ├── .gitignore ├── .scrutinizer.yml ├── .travis.yml ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── phpunit.xml ├── src ├── BuiltInTypes.php ├── CallbackType.php ├── InvalidCallbackException.php ├── MatchTester.php ├── ParameterType.php ├── ReturnType.php └── Type.php └── tests ├── Fixtures ├── ClassImplementingInvoke.php ├── ClassImplementingIteratorAggregate.php ├── ClassImplementingNothing.php └── ClassImplementingToString.php ├── MatchTesterTest.php ├── Php71 └── BasePhp71Test.php └── TypeTest.php /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | indent_style = spaces 8 | indent_size = 4 9 | charset = utf-8 10 | 11 | [{.travis.yml}] 12 | indent_style = space 13 | indent_size = 2 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | vendor 3 | -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | filter: 2 | excluded_paths: 3 | - 'tests/*' 4 | 5 | tools: 6 | external_code_coverage: true 7 | 8 | build: 9 | environment: 10 | php: 11 | version: "7.0" 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: php 4 | 5 | php: 6 | - '7.0' 7 | - '7.1' 8 | - nightly 9 | 10 | before_script: 11 | - travis_retry composer self-update 12 | - travis_retry composer install --no-interaction 13 | 14 | script: 15 | - phpdbg -qrr vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover 16 | 17 | after_script: 18 | - wget https://scrutinizer-ci.com/ocular.phar 19 | - php ocular.phar code-coverage:upload --format=php-clover coverage.clover 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Chris Wright 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Callback Validator 2 | ================== 3 | 4 | Validates callback signatures against a prototype. 5 | 6 | ## Status 7 | 8 | [![Build Status](https://travis-ci.org/DaveRandom/CallbackValidator.svg?branch=master)](https://travis-ci.org/DaveRandom/CallbackValidator) 9 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/DaveRandom/CallbackValidator/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/DaveRandom/CallbackValidator/?branch=master) 10 | [![Code Coverage](https://scrutinizer-ci.com/g/DaveRandom/CallbackValidator/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/DaveRandom/CallbackValidator/?branch=master) 11 | 12 | ## Usage 13 | 14 | ```php 15 | // Create a prototype function (can be any callable) 16 | $prototype = function (A $a, B $b, $c): ?string {}; 17 | 18 | // Validate that callables match the prototype 19 | $tests = [ 20 | $prototype, // true 21 | function (A $a, B $b, $c) {}, // false - return type does not match 22 | function ($a, $b, $c): ?string {}, // true - arguments are contravariant 23 | function (A $a, B $b): ?string {}, // true - extra args don't cause errors 24 | function (A $a, B $b, $c, $d): ?string {}, // false - Insufficient args cause an error 25 | function (C $a, B $b, $c): ?string {}, // true if C is a supertype of A, false otherwise 26 | function (SuperTypeOfA $a, B $b, $c): ?string {}, // true 27 | function (A $a, B $b, $c): string {}, // true - return types are covariant 28 | ]; 29 | 30 | // Create a type from a prototype 31 | $type = CallbackType::createFromCallable($prototype); 32 | 33 | run_tests($type, $tests); 34 | 35 | // ...or create a type by hand for more granular control over variance rules 36 | $type = new CallbackType( 37 | new ReturnType(BuiltInTypes::STRING, ReturnType::NULLABLE | ReturnType::COVARIANT), 38 | new ParameterType('a', A::class), 39 | new ParameterType('b', B::class), 40 | new ParameterType('c') 41 | ); 42 | 43 | run_tests($type, $tests); 44 | 45 | function run_tests(CallbackType $type, array $tests) 46 | { 47 | foreach ($tests as $test) { 48 | if ($type->isSatisfiedBy($test)) { 49 | echo "pass\n"; 50 | } else { 51 | // CallbackType implements __toString() for easy inspections 52 | echo CallbackType::createFromCallable($test) . " does not satisfy {$type}\n"; 53 | } 54 | } 55 | } 56 | ``` 57 | 58 | ## TODO 59 | 60 | - Lots more tests 61 | - Explain (text explanation of why callback does not validate) 62 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "daverandom/callback-validator", 3 | "description": "Tools for validating callback signatures", 4 | "minimum-stability": "dev", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Chris Wright", 9 | "email": "cw@daverandom.com" 10 | } 11 | ], 12 | "require": { 13 | "php": ">=7.0", 14 | "ext-reflection": "*" 15 | }, 16 | "require-dev": { 17 | "phpunit/phpunit": "^6.0" 18 | }, 19 | "autoload": { 20 | "psr-4": { 21 | "DaveRandom\\CallbackValidator\\": "src/" 22 | } 23 | }, 24 | "autoload-dev": { 25 | "psr-4": { 26 | "DaveRandom\\CallbackValidator\\Test\\": "tests/" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "18c63c10fc5c838a467859b0447d0107", 8 | "content-hash": "0e9e28039a829626faa914ca73ef8b7f", 9 | "packages": [], 10 | "packages-dev": [ 11 | { 12 | "name": "doctrine/instantiator", 13 | "version": "dev-master", 14 | "source": { 15 | "type": "git", 16 | "url": "https://github.com/doctrine/instantiator.git", 17 | "reference": "5acd2bd8c2b600ad5cc4c9180ebf0a930604d6a5" 18 | }, 19 | "dist": { 20 | "type": "zip", 21 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/5acd2bd8c2b600ad5cc4c9180ebf0a930604d6a5", 22 | "reference": "5acd2bd8c2b600ad5cc4c9180ebf0a930604d6a5", 23 | "shasum": "" 24 | }, 25 | "require": { 26 | "php": ">=5.3,<8.0-DEV" 27 | }, 28 | "require-dev": { 29 | "athletic/athletic": "~0.1.8", 30 | "ext-pdo": "*", 31 | "ext-phar": "*", 32 | "phpunit/phpunit": "~4.0", 33 | "squizlabs/php_codesniffer": "~2.0" 34 | }, 35 | "type": "library", 36 | "extra": { 37 | "branch-alias": { 38 | "dev-master": "1.0.x-dev" 39 | } 40 | }, 41 | "autoload": { 42 | "psr-4": { 43 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 44 | } 45 | }, 46 | "notification-url": "https://packagist.org/downloads/", 47 | "license": [ 48 | "MIT" 49 | ], 50 | "authors": [ 51 | { 52 | "name": "Marco Pivetta", 53 | "email": "ocramius@gmail.com", 54 | "homepage": "http://ocramius.github.com/" 55 | } 56 | ], 57 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 58 | "homepage": "https://github.com/doctrine/instantiator", 59 | "keywords": [ 60 | "constructor", 61 | "instantiate" 62 | ], 63 | "time": "2017-02-16 16:15:51" 64 | }, 65 | { 66 | "name": "myclabs/deep-copy", 67 | "version": "1.6.0", 68 | "source": { 69 | "type": "git", 70 | "url": "https://github.com/myclabs/DeepCopy.git", 71 | "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe" 72 | }, 73 | "dist": { 74 | "type": "zip", 75 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/5a5a9fc8025a08d8919be87d6884d5a92520cefe", 76 | "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe", 77 | "shasum": "" 78 | }, 79 | "require": { 80 | "php": ">=5.4.0" 81 | }, 82 | "require-dev": { 83 | "doctrine/collections": "1.*", 84 | "phpunit/phpunit": "~4.1" 85 | }, 86 | "type": "library", 87 | "autoload": { 88 | "psr-4": { 89 | "DeepCopy\\": "src/DeepCopy/" 90 | } 91 | }, 92 | "notification-url": "https://packagist.org/downloads/", 93 | "license": [ 94 | "MIT" 95 | ], 96 | "description": "Create deep copies (clones) of your objects", 97 | "homepage": "https://github.com/myclabs/DeepCopy", 98 | "keywords": [ 99 | "clone", 100 | "copy", 101 | "duplicate", 102 | "object", 103 | "object graph" 104 | ], 105 | "time": "2017-01-26 22:05:40" 106 | }, 107 | { 108 | "name": "phar-io/manifest", 109 | "version": "dev-master", 110 | "source": { 111 | "type": "git", 112 | "url": "https://github.com/phar-io/manifest.git", 113 | "reference": "7f913ee00931341f88902b6dd3b969f5dc8fff85" 114 | }, 115 | "dist": { 116 | "type": "zip", 117 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/7f913ee00931341f88902b6dd3b969f5dc8fff85", 118 | "reference": "7f913ee00931341f88902b6dd3b969f5dc8fff85", 119 | "shasum": "" 120 | }, 121 | "require": { 122 | "ext-dom": "*", 123 | "ext-phar": "*", 124 | "phar-io/version": "^1.0.1", 125 | "php": "^5.6 || ^7.0" 126 | }, 127 | "type": "library", 128 | "extra": { 129 | "branch-alias": { 130 | "dev-master": "1.0.x-dev" 131 | } 132 | }, 133 | "autoload": { 134 | "classmap": [ 135 | "src/" 136 | ] 137 | }, 138 | "notification-url": "https://packagist.org/downloads/", 139 | "license": [ 140 | "BSD-3-Clause" 141 | ], 142 | "authors": [ 143 | { 144 | "name": "Arne Blankerts", 145 | "email": "arne@blankerts.de", 146 | "role": "Developer" 147 | }, 148 | { 149 | "name": "Sebastian Heuer", 150 | "email": "sebastian@phpeople.de", 151 | "role": "Developer" 152 | }, 153 | { 154 | "name": "Sebastian Bergmann", 155 | "email": "sebastian@phpunit.de", 156 | "role": "Developer" 157 | } 158 | ], 159 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 160 | "time": "2017-03-05 19:02:22" 161 | }, 162 | { 163 | "name": "phar-io/version", 164 | "version": "1.0.1", 165 | "source": { 166 | "type": "git", 167 | "url": "https://github.com/phar-io/version.git", 168 | "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" 169 | }, 170 | "dist": { 171 | "type": "zip", 172 | "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", 173 | "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", 174 | "shasum": "" 175 | }, 176 | "require": { 177 | "php": "^5.6 || ^7.0" 178 | }, 179 | "type": "library", 180 | "autoload": { 181 | "classmap": [ 182 | "src/" 183 | ] 184 | }, 185 | "notification-url": "https://packagist.org/downloads/", 186 | "license": [ 187 | "BSD-3-Clause" 188 | ], 189 | "authors": [ 190 | { 191 | "name": "Arne Blankerts", 192 | "email": "arne@blankerts.de", 193 | "role": "Developer" 194 | }, 195 | { 196 | "name": "Sebastian Heuer", 197 | "email": "sebastian@phpeople.de", 198 | "role": "Developer" 199 | }, 200 | { 201 | "name": "Sebastian Bergmann", 202 | "email": "sebastian@phpunit.de", 203 | "role": "Developer" 204 | } 205 | ], 206 | "description": "Library for handling version information and constraints", 207 | "time": "2017-03-05 17:38:23" 208 | }, 209 | { 210 | "name": "phpdocumentor/reflection-common", 211 | "version": "dev-master", 212 | "source": { 213 | "type": "git", 214 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 215 | "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" 216 | }, 217 | "dist": { 218 | "type": "zip", 219 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", 220 | "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", 221 | "shasum": "" 222 | }, 223 | "require": { 224 | "php": ">=5.5" 225 | }, 226 | "require-dev": { 227 | "phpunit/phpunit": "^4.6" 228 | }, 229 | "type": "library", 230 | "extra": { 231 | "branch-alias": { 232 | "dev-master": "1.0.x-dev" 233 | } 234 | }, 235 | "autoload": { 236 | "psr-4": { 237 | "phpDocumentor\\Reflection\\": [ 238 | "src" 239 | ] 240 | } 241 | }, 242 | "notification-url": "https://packagist.org/downloads/", 243 | "license": [ 244 | "MIT" 245 | ], 246 | "authors": [ 247 | { 248 | "name": "Jaap van Otterdijk", 249 | "email": "opensource@ijaap.nl" 250 | } 251 | ], 252 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 253 | "homepage": "http://www.phpdoc.org", 254 | "keywords": [ 255 | "FQSEN", 256 | "phpDocumentor", 257 | "phpdoc", 258 | "reflection", 259 | "static analysis" 260 | ], 261 | "time": "2015-12-27 11:43:31" 262 | }, 263 | { 264 | "name": "phpdocumentor/reflection-docblock", 265 | "version": "3.1.1", 266 | "source": { 267 | "type": "git", 268 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 269 | "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" 270 | }, 271 | "dist": { 272 | "type": "zip", 273 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", 274 | "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", 275 | "shasum": "" 276 | }, 277 | "require": { 278 | "php": ">=5.5", 279 | "phpdocumentor/reflection-common": "^1.0@dev", 280 | "phpdocumentor/type-resolver": "^0.2.0", 281 | "webmozart/assert": "^1.0" 282 | }, 283 | "require-dev": { 284 | "mockery/mockery": "^0.9.4", 285 | "phpunit/phpunit": "^4.4" 286 | }, 287 | "type": "library", 288 | "autoload": { 289 | "psr-4": { 290 | "phpDocumentor\\Reflection\\": [ 291 | "src/" 292 | ] 293 | } 294 | }, 295 | "notification-url": "https://packagist.org/downloads/", 296 | "license": [ 297 | "MIT" 298 | ], 299 | "authors": [ 300 | { 301 | "name": "Mike van Riel", 302 | "email": "me@mikevanriel.com" 303 | } 304 | ], 305 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 306 | "time": "2016-09-30 07:12:33" 307 | }, 308 | { 309 | "name": "phpdocumentor/type-resolver", 310 | "version": "0.2.1", 311 | "source": { 312 | "type": "git", 313 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 314 | "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" 315 | }, 316 | "dist": { 317 | "type": "zip", 318 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", 319 | "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", 320 | "shasum": "" 321 | }, 322 | "require": { 323 | "php": ">=5.5", 324 | "phpdocumentor/reflection-common": "^1.0" 325 | }, 326 | "require-dev": { 327 | "mockery/mockery": "^0.9.4", 328 | "phpunit/phpunit": "^5.2||^4.8.24" 329 | }, 330 | "type": "library", 331 | "extra": { 332 | "branch-alias": { 333 | "dev-master": "1.0.x-dev" 334 | } 335 | }, 336 | "autoload": { 337 | "psr-4": { 338 | "phpDocumentor\\Reflection\\": [ 339 | "src/" 340 | ] 341 | } 342 | }, 343 | "notification-url": "https://packagist.org/downloads/", 344 | "license": [ 345 | "MIT" 346 | ], 347 | "authors": [ 348 | { 349 | "name": "Mike van Riel", 350 | "email": "me@mikevanriel.com" 351 | } 352 | ], 353 | "time": "2016-11-25 06:54:22" 354 | }, 355 | { 356 | "name": "phpspec/prophecy", 357 | "version": "dev-master", 358 | "source": { 359 | "type": "git", 360 | "url": "https://github.com/phpspec/prophecy.git", 361 | "reference": "abe41cb27f4e4207c6f54a09272969fe55e0bbff" 362 | }, 363 | "dist": { 364 | "type": "zip", 365 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/abe41cb27f4e4207c6f54a09272969fe55e0bbff", 366 | "reference": "abe41cb27f4e4207c6f54a09272969fe55e0bbff", 367 | "shasum": "" 368 | }, 369 | "require": { 370 | "doctrine/instantiator": "^1.0.2", 371 | "php": "^5.3|^7.0", 372 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", 373 | "sebastian/comparator": "^1.1|^2.0", 374 | "sebastian/recursion-context": "^1.0|^2.0|^3.0" 375 | }, 376 | "require-dev": { 377 | "phpspec/phpspec": "^2.5|^3.2", 378 | "phpunit/phpunit": "^4.8 || ^5.6.5" 379 | }, 380 | "type": "library", 381 | "extra": { 382 | "branch-alias": { 383 | "dev-master": "1.7.x-dev" 384 | } 385 | }, 386 | "autoload": { 387 | "psr-0": { 388 | "Prophecy\\": "src/" 389 | } 390 | }, 391 | "notification-url": "https://packagist.org/downloads/", 392 | "license": [ 393 | "MIT" 394 | ], 395 | "authors": [ 396 | { 397 | "name": "Konstantin Kudryashov", 398 | "email": "ever.zet@gmail.com", 399 | "homepage": "http://everzet.com" 400 | }, 401 | { 402 | "name": "Marcello Duarte", 403 | "email": "marcello.duarte@gmail.com" 404 | } 405 | ], 406 | "description": "Highly opinionated mocking framework for PHP 5.3+", 407 | "homepage": "https://github.com/phpspec/prophecy", 408 | "keywords": [ 409 | "Double", 410 | "Dummy", 411 | "fake", 412 | "mock", 413 | "spy", 414 | "stub" 415 | ], 416 | "time": "2017-03-03 17:09:02" 417 | }, 418 | { 419 | "name": "phpunit/php-code-coverage", 420 | "version": "dev-master", 421 | "source": { 422 | "type": "git", 423 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 424 | "reference": "7b69b0c75afe601047bae69e9065ef154ffce111" 425 | }, 426 | "dist": { 427 | "type": "zip", 428 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7b69b0c75afe601047bae69e9065ef154ffce111", 429 | "reference": "7b69b0c75afe601047bae69e9065ef154ffce111", 430 | "shasum": "" 431 | }, 432 | "require": { 433 | "ext-dom": "*", 434 | "ext-xmlwriter": "*", 435 | "php": "^7.0", 436 | "phpunit/php-file-iterator": "^1.3", 437 | "phpunit/php-text-template": "^1.2", 438 | "phpunit/php-token-stream": "^1.4.11 || ^2.0", 439 | "sebastian/code-unit-reverse-lookup": "^1.0", 440 | "sebastian/environment": "^2.0", 441 | "sebastian/version": "^2.0" 442 | }, 443 | "require-dev": { 444 | "ext-xdebug": "^2.5", 445 | "phpunit/phpunit": "^6.0" 446 | }, 447 | "suggest": { 448 | "ext-xdebug": "^2.5.1" 449 | }, 450 | "type": "library", 451 | "extra": { 452 | "branch-alias": { 453 | "dev-master": "5.0.x-dev" 454 | } 455 | }, 456 | "autoload": { 457 | "classmap": [ 458 | "src/" 459 | ] 460 | }, 461 | "notification-url": "https://packagist.org/downloads/", 462 | "license": [ 463 | "BSD-3-Clause" 464 | ], 465 | "authors": [ 466 | { 467 | "name": "Sebastian Bergmann", 468 | "email": "sb@sebastian-bergmann.de", 469 | "role": "lead" 470 | } 471 | ], 472 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 473 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 474 | "keywords": [ 475 | "coverage", 476 | "testing", 477 | "xunit" 478 | ], 479 | "time": "2017-03-31 13:21:26" 480 | }, 481 | { 482 | "name": "phpunit/php-file-iterator", 483 | "version": "dev-master", 484 | "source": { 485 | "type": "git", 486 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 487 | "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" 488 | }, 489 | "dist": { 490 | "type": "zip", 491 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", 492 | "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", 493 | "shasum": "" 494 | }, 495 | "require": { 496 | "php": ">=5.3.3" 497 | }, 498 | "type": "library", 499 | "extra": { 500 | "branch-alias": { 501 | "dev-master": "1.4.x-dev" 502 | } 503 | }, 504 | "autoload": { 505 | "classmap": [ 506 | "src/" 507 | ] 508 | }, 509 | "notification-url": "https://packagist.org/downloads/", 510 | "license": [ 511 | "BSD-3-Clause" 512 | ], 513 | "authors": [ 514 | { 515 | "name": "Sebastian Bergmann", 516 | "email": "sb@sebastian-bergmann.de", 517 | "role": "lead" 518 | } 519 | ], 520 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 521 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 522 | "keywords": [ 523 | "filesystem", 524 | "iterator" 525 | ], 526 | "time": "2016-10-03 07:40:28" 527 | }, 528 | { 529 | "name": "phpunit/php-text-template", 530 | "version": "1.2.1", 531 | "source": { 532 | "type": "git", 533 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 534 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 535 | }, 536 | "dist": { 537 | "type": "zip", 538 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 539 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 540 | "shasum": "" 541 | }, 542 | "require": { 543 | "php": ">=5.3.3" 544 | }, 545 | "type": "library", 546 | "autoload": { 547 | "classmap": [ 548 | "src/" 549 | ] 550 | }, 551 | "notification-url": "https://packagist.org/downloads/", 552 | "license": [ 553 | "BSD-3-Clause" 554 | ], 555 | "authors": [ 556 | { 557 | "name": "Sebastian Bergmann", 558 | "email": "sebastian@phpunit.de", 559 | "role": "lead" 560 | } 561 | ], 562 | "description": "Simple template engine.", 563 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 564 | "keywords": [ 565 | "template" 566 | ], 567 | "time": "2015-06-21 13:50:34" 568 | }, 569 | { 570 | "name": "phpunit/php-timer", 571 | "version": "dev-master", 572 | "source": { 573 | "type": "git", 574 | "url": "https://github.com/sebastianbergmann/php-timer.git", 575 | "reference": "d107f347d368dd8a384601398280c7c608390ab7" 576 | }, 577 | "dist": { 578 | "type": "zip", 579 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/d107f347d368dd8a384601398280c7c608390ab7", 580 | "reference": "d107f347d368dd8a384601398280c7c608390ab7", 581 | "shasum": "" 582 | }, 583 | "require": { 584 | "php": "^5.3.3 || ^7.0" 585 | }, 586 | "require-dev": { 587 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 588 | }, 589 | "type": "library", 590 | "extra": { 591 | "branch-alias": { 592 | "dev-master": "1.0-dev" 593 | } 594 | }, 595 | "autoload": { 596 | "classmap": [ 597 | "src/" 598 | ] 599 | }, 600 | "notification-url": "https://packagist.org/downloads/", 601 | "license": [ 602 | "BSD-3-Clause" 603 | ], 604 | "authors": [ 605 | { 606 | "name": "Sebastian Bergmann", 607 | "email": "sb@sebastian-bergmann.de", 608 | "role": "lead" 609 | } 610 | ], 611 | "description": "Utility class for timing", 612 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 613 | "keywords": [ 614 | "timer" 615 | ], 616 | "time": "2017-03-07 15:42:04" 617 | }, 618 | { 619 | "name": "phpunit/php-token-stream", 620 | "version": "dev-master", 621 | "source": { 622 | "type": "git", 623 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 624 | "reference": "9ddb181faa4a3841fe131c357fd01de75cbb4da9" 625 | }, 626 | "dist": { 627 | "type": "zip", 628 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/9ddb181faa4a3841fe131c357fd01de75cbb4da9", 629 | "reference": "9ddb181faa4a3841fe131c357fd01de75cbb4da9", 630 | "shasum": "" 631 | }, 632 | "require": { 633 | "ext-tokenizer": "*", 634 | "php": "^5.6 || ^7.0" 635 | }, 636 | "require-dev": { 637 | "phpunit/phpunit": "^5.7 || ^6.0" 638 | }, 639 | "type": "library", 640 | "extra": { 641 | "branch-alias": { 642 | "dev-master": "2.0-dev" 643 | } 644 | }, 645 | "autoload": { 646 | "classmap": [ 647 | "src/" 648 | ] 649 | }, 650 | "notification-url": "https://packagist.org/downloads/", 651 | "license": [ 652 | "BSD-3-Clause" 653 | ], 654 | "authors": [ 655 | { 656 | "name": "Sebastian Bergmann", 657 | "email": "sebastian@phpunit.de" 658 | } 659 | ], 660 | "description": "Wrapper around PHP's tokenizer extension.", 661 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 662 | "keywords": [ 663 | "tokenizer" 664 | ], 665 | "time": "2017-03-07 07:36:57" 666 | }, 667 | { 668 | "name": "phpunit/phpunit", 669 | "version": "dev-master", 670 | "source": { 671 | "type": "git", 672 | "url": "https://github.com/sebastianbergmann/phpunit.git", 673 | "reference": "bf00f6f0dd1c379c082dd4fab27de475dbcb7bff" 674 | }, 675 | "dist": { 676 | "type": "zip", 677 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/bf00f6f0dd1c379c082dd4fab27de475dbcb7bff", 678 | "reference": "bf00f6f0dd1c379c082dd4fab27de475dbcb7bff", 679 | "shasum": "" 680 | }, 681 | "require": { 682 | "ext-dom": "*", 683 | "ext-json": "*", 684 | "ext-libxml": "*", 685 | "ext-mbstring": "*", 686 | "ext-xml": "*", 687 | "myclabs/deep-copy": "^1.3", 688 | "phar-io/manifest": "^1.0.1", 689 | "php": "^7.0", 690 | "phpspec/prophecy": "^1.7", 691 | "phpunit/php-code-coverage": "^5.0", 692 | "phpunit/php-file-iterator": "^1.4", 693 | "phpunit/php-text-template": "^1.2", 694 | "phpunit/php-timer": "^1.0.6", 695 | "phpunit/phpunit-mock-objects": "^4.0", 696 | "sebastian/comparator": "^2.0", 697 | "sebastian/diff": "^1.2", 698 | "sebastian/environment": "^2.0", 699 | "sebastian/exporter": "^3.0", 700 | "sebastian/global-state": "^1.1 || ^2.0", 701 | "sebastian/object-enumerator": "^3.0.2", 702 | "sebastian/resource-operations": "^1.0", 703 | "sebastian/version": "^2.0" 704 | }, 705 | "conflict": { 706 | "phpdocumentor/reflection-docblock": "3.0.2", 707 | "phpunit/dbunit": "<3.0" 708 | }, 709 | "require-dev": { 710 | "ext-pdo": "*" 711 | }, 712 | "suggest": { 713 | "ext-xdebug": "*", 714 | "phpunit/php-invoker": "^1.1" 715 | }, 716 | "bin": [ 717 | "phpunit" 718 | ], 719 | "type": "library", 720 | "extra": { 721 | "branch-alias": { 722 | "dev-master": "6.1.x-dev" 723 | } 724 | }, 725 | "autoload": { 726 | "classmap": [ 727 | "src/" 728 | ] 729 | }, 730 | "notification-url": "https://packagist.org/downloads/", 731 | "license": [ 732 | "BSD-3-Clause" 733 | ], 734 | "authors": [ 735 | { 736 | "name": "Sebastian Bergmann", 737 | "email": "sebastian@phpunit.de", 738 | "role": "lead" 739 | } 740 | ], 741 | "description": "The PHP Unit Testing framework.", 742 | "homepage": "https://phpunit.de/", 743 | "keywords": [ 744 | "phpunit", 745 | "testing", 746 | "xunit" 747 | ], 748 | "time": "2017-03-31 17:18:07" 749 | }, 750 | { 751 | "name": "phpunit/phpunit-mock-objects", 752 | "version": "dev-master", 753 | "source": { 754 | "type": "git", 755 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 756 | "reference": "94694b31c0099e9ce01443857ae0e3c65b1c1825" 757 | }, 758 | "dist": { 759 | "type": "zip", 760 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/94694b31c0099e9ce01443857ae0e3c65b1c1825", 761 | "reference": "94694b31c0099e9ce01443857ae0e3c65b1c1825", 762 | "shasum": "" 763 | }, 764 | "require": { 765 | "doctrine/instantiator": "^1.0.2", 766 | "php": "^7.0", 767 | "phpunit/php-text-template": "^1.2", 768 | "sebastian/exporter": "^3.0" 769 | }, 770 | "conflict": { 771 | "phpunit/phpunit": "<6.0" 772 | }, 773 | "require-dev": { 774 | "phpunit/phpunit": "^6.0" 775 | }, 776 | "suggest": { 777 | "ext-soap": "*" 778 | }, 779 | "type": "library", 780 | "extra": { 781 | "branch-alias": { 782 | "dev-master": "4.0.x-dev" 783 | } 784 | }, 785 | "autoload": { 786 | "classmap": [ 787 | "src/" 788 | ] 789 | }, 790 | "notification-url": "https://packagist.org/downloads/", 791 | "license": [ 792 | "BSD-3-Clause" 793 | ], 794 | "authors": [ 795 | { 796 | "name": "Sebastian Bergmann", 797 | "email": "sb@sebastian-bergmann.de", 798 | "role": "lead" 799 | } 800 | ], 801 | "description": "Mock Object library for PHPUnit", 802 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 803 | "keywords": [ 804 | "mock", 805 | "xunit" 806 | ], 807 | "time": "2017-03-07 08:51:01" 808 | }, 809 | { 810 | "name": "sebastian/code-unit-reverse-lookup", 811 | "version": "dev-master", 812 | "source": { 813 | "type": "git", 814 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 815 | "reference": "3488be0a7b346cd6e5361510ed07e88f9bea2e88" 816 | }, 817 | "dist": { 818 | "type": "zip", 819 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/3488be0a7b346cd6e5361510ed07e88f9bea2e88", 820 | "reference": "3488be0a7b346cd6e5361510ed07e88f9bea2e88", 821 | "shasum": "" 822 | }, 823 | "require": { 824 | "php": "^5.6 || ^7.0" 825 | }, 826 | "require-dev": { 827 | "phpunit/phpunit": "^5.7 || ^6.0" 828 | }, 829 | "type": "library", 830 | "extra": { 831 | "branch-alias": { 832 | "dev-master": "1.0.x-dev" 833 | } 834 | }, 835 | "autoload": { 836 | "classmap": [ 837 | "src/" 838 | ] 839 | }, 840 | "notification-url": "https://packagist.org/downloads/", 841 | "license": [ 842 | "BSD-3-Clause" 843 | ], 844 | "authors": [ 845 | { 846 | "name": "Sebastian Bergmann", 847 | "email": "sebastian@phpunit.de" 848 | } 849 | ], 850 | "description": "Looks up which function or method a line of code belongs to", 851 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 852 | "time": "2017-03-04 10:23:55" 853 | }, 854 | { 855 | "name": "sebastian/comparator", 856 | "version": "dev-master", 857 | "source": { 858 | "type": "git", 859 | "url": "https://github.com/sebastianbergmann/comparator.git", 860 | "reference": "8d783f84d4d5adb5e6668589c227f95172373b6a" 861 | }, 862 | "dist": { 863 | "type": "zip", 864 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/8d783f84d4d5adb5e6668589c227f95172373b6a", 865 | "reference": "8d783f84d4d5adb5e6668589c227f95172373b6a", 866 | "shasum": "" 867 | }, 868 | "require": { 869 | "php": "^7.0", 870 | "sebastian/diff": "^1.2", 871 | "sebastian/exporter": "^3.0" 872 | }, 873 | "require-dev": { 874 | "phpunit/phpunit": "^6.0" 875 | }, 876 | "type": "library", 877 | "extra": { 878 | "branch-alias": { 879 | "dev-master": "2.0.x-dev" 880 | } 881 | }, 882 | "autoload": { 883 | "classmap": [ 884 | "src/" 885 | ] 886 | }, 887 | "notification-url": "https://packagist.org/downloads/", 888 | "license": [ 889 | "BSD-3-Clause" 890 | ], 891 | "authors": [ 892 | { 893 | "name": "Jeff Welch", 894 | "email": "whatthejeff@gmail.com" 895 | }, 896 | { 897 | "name": "Volker Dusch", 898 | "email": "github@wallbash.com" 899 | }, 900 | { 901 | "name": "Bernhard Schussek", 902 | "email": "bschussek@2bepublished.at" 903 | }, 904 | { 905 | "name": "Sebastian Bergmann", 906 | "email": "sebastian@phpunit.de" 907 | } 908 | ], 909 | "description": "Provides the functionality to compare PHP values for equality", 910 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 911 | "keywords": [ 912 | "comparator", 913 | "compare", 914 | "equality" 915 | ], 916 | "time": "2017-03-07 07:07:51" 917 | }, 918 | { 919 | "name": "sebastian/diff", 920 | "version": "dev-master", 921 | "source": { 922 | "type": "git", 923 | "url": "https://github.com/sebastianbergmann/diff.git", 924 | "reference": "763d7adeb8c35d2af2b04c0f6cafeee059074dfb" 925 | }, 926 | "dist": { 927 | "type": "zip", 928 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/763d7adeb8c35d2af2b04c0f6cafeee059074dfb", 929 | "reference": "763d7adeb8c35d2af2b04c0f6cafeee059074dfb", 930 | "shasum": "" 931 | }, 932 | "require": { 933 | "php": "^5.3.3 || ^7.0" 934 | }, 935 | "require-dev": { 936 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 937 | }, 938 | "type": "library", 939 | "extra": { 940 | "branch-alias": { 941 | "dev-master": "1.4-dev" 942 | } 943 | }, 944 | "autoload": { 945 | "classmap": [ 946 | "src/" 947 | ] 948 | }, 949 | "notification-url": "https://packagist.org/downloads/", 950 | "license": [ 951 | "BSD-3-Clause" 952 | ], 953 | "authors": [ 954 | { 955 | "name": "Kore Nordmann", 956 | "email": "mail@kore-nordmann.de" 957 | }, 958 | { 959 | "name": "Sebastian Bergmann", 960 | "email": "sebastian@phpunit.de" 961 | } 962 | ], 963 | "description": "Diff implementation", 964 | "homepage": "https://github.com/sebastianbergmann/diff", 965 | "keywords": [ 966 | "diff" 967 | ], 968 | "time": "2017-03-07 07:26:53" 969 | }, 970 | { 971 | "name": "sebastian/environment", 972 | "version": "dev-master", 973 | "source": { 974 | "type": "git", 975 | "url": "https://github.com/sebastianbergmann/environment.git", 976 | "reference": "144fedf9aa8e3f1c52199f3634eb699cb59741d9" 977 | }, 978 | "dist": { 979 | "type": "zip", 980 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/144fedf9aa8e3f1c52199f3634eb699cb59741d9", 981 | "reference": "144fedf9aa8e3f1c52199f3634eb699cb59741d9", 982 | "shasum": "" 983 | }, 984 | "require": { 985 | "php": "^5.6 || ^7.0" 986 | }, 987 | "require-dev": { 988 | "phpunit/phpunit": "^5.7 || ^6.0" 989 | }, 990 | "type": "library", 991 | "extra": { 992 | "branch-alias": { 993 | "dev-master": "2.0.x-dev" 994 | } 995 | }, 996 | "autoload": { 997 | "classmap": [ 998 | "src/" 999 | ] 1000 | }, 1001 | "notification-url": "https://packagist.org/downloads/", 1002 | "license": [ 1003 | "BSD-3-Clause" 1004 | ], 1005 | "authors": [ 1006 | { 1007 | "name": "Sebastian Bergmann", 1008 | "email": "sebastian@phpunit.de" 1009 | } 1010 | ], 1011 | "description": "Provides functionality to handle HHVM/PHP environments", 1012 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1013 | "keywords": [ 1014 | "Xdebug", 1015 | "environment", 1016 | "hhvm" 1017 | ], 1018 | "time": "2017-03-07 12:59:58" 1019 | }, 1020 | { 1021 | "name": "sebastian/exporter", 1022 | "version": "dev-master", 1023 | "source": { 1024 | "type": "git", 1025 | "url": "https://github.com/sebastianbergmann/exporter.git", 1026 | "reference": "aaaaa5afbde60821d6c83477011fdb6c575e5243" 1027 | }, 1028 | "dist": { 1029 | "type": "zip", 1030 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/aaaaa5afbde60821d6c83477011fdb6c575e5243", 1031 | "reference": "aaaaa5afbde60821d6c83477011fdb6c575e5243", 1032 | "shasum": "" 1033 | }, 1034 | "require": { 1035 | "php": "^7.0", 1036 | "sebastian/recursion-context": "^3.0" 1037 | }, 1038 | "require-dev": { 1039 | "ext-mbstring": "*", 1040 | "phpunit/phpunit": "^6.0" 1041 | }, 1042 | "type": "library", 1043 | "extra": { 1044 | "branch-alias": { 1045 | "dev-master": "3.0.x-dev" 1046 | } 1047 | }, 1048 | "autoload": { 1049 | "classmap": [ 1050 | "src/" 1051 | ] 1052 | }, 1053 | "notification-url": "https://packagist.org/downloads/", 1054 | "license": [ 1055 | "BSD-3-Clause" 1056 | ], 1057 | "authors": [ 1058 | { 1059 | "name": "Jeff Welch", 1060 | "email": "whatthejeff@gmail.com" 1061 | }, 1062 | { 1063 | "name": "Volker Dusch", 1064 | "email": "github@wallbash.com" 1065 | }, 1066 | { 1067 | "name": "Bernhard Schussek", 1068 | "email": "bschussek@2bepublished.at" 1069 | }, 1070 | { 1071 | "name": "Sebastian Bergmann", 1072 | "email": "sebastian@phpunit.de" 1073 | }, 1074 | { 1075 | "name": "Adam Harvey", 1076 | "email": "aharvey@php.net" 1077 | } 1078 | ], 1079 | "description": "Provides the functionality to export PHP variables for visualization", 1080 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1081 | "keywords": [ 1082 | "export", 1083 | "exporter" 1084 | ], 1085 | "time": "2017-03-07 07:32:56" 1086 | }, 1087 | { 1088 | "name": "sebastian/global-state", 1089 | "version": "dev-master", 1090 | "source": { 1091 | "type": "git", 1092 | "url": "https://github.com/sebastianbergmann/global-state.git", 1093 | "reference": "1882b954f483d44095e72b40841472a22da91d4f" 1094 | }, 1095 | "dist": { 1096 | "type": "zip", 1097 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/1882b954f483d44095e72b40841472a22da91d4f", 1098 | "reference": "1882b954f483d44095e72b40841472a22da91d4f", 1099 | "shasum": "" 1100 | }, 1101 | "require": { 1102 | "php": "^7.0" 1103 | }, 1104 | "require-dev": { 1105 | "phpunit/phpunit": "^6.0" 1106 | }, 1107 | "suggest": { 1108 | "ext-uopz": "*" 1109 | }, 1110 | "type": "library", 1111 | "extra": { 1112 | "branch-alias": { 1113 | "dev-master": "2.0-dev" 1114 | } 1115 | }, 1116 | "autoload": { 1117 | "classmap": [ 1118 | "src/" 1119 | ] 1120 | }, 1121 | "notification-url": "https://packagist.org/downloads/", 1122 | "license": [ 1123 | "BSD-3-Clause" 1124 | ], 1125 | "authors": [ 1126 | { 1127 | "name": "Sebastian Bergmann", 1128 | "email": "sebastian@phpunit.de" 1129 | } 1130 | ], 1131 | "description": "Snapshotting of global state", 1132 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1133 | "keywords": [ 1134 | "global state" 1135 | ], 1136 | "time": "2017-03-07 07:33:59" 1137 | }, 1138 | { 1139 | "name": "sebastian/object-enumerator", 1140 | "version": "dev-master", 1141 | "source": { 1142 | "type": "git", 1143 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1144 | "reference": "31dd3379d16446c5d86dec32ab1ad1f378581ad8" 1145 | }, 1146 | "dist": { 1147 | "type": "zip", 1148 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/31dd3379d16446c5d86dec32ab1ad1f378581ad8", 1149 | "reference": "31dd3379d16446c5d86dec32ab1ad1f378581ad8", 1150 | "shasum": "" 1151 | }, 1152 | "require": { 1153 | "php": "^7.0", 1154 | "sebastian/object-reflector": "^1.0", 1155 | "sebastian/recursion-context": "^3.0" 1156 | }, 1157 | "require-dev": { 1158 | "phpunit/phpunit": "^6.0" 1159 | }, 1160 | "type": "library", 1161 | "extra": { 1162 | "branch-alias": { 1163 | "dev-master": "3.0.x-dev" 1164 | } 1165 | }, 1166 | "autoload": { 1167 | "classmap": [ 1168 | "src/" 1169 | ] 1170 | }, 1171 | "notification-url": "https://packagist.org/downloads/", 1172 | "license": [ 1173 | "BSD-3-Clause" 1174 | ], 1175 | "authors": [ 1176 | { 1177 | "name": "Sebastian Bergmann", 1178 | "email": "sebastian@phpunit.de" 1179 | } 1180 | ], 1181 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1182 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1183 | "time": "2017-03-12 15:17:29" 1184 | }, 1185 | { 1186 | "name": "sebastian/object-reflector", 1187 | "version": "dev-master", 1188 | "source": { 1189 | "type": "git", 1190 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 1191 | "reference": "773f97c67f28de00d397be301821b06708fca0be" 1192 | }, 1193 | "dist": { 1194 | "type": "zip", 1195 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", 1196 | "reference": "773f97c67f28de00d397be301821b06708fca0be", 1197 | "shasum": "" 1198 | }, 1199 | "require": { 1200 | "php": "^7.0" 1201 | }, 1202 | "require-dev": { 1203 | "phpunit/phpunit": "^6.0" 1204 | }, 1205 | "type": "library", 1206 | "extra": { 1207 | "branch-alias": { 1208 | "dev-master": "1.1-dev" 1209 | } 1210 | }, 1211 | "autoload": { 1212 | "classmap": [ 1213 | "src/" 1214 | ] 1215 | }, 1216 | "notification-url": "https://packagist.org/downloads/", 1217 | "license": [ 1218 | "BSD-3-Clause" 1219 | ], 1220 | "authors": [ 1221 | { 1222 | "name": "Sebastian Bergmann", 1223 | "email": "sebastian@phpunit.de" 1224 | } 1225 | ], 1226 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 1227 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 1228 | "time": "2017-03-29 09:07:27" 1229 | }, 1230 | { 1231 | "name": "sebastian/recursion-context", 1232 | "version": "dev-master", 1233 | "source": { 1234 | "type": "git", 1235 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1236 | "reference": "a0e54bc9bf04e2c5b302236984cebc277631f0f1" 1237 | }, 1238 | "dist": { 1239 | "type": "zip", 1240 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/a0e54bc9bf04e2c5b302236984cebc277631f0f1", 1241 | "reference": "a0e54bc9bf04e2c5b302236984cebc277631f0f1", 1242 | "shasum": "" 1243 | }, 1244 | "require": { 1245 | "php": "^7.0" 1246 | }, 1247 | "require-dev": { 1248 | "phpunit/phpunit": "^6.0" 1249 | }, 1250 | "type": "library", 1251 | "extra": { 1252 | "branch-alias": { 1253 | "dev-master": "3.0.x-dev" 1254 | } 1255 | }, 1256 | "autoload": { 1257 | "classmap": [ 1258 | "src/" 1259 | ] 1260 | }, 1261 | "notification-url": "https://packagist.org/downloads/", 1262 | "license": [ 1263 | "BSD-3-Clause" 1264 | ], 1265 | "authors": [ 1266 | { 1267 | "name": "Jeff Welch", 1268 | "email": "whatthejeff@gmail.com" 1269 | }, 1270 | { 1271 | "name": "Sebastian Bergmann", 1272 | "email": "sebastian@phpunit.de" 1273 | }, 1274 | { 1275 | "name": "Adam Harvey", 1276 | "email": "aharvey@php.net" 1277 | } 1278 | ], 1279 | "description": "Provides functionality to recursively process PHP variables", 1280 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1281 | "time": "2017-03-07 15:09:59" 1282 | }, 1283 | { 1284 | "name": "sebastian/resource-operations", 1285 | "version": "dev-master", 1286 | "source": { 1287 | "type": "git", 1288 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1289 | "reference": "fadc83f7c41fb2924e542635fea47ae546816ece" 1290 | }, 1291 | "dist": { 1292 | "type": "zip", 1293 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/fadc83f7c41fb2924e542635fea47ae546816ece", 1294 | "reference": "fadc83f7c41fb2924e542635fea47ae546816ece", 1295 | "shasum": "" 1296 | }, 1297 | "require": { 1298 | "php": ">=5.6.0" 1299 | }, 1300 | "type": "library", 1301 | "extra": { 1302 | "branch-alias": { 1303 | "dev-master": "1.0.x-dev" 1304 | } 1305 | }, 1306 | "autoload": { 1307 | "classmap": [ 1308 | "src/" 1309 | ] 1310 | }, 1311 | "notification-url": "https://packagist.org/downloads/", 1312 | "license": [ 1313 | "BSD-3-Clause" 1314 | ], 1315 | "authors": [ 1316 | { 1317 | "name": "Sebastian Bergmann", 1318 | "email": "sebastian@phpunit.de" 1319 | } 1320 | ], 1321 | "description": "Provides a list of PHP built-in functions that operate on resources", 1322 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1323 | "time": "2016-10-03 07:43:09" 1324 | }, 1325 | { 1326 | "name": "sebastian/version", 1327 | "version": "dev-master", 1328 | "source": { 1329 | "type": "git", 1330 | "url": "https://github.com/sebastianbergmann/version.git", 1331 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" 1332 | }, 1333 | "dist": { 1334 | "type": "zip", 1335 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", 1336 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", 1337 | "shasum": "" 1338 | }, 1339 | "require": { 1340 | "php": ">=5.6" 1341 | }, 1342 | "type": "library", 1343 | "extra": { 1344 | "branch-alias": { 1345 | "dev-master": "2.0.x-dev" 1346 | } 1347 | }, 1348 | "autoload": { 1349 | "classmap": [ 1350 | "src/" 1351 | ] 1352 | }, 1353 | "notification-url": "https://packagist.org/downloads/", 1354 | "license": [ 1355 | "BSD-3-Clause" 1356 | ], 1357 | "authors": [ 1358 | { 1359 | "name": "Sebastian Bergmann", 1360 | "email": "sebastian@phpunit.de", 1361 | "role": "lead" 1362 | } 1363 | ], 1364 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1365 | "homepage": "https://github.com/sebastianbergmann/version", 1366 | "time": "2016-10-03 07:35:21" 1367 | }, 1368 | { 1369 | "name": "webmozart/assert", 1370 | "version": "dev-master", 1371 | "source": { 1372 | "type": "git", 1373 | "url": "https://github.com/webmozart/assert.git", 1374 | "reference": "4a8bf11547e139e77b651365113fc12850c43d9a" 1375 | }, 1376 | "dist": { 1377 | "type": "zip", 1378 | "url": "https://api.github.com/repos/webmozart/assert/zipball/4a8bf11547e139e77b651365113fc12850c43d9a", 1379 | "reference": "4a8bf11547e139e77b651365113fc12850c43d9a", 1380 | "shasum": "" 1381 | }, 1382 | "require": { 1383 | "php": "^5.3.3 || ^7.0" 1384 | }, 1385 | "require-dev": { 1386 | "phpunit/phpunit": "^4.6", 1387 | "sebastian/version": "^1.0.1" 1388 | }, 1389 | "type": "library", 1390 | "extra": { 1391 | "branch-alias": { 1392 | "dev-master": "1.3-dev" 1393 | } 1394 | }, 1395 | "autoload": { 1396 | "psr-4": { 1397 | "Webmozart\\Assert\\": "src/" 1398 | } 1399 | }, 1400 | "notification-url": "https://packagist.org/downloads/", 1401 | "license": [ 1402 | "MIT" 1403 | ], 1404 | "authors": [ 1405 | { 1406 | "name": "Bernhard Schussek", 1407 | "email": "bschussek@gmail.com" 1408 | } 1409 | ], 1410 | "description": "Assertions to validate method input/output with nice error messages.", 1411 | "keywords": [ 1412 | "assert", 1413 | "check", 1414 | "validate" 1415 | ], 1416 | "time": "2016-11-23 20:04:41" 1417 | } 1418 | ], 1419 | "aliases": [], 1420 | "minimum-stability": "dev", 1421 | "stability-flags": [], 1422 | "prefer-stable": false, 1423 | "prefer-lowest": false, 1424 | "platform": { 1425 | "php": ">=7.0", 1426 | "ext-reflection": "*" 1427 | }, 1428 | "platform-dev": [] 1429 | } 1430 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | ./tests 10 | 11 | 12 | 13 | 14 | ./src 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/BuiltInTypes.php: -------------------------------------------------------------------------------- 1 | getParameters() as $parameterReflection) { 67 | $parameters[] = ParameterType::createFromReflectionParameter($parameterReflection, $flags); 68 | } 69 | 70 | return new CallbackType($returnType, ...$parameters); 71 | } 72 | 73 | public function __construct(ReturnType $returnType, ParameterType ...$parameters) 74 | { 75 | $this->returnType = $returnType; 76 | $this->parameters = $parameters; 77 | } 78 | 79 | /** 80 | * @param callable $callable 81 | * @return bool 82 | */ 83 | public function isSatisfiedBy($callable) 84 | { 85 | try { 86 | $candidate = self::reflectCallable($callable); 87 | } catch (\ReflectionException $e) { 88 | throw new InvalidCallbackException('Failed to reflect the supplied callable', 0, $e); 89 | } 90 | 91 | $byRef = $candidate->returnsReference(); 92 | $returnType = $candidate->getReturnType(); 93 | 94 | if ($returnType !== null) { 95 | $typeName = (string)$returnType; 96 | $nullable = $returnType->allowsNull(); 97 | } else { 98 | $typeName = null; 99 | $nullable = false; 100 | } 101 | 102 | if (!$this->returnType->isSatisfiedBy($typeName, $nullable, $byRef)) { 103 | return false; 104 | } 105 | 106 | $last = null; 107 | 108 | foreach ($candidate->getParameters() as $position => $parameter) { 109 | $byRef = $parameter->isPassedByReference(); 110 | 111 | if ($parameter->hasType()) { 112 | $type = $parameter->getType(); 113 | $typeName = (string)$type; 114 | $nullable = $type->allowsNull(); 115 | } else { 116 | $typeName = null; 117 | $nullable = false; 118 | } 119 | 120 | // Parameters that exist in the prototype must always be satisfied directly 121 | if (isset($this->parameters[$position])) { 122 | if (!$this->parameters[$position]->isSatisfiedBy($typeName, $nullable, $byRef)) { 123 | return false; 124 | } 125 | 126 | $last = $this->parameters[$position]; 127 | continue; 128 | } 129 | 130 | // Candidates can accept additional args that are not in the prototype as long as they are not mandatory 131 | if (!$parameter->isOptional() && !$parameter->isVariadic()) { 132 | return false; 133 | } 134 | 135 | // If the last arg of the prototype is variadic, any additional args the candidate accepts must satisfy it 136 | if ($last !== null && $last->isVariadic && !$last->isSatisfiedBy($typeName, $nullable, $byRef)) { 137 | return false; 138 | } 139 | } 140 | 141 | return true; 142 | } 143 | 144 | /** 145 | * @return string 146 | */ 147 | public function __toString() 148 | { 149 | $string = 'function '; 150 | 151 | if ($this->returnType->isByReference) { 152 | $string .= '& '; 153 | } 154 | 155 | $string .= '( '; 156 | 157 | for ($i = $o = 0, $l = count($this->parameters) - 1; $i < $l; $i++) { 158 | $string .= $this->parameters[$i]; 159 | 160 | if (!$o && !($this->parameters[$i + 1]->isOptional)) { 161 | $string .= ', '; 162 | continue; 163 | } 164 | 165 | $string .= ' [, '; 166 | $o++; 167 | } 168 | 169 | if (isset($this->parameters[$l])) { 170 | $string .= $this->parameters[$i] . ' '; 171 | } 172 | 173 | if ($o) { 174 | $string .= str_repeat(']', $o) . ' '; 175 | } 176 | 177 | $string .= ')'; 178 | 179 | if ($this->returnType->typeName !== null) { 180 | $string .= ' : ' . $this->returnType; 181 | } 182 | 183 | return $string; 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /src/InvalidCallbackException.php: -------------------------------------------------------------------------------- 1 | true, 17 | BuiltInTypes::INT => true, 18 | BuiltInTypes::FLOAT => true, 19 | BuiltInTypes::BOOL => true, 20 | BuiltInTypes::ARRAY => true, 21 | BuiltInTypes::CALLABLE => true, 22 | BuiltInTypes::VOID => true, 23 | BuiltInTypes::ITERABLE => true, 24 | ]; 25 | 26 | /** 27 | * Lookup table of scalar types 28 | */ 29 | private static $scalarTypes = [ 30 | BuiltInTypes::STRING => true, 31 | BuiltInTypes::INT => true, 32 | BuiltInTypes::FLOAT => true, 33 | BuiltInTypes::BOOL => true, 34 | ]; 35 | 36 | /** 37 | * @param string $superTypeName 38 | * @param string $subTypeName 39 | * @return bool 40 | */ 41 | public static function isWeakScalarMatch($superTypeName, $subTypeName) 42 | { 43 | // Nothing else satisfies array, callable, void or iterable 44 | if (!isset(self::$scalarTypes[$superTypeName])) { 45 | return false; 46 | } 47 | 48 | // Scalars can all cast to each other 49 | if (isset(self::$scalarTypes[$subTypeName])) { 50 | return true; 51 | } 52 | 53 | // Classes with __toString() satisfy string 54 | if ($superTypeName === BuiltInTypes::STRING && \method_exists($subTypeName, '__toString')) { 55 | return true; 56 | } 57 | 58 | return false; 59 | } 60 | 61 | /** 62 | * @param string|null $superTypeName 63 | * @param bool $superTypeNullable 64 | * @param string|null $subTypeName 65 | * @param bool $subTypeNullable 66 | * @param bool $weak 67 | * @return bool 68 | */ 69 | public static function isMatch($superTypeName, $superTypeNullable, $subTypeName, $subTypeNullable, $weak) 70 | { 71 | // If the super type is unspecified, anything is a match 72 | if ($superTypeName === null) { 73 | return true; 74 | } 75 | 76 | // If the sub type is unspecified, nothing is a match 77 | if ($subTypeName === null) { 78 | return false; 79 | } 80 | 81 | $superTypeName = (string)$superTypeName; 82 | $subTypeName = (string)$subTypeName; 83 | 84 | // Sub type cannot be nullable unless the super type is as well 85 | if ($subTypeNullable && !$superTypeNullable) { 86 | // nullable void doesn't really make sense but for completeness... 87 | return $superTypeName === BuiltInTypes::VOID && $subTypeName === BuiltInTypes::VOID; 88 | } 89 | 90 | // If the string is an exact match it's definitely acceptable 91 | if ($superTypeName === $subTypeName) { 92 | return true; 93 | } 94 | 95 | // Check iterable 96 | if ($superTypeName === BuiltInTypes::ITERABLE) { 97 | return $subTypeName === BuiltInTypes::ARRAY 98 | || $subTypeName === \Traversable::class 99 | || \is_subclass_of($subTypeName, \Traversable::class); 100 | } 101 | 102 | // Check callable 103 | if ($superTypeName === BuiltInTypes::CALLABLE) { 104 | return $subTypeName === \Closure::class 105 | || \method_exists($subTypeName, '__invoke') 106 | || \is_subclass_of($subTypeName, \Closure::class); 107 | } 108 | 109 | // If the super type is built-in, check whether casting rules can succeed 110 | if (isset(self::$builtInTypes[$superTypeName])) { 111 | // Fail immediately in strict mode 112 | return $weak && self::isWeakScalarMatch($superTypeName, $subTypeName); 113 | } 114 | 115 | // We now know the super type is not built-in and there's no string match, sub type must not be built-in 116 | if (isset(self::$builtInTypes[$subTypeName])) { 117 | return false; 118 | } 119 | 120 | return \is_subclass_of($subTypeName, $superTypeName); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/ParameterType.php: -------------------------------------------------------------------------------- 1 | getName(); 59 | 60 | if ($reflection->isPassedByReference()) { 61 | $flags |= self::REFERENCE; 62 | } 63 | 64 | if ($reflection->isVariadic()) { 65 | $flags |= self::VARIADIC; 66 | } 67 | 68 | if ($reflection->isOptional()) { 69 | $flags |= self::OPTIONAL; 70 | } 71 | 72 | $typeName = null; 73 | $typeReflection = $reflection->getType(); 74 | 75 | if ($typeReflection !== null) { 76 | $typeName = (string)$typeReflection; 77 | 78 | if ($typeReflection->allowsNull()) { 79 | $flags |= self::NULLABLE; 80 | } 81 | } 82 | 83 | return new self($parameterName, $typeName, $flags); 84 | } 85 | 86 | /** 87 | * @param string $parameterName 88 | * @param string|null $typeName 89 | * @param int $flags 90 | */ 91 | public function __construct($parameterName, $typeName = null, $flags = self::CONTRAVARIANT) 92 | { 93 | $flags = (int)$flags; 94 | 95 | parent::__construct($typeName, $flags, $flags & self::COVARIANT, $flags & self::CONTRAVARIANT); 96 | 97 | $this->parameterName = (string)$parameterName; 98 | $this->isOptional = (bool)($flags & self::OPTIONAL); 99 | $this->isVariadic = (bool)($flags & self::VARIADIC); 100 | } 101 | 102 | /** 103 | * @return string 104 | */ 105 | public function __toString() 106 | { 107 | $string = ''; 108 | 109 | if ($this->typeName !== null) { 110 | if ($this->isNullable) { 111 | $string .= '?'; 112 | } 113 | 114 | $string .= $this->typeName . ' '; 115 | } 116 | 117 | if ($this->isByReference) { 118 | $string .= '&'; 119 | } 120 | 121 | if ($this->isVariadic) { 122 | $string .= '...'; 123 | } 124 | 125 | return $string . '$' . $this->parameterName; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/ReturnType.php: -------------------------------------------------------------------------------- 1 | returnsReference()) { 26 | $flags |= self::REFERENCE; 27 | } 28 | 29 | $typeName = null; 30 | $typeReflection = $reflection->getReturnType(); 31 | 32 | if ($typeReflection !== null) { 33 | $typeName = (string)$typeReflection; 34 | 35 | if ($typeReflection->allowsNull()) { 36 | $flags |= self::NULLABLE; 37 | } 38 | } 39 | 40 | return new self($typeName, $flags); 41 | } 42 | 43 | /** 44 | * @param string|null $typeName 45 | * @param int $flags 46 | */ 47 | public function __construct($typeName = null, $flags = self::COVARIANT) 48 | { 49 | $flags = (int)$flags; 50 | 51 | parent::__construct($typeName, $flags, $flags & self::COVARIANT, $flags & self::CONTRAVARIANT); 52 | } 53 | 54 | /** 55 | * @return string 56 | */ 57 | public function __toString() 58 | { 59 | return $this->isNullable && $this->typeName !== null 60 | ? '?' . $this->typeName 61 | : (string)$this->typeName; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Type.php: -------------------------------------------------------------------------------- 1 | =7.1) or with a default value of null 14 | */ 15 | const NULLABLE = 0x02; 16 | 17 | /** 18 | * Reference types must always match 19 | */ 20 | const REFERENCE = 0x04; 21 | 22 | /** 23 | * The name of the type 24 | * 25 | * @var string|null 26 | */ 27 | public $typeName; 28 | 29 | /** 30 | * Whether the type is nullable 31 | * 32 | * @var bool 33 | */ 34 | public $isNullable; 35 | 36 | /** 37 | * Whether the type is passed by reference 38 | * 39 | * @var bool 40 | */ 41 | public $isByReference; 42 | 43 | /** 44 | * Whether the type should be matched in weak mode 45 | * 46 | * @var bool 47 | */ 48 | public $isWeak; 49 | 50 | /** 51 | * Whether the type allows covariant matches 52 | * 53 | * @var bool 54 | */ 55 | public $allowsCovariance; 56 | 57 | /** 58 | * Whether the type allows contravariant matches 59 | * 60 | * @var bool 61 | */ 62 | public $allowsContravariance; 63 | 64 | /** 65 | * @param string|null $typeName 66 | * @param int $flags 67 | * @param bool $allowsCovariance 68 | * @param bool $allowsContravariance 69 | */ 70 | protected function __construct($typeName, $flags, $allowsCovariance, $allowsContravariance) 71 | { 72 | $this->typeName = $typeName !== null 73 | ? (string)$typeName 74 | : null; 75 | 76 | $this->isNullable = (bool)($flags & self::NULLABLE); 77 | $this->isByReference = (bool)($flags & self::REFERENCE); 78 | $this->isWeak = (bool)($flags & self::WEAK); 79 | $this->allowsCovariance = (bool)$allowsCovariance; 80 | $this->allowsContravariance = (bool)$allowsContravariance; 81 | } 82 | 83 | /** 84 | * Whether the type will be satisfied by the specified type name, nullability and by-reference combination 85 | * 86 | * @param string|null $typeName 87 | * @param bool $nullable 88 | * @param bool $byReference 89 | * @return bool 90 | */ 91 | public function isSatisfiedBy($typeName, $nullable, $byReference) 92 | { 93 | // By-ref must always be the same 94 | if ($byReference xor $this->isByReference) { 95 | return false; 96 | } 97 | 98 | // Candidate is exact match to prototype 99 | if ($typeName === $this->typeName && $nullable === $this->isNullable) { 100 | return true; 101 | } 102 | 103 | // Test for a covariant match 104 | if ($this->allowsCovariance 105 | && MatchTester::isMatch($this->typeName, $this->isNullable, $typeName, $nullable, $this->isWeak)) { 106 | return true; 107 | } 108 | 109 | // Test for a contravariant match 110 | if ($this->allowsContravariance 111 | && MatchTester::isMatch($typeName, $nullable, $this->typeName, $this->isNullable, $this->isWeak)) { 112 | return true; 113 | } 114 | 115 | // In weak mode, allow castable scalars as long as nullability matches (invariant) 116 | return $this->isWeak 117 | && $nullable === $this->isNullable 118 | && MatchTester::isWeakScalarMatch($typeName, $this->typeName); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /tests/Fixtures/ClassImplementingInvoke.php: -------------------------------------------------------------------------------- 1 | assertTrue(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, ClassImplementingIteratorAggregate::class, false, false)); 18 | } 19 | 20 | public function test_ClassImplementingTraversableSubType_Match_IterableSuperType_WeakMode() 21 | { 22 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, ClassImplementingIteratorAggregate::class, false, true)); 23 | } 24 | 25 | public function test_NullableClassImplementingTraversableSubType_NotMatch_IterableSuperType_StrictMode() 26 | { 27 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, ClassImplementingIteratorAggregate::class, true, false)); 28 | } 29 | 30 | public function test_NullableClassImplementingTraversableSubType_NotMatch_IterableSuperType_WeakMode() 31 | { 32 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, ClassImplementingIteratorAggregate::class, true, true)); 33 | } 34 | 35 | public function test_ClassImplementingTraversableSubType_Match_NullableIterableSuperType_StrictMode() 36 | { 37 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, ClassImplementingIteratorAggregate::class, false, false)); 38 | } 39 | 40 | public function test_ClassImplementingTraversableSubType_Match_NullableIterableSuperType_WeakMode() 41 | { 42 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, ClassImplementingIteratorAggregate::class, false, true)); 43 | } 44 | 45 | public function test_NullableClassImplementingTraversableSubType_Match_NullableIterableSuperType_StrictMode() 46 | { 47 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, ClassImplementingIteratorAggregate::class, true, false)); 48 | } 49 | 50 | public function test_NullableClassImplementingTraversableSubType_Match_NullableIterableSuperType_WeakMode() 51 | { 52 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, ClassImplementingIteratorAggregate::class, true, true)); 53 | } 54 | 55 | public function test_ArraySubType_Match_IterableSuperType_StrictMode() 56 | { 57 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::ARRAY, false, false)); 58 | } 59 | 60 | public function test_ArraySubType_Match_IterableSuperType_WeakMode() 61 | { 62 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::ARRAY, false, true)); 63 | } 64 | 65 | public function test_NullableArraySubType_NotMatch_IterableSuperType_StrictMode() 66 | { 67 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::ARRAY, true, false)); 68 | } 69 | 70 | public function test_NullableArraySubType_NotMatch_IterableSuperType_WeakMode() 71 | { 72 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::ARRAY, true, true)); 73 | } 74 | 75 | public function test_ArraySubType_Match_NullableIterableSuperType_StrictMode() 76 | { 77 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::ARRAY, false, false)); 78 | } 79 | 80 | public function test_ArraySubType_Match_NullableIterableSuperType_WeakMode() 81 | { 82 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::ARRAY, false, true)); 83 | } 84 | 85 | public function test_NullableArraySubType_Match_NullableIterableSuperType_StrictMode() 86 | { 87 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::ARRAY, true, false)); 88 | } 89 | 90 | public function test_NullableArraySubType_Match_NullableIterableSuperType_WeakMode() 91 | { 92 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::ARRAY, true, true)); 93 | } 94 | 95 | public function test_ClassNotImplementingTraversableSubType_NotMatch_IterableSuperType_StrictMode() 96 | { 97 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, ClassImplementingNothing::class, false, false)); 98 | } 99 | 100 | public function test_ClassNotImplementingTraversableSubType_NotMatch_IterableSuperType_WeakMode() 101 | { 102 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, ClassImplementingNothing::class, false, true)); 103 | } 104 | 105 | public function test_NullableClassNotImplementingTraversableSubType_NotMatch_IterableSuperType_StrictMode() 106 | { 107 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, ClassImplementingNothing::class, true, false)); 108 | } 109 | 110 | public function test_NullableClassNotImplementingTraversableSubType_NotMatch_IterableSuperType_WeakMode() 111 | { 112 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, ClassImplementingNothing::class, true, true)); 113 | } 114 | 115 | public function test_ClassNotImplementingTraversableSubType_NotMatch_NullableIterableSuperType_StrictMode() 116 | { 117 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, ClassImplementingNothing::class, false, false)); 118 | } 119 | 120 | public function test_ClassNotImplementingTraversableSubType_NotMatch_NullableIterableSuperType_WeakMode() 121 | { 122 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, ClassImplementingNothing::class, false, true)); 123 | } 124 | 125 | public function test_NullableClassNotImplementingTraversableSubType_NotMatch_NullableIterableSuperType_StrictMode() 126 | { 127 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, ClassImplementingNothing::class, true, false)); 128 | } 129 | 130 | public function test_NullableClassNotImplementingTraversableSubType_NotMatch_NullableIterableSuperType_WeakMode() 131 | { 132 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, ClassImplementingNothing::class, true, true)); 133 | } 134 | 135 | public function test_ClassImplementingToStringSubType_NotMatch_StringSuperType_StrictMode() 136 | { 137 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, ClassImplementingIteratorAggregate::class, false, false)); 138 | } 139 | 140 | public function test_ClassImplementingToStringSubType_Match_StringSuperType_WeakMode() 141 | { 142 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, false, ClassImplementingToString::class, false, true)); 143 | } 144 | 145 | public function test_NullableClassImplementingToStringSubType_NotMatch_StringSuperType_StrictMode() 146 | { 147 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, ClassImplementingToString::class, true, false)); 148 | } 149 | 150 | public function test_NullableClassImplementingToStringSubType_NotMatch_StringSuperType_WeakMode() 151 | { 152 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, ClassImplementingToString::class, true, true)); 153 | } 154 | 155 | public function test_ClassImplementingToStringSubType_NotMatch_NullableStringSuperType_StrictMode() 156 | { 157 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, true, ClassImplementingToString::class, false, false)); 158 | } 159 | 160 | public function test_ClassImplementingToStringSubType_Match_NullableStringSuperType_WeakMode() 161 | { 162 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, true, ClassImplementingToString::class, false, true)); 163 | } 164 | 165 | public function test_NullableClassImplementingToStringSubType_NotMatch_NullableStringSuperType_StrictMode() 166 | { 167 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, true, ClassImplementingToString::class, true, false)); 168 | } 169 | 170 | public function test_NullableClassImplementingToStringSubType_Match_NullableStringSuperType_WeakMode() 171 | { 172 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, true, ClassImplementingToString::class, true, true)); 173 | } 174 | 175 | public function test_ClassNotImplementingToStringSubType_NotMatch_StringSuperType_StrictMode() 176 | { 177 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, ClassImplementingNothing::class, false, false)); 178 | } 179 | 180 | public function test_ClassNotImplementingToStringSubType_NotMatch_StringSuperType_WeakMode() 181 | { 182 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, ClassImplementingNothing::class, false, true)); 183 | } 184 | 185 | public function test_NullableClassNotImplementingToStringSubType_NotMatch_StringSuperType_StrictMode() 186 | { 187 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, ClassImplementingNothing::class, true, false)); 188 | } 189 | 190 | public function test_NullableClassNotImplementingToStringSubType_NotMatch_StringSuperType_WeakMode() 191 | { 192 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, ClassImplementingNothing::class, true, true)); 193 | } 194 | 195 | public function test_ClassNotImplementingToStringSubType_NotMatch_NullableStringSuperType_StrictMode() 196 | { 197 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, true, ClassImplementingNothing::class, false, false)); 198 | } 199 | 200 | public function test_ClassNotImplementingToStringSubType_NotMatch_NullableStringSuperType_WeakMode() 201 | { 202 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, true, ClassImplementingNothing::class, false, true)); 203 | } 204 | 205 | public function test_NullableClassNotImplementingToStringSubType_NotMatch_NullableStringSuperType_StrictMode() 206 | { 207 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, true, ClassImplementingNothing::class, true, false)); 208 | } 209 | 210 | public function test_NullableClassNotImplementingToStringSubType_NotMatch_NullableStringSuperType_WeakMode() 211 | { 212 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, true, ClassImplementingNothing::class, true, true)); 213 | } 214 | 215 | public function test_ClassImplementingInvokeSubType_NotMatch_CallableSuperType_StrictMode() 216 | { 217 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, ClassImplementingIteratorAggregate::class, false, false)); 218 | } 219 | 220 | public function test_ClassImplementingInvokeSubType_Match_CallableSuperType_WeakMode() 221 | { 222 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, ClassImplementingInvoke::class, false, true)); 223 | } 224 | 225 | public function test_NullableClassImplementingInvokeSubType_NotMatch_CallableSuperType_StrictMode() 226 | { 227 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, ClassImplementingInvoke::class, true, false)); 228 | } 229 | 230 | public function test_NullableClassImplementingInvokeSubType_NotMatch_CallableSuperType_WeakMode() 231 | { 232 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, ClassImplementingInvoke::class, true, true)); 233 | } 234 | 235 | public function test_ClassImplementingInvokeSubType_Match_NullableCallableSuperType_StrictMode() 236 | { 237 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, ClassImplementingInvoke::class, false, false)); 238 | } 239 | 240 | public function test_ClassImplementingInvokeSubType_Match_NullableCallableSuperType_WeakMode() 241 | { 242 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, ClassImplementingInvoke::class, false, true)); 243 | } 244 | 245 | public function test_NullableClassImplementingInvokeSubType_Match_NullableCallableSuperType_StrictMode() 246 | { 247 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, ClassImplementingInvoke::class, true, false)); 248 | } 249 | 250 | public function test_NullableClassImplementingInvokeSubType_Match_NullableCallableSuperType_WeakMode() 251 | { 252 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, ClassImplementingInvoke::class, true, true)); 253 | } 254 | 255 | public function test_ClosureSubType_Match_CallableSuperType_StrictMode() 256 | { 257 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, \Closure::class, false, false)); 258 | } 259 | 260 | public function test_ClosureSubType_Match_CallableSuperType_WeakMode() 261 | { 262 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, \Closure::class, false, true)); 263 | } 264 | 265 | public function test_NullableClosureSubType_NotMatch_CallableSuperType_StrictMode() 266 | { 267 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, \Closure::class, true, false)); 268 | } 269 | 270 | public function test_NullableClosureSubType_NotMatch_CallableSuperType_WeakMode() 271 | { 272 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, \Closure::class, true, true)); 273 | } 274 | 275 | public function test_ClosureSubType_Match_NullableCallableSuperType_StrictMode() 276 | { 277 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, \Closure::class, false, false)); 278 | } 279 | 280 | public function test_ClosureSubType_Match_NullableCallableSuperType_WeakMode() 281 | { 282 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, \Closure::class, false, true)); 283 | } 284 | 285 | public function test_NullableClosureSubType_Match_NullableCallableSuperType_StrictMode() 286 | { 287 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, \Closure::class, true, false)); 288 | } 289 | 290 | public function test_NullableClosureSubType_Match_NullableCallableSuperType_WeakMode() 291 | { 292 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, \Closure::class, true, true)); 293 | } 294 | 295 | public function test_ClassNotImplementingInvokeOrClosureSubType_NotMatch_CallableSuperType_StrictMode() 296 | { 297 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, ClassImplementingNothing::class, false, false)); 298 | } 299 | 300 | public function test_ClassNotImplementingInvokeOrClosureSubType_NotMatch_CallableSuperType_WeakMode() 301 | { 302 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, ClassImplementingNothing::class, false, true)); 303 | } 304 | 305 | public function test_NullableClassNotImplementingInvokeOrClosureSubType_NotMatch_CallableSuperType_StrictMode() 306 | { 307 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, ClassImplementingNothing::class, true, false)); 308 | } 309 | 310 | public function test_NullableClassNotImplementingInvokeOrClosureSubType_NotMatch_CallableSuperType_WeakMode() 311 | { 312 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, ClassImplementingNothing::class, true, true)); 313 | } 314 | 315 | public function test_ClassNotImplementingInvokeOrClosureSubType_NotMatch_NullableCallableSuperType_StrictMode() 316 | { 317 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, ClassImplementingNothing::class, false, false)); 318 | } 319 | 320 | public function test_ClassNotImplementingInvokeOrClosureSubType_NotMatch_NullableCallableSuperType_WeakMode() 321 | { 322 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, ClassImplementingNothing::class, false, true)); 323 | } 324 | 325 | public function test_NullableClassNotImplementingInvokeOrClosureSubType_NotMatch_NullableCallableSuperType_StrictMode() 326 | { 327 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, ClassImplementingNothing::class, true, false)); 328 | } 329 | 330 | public function test_NullableClassNotImplementingInvokeOrClosureSubType_NotMatch_NullableCallableSuperType_WeakMode() 331 | { 332 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, ClassImplementingNothing::class, true, true)); 333 | } 334 | 335 | public function test_NotVoidSubType_NotMatch_VoidSuperType_WeakMode() 336 | { 337 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::ARRAY, false, false)); 338 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::ARRAY, true, false)); 339 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::ARRAY, false, false)); 340 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::ARRAY, true, false)); 341 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::BOOL, false, false)); 342 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::BOOL, true, false)); 343 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::BOOL, false, false)); 344 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::BOOL, true, false)); 345 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::CALLABLE, false, false)); 346 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::CALLABLE, true, false)); 347 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::CALLABLE, false, false)); 348 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::CALLABLE, true, false)); 349 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::FLOAT, false, false)); 350 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::FLOAT, true, false)); 351 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::FLOAT, false, false)); 352 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::FLOAT, true, false)); 353 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::INT, false, false)); 354 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::INT, true, false)); 355 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::INT, false, false)); 356 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::INT, true, false)); 357 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::ITERABLE, false, false)); 358 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::ITERABLE, true, false)); 359 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::ITERABLE, false, false)); 360 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::ITERABLE, true, false)); 361 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::STRING, false, false)); 362 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::STRING, true, false)); 363 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::STRING, false, false)); 364 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::STRING, true, false)); 365 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, ClassImplementingNothing::class, false, false)); 366 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, ClassImplementingNothing::class, true, false)); 367 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, ClassImplementingNothing::class, false, false)); 368 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, ClassImplementingNothing::class, true, false)); 369 | } 370 | 371 | public function test_NotVoidSubType_NotMatch_VoidSuperType_StrictMode() 372 | { 373 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::ARRAY, false, true)); 374 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::ARRAY, true, true)); 375 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::ARRAY, false, true)); 376 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::ARRAY, true, true)); 377 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::BOOL, false, true)); 378 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::BOOL, true, true)); 379 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::BOOL, false, true)); 380 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::BOOL, true, true)); 381 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::CALLABLE, false, true)); 382 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::CALLABLE, true, true)); 383 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::CALLABLE, false, true)); 384 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::CALLABLE, true, true)); 385 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::FLOAT, false, true)); 386 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::FLOAT, true, true)); 387 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::FLOAT, false, true)); 388 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::FLOAT, true, true)); 389 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::INT, false, true)); 390 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::INT, true, true)); 391 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::INT, false, true)); 392 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::INT, true, true)); 393 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::ITERABLE, false, true)); 394 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::ITERABLE, true, true)); 395 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::ITERABLE, false, true)); 396 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::ITERABLE, true, true)); 397 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::STRING, false, true)); 398 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::STRING, true, true)); 399 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::STRING, false, true)); 400 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::STRING, true, true)); 401 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, ClassImplementingNothing::class, false, true)); 402 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, ClassImplementingNothing::class, true, true)); 403 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, ClassImplementingNothing::class, false, true)); 404 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, ClassImplementingNothing::class, true, true)); 405 | } 406 | 407 | public function test_VoidSubType_Match_VoidSuperType_WeakMode() 408 | { 409 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::VOID, false, false)); 410 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::VOID, true, false)); 411 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::VOID, false, false)); 412 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::VOID, true, false)); 413 | } 414 | 415 | public function test_VoidSubType_Match_VoidSuperType_StrictMode() 416 | { 417 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::VOID, false, true)); 418 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::VOID, true, true)); 419 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::VOID, false, true)); 420 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::VOID, true, true)); 421 | } 422 | 423 | public function test_ScalarSubTypes_Match_ScalarSuperTypes_WeakMode() 424 | { 425 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, false, BuiltInTypes::STRING, false, true)); 426 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, false, BuiltInTypes::INT, false, true)); 427 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, false, BuiltInTypes::FLOAT, false, true)); 428 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, false, BuiltInTypes::BOOL, false, true)); 429 | 430 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::INT, false, BuiltInTypes::STRING, false, true)); 431 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::INT, false, BuiltInTypes::INT, false, true)); 432 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::INT, false, BuiltInTypes::FLOAT, false, true)); 433 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::INT, false, BuiltInTypes::BOOL, false, true)); 434 | 435 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::FLOAT, false, BuiltInTypes::STRING, false, true)); 436 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::FLOAT, false, BuiltInTypes::INT, false, true)); 437 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::FLOAT, false, BuiltInTypes::FLOAT, false, true)); 438 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::FLOAT, false, BuiltInTypes::BOOL, false, true)); 439 | 440 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::BOOL, false, BuiltInTypes::STRING, false, true)); 441 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::BOOL, false, BuiltInTypes::INT, false, true)); 442 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::BOOL, false, BuiltInTypes::FLOAT, false, true)); 443 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::BOOL, false, BuiltInTypes::BOOL, false, true)); 444 | } 445 | 446 | public function test_ScalarSubTypes_NotMatch_NonScalarBuiltInSuperTypes_WeakMode() 447 | { 448 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, false, BuiltInTypes::STRING, false, true)); 449 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, false, BuiltInTypes::INT, false, true)); 450 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, false, BuiltInTypes::FLOAT, false, true)); 451 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, false, BuiltInTypes::BOOL, false, true)); 452 | 453 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::STRING, false, true)); 454 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::INT, false, true)); 455 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::FLOAT, false, true)); 456 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::BOOL, false, true)); 457 | 458 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, BuiltInTypes::STRING, false, true)); 459 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, BuiltInTypes::INT, false, true)); 460 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, BuiltInTypes::FLOAT, false, true)); 461 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, BuiltInTypes::BOOL, false, true)); 462 | 463 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::STRING, false, true)); 464 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::INT, false, true)); 465 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::FLOAT, false, true)); 466 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::BOOL, false, true)); 467 | } 468 | 469 | public function test_ScalarSubTypes_Match_NullableScalarSuperTypes_WeakMode() 470 | { 471 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, true, BuiltInTypes::STRING, false, true)); 472 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, true, BuiltInTypes::INT, false, true)); 473 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, true, BuiltInTypes::FLOAT, false, true)); 474 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, true, BuiltInTypes::BOOL, false, true)); 475 | 476 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::INT, true, BuiltInTypes::STRING, false, true)); 477 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::INT, true, BuiltInTypes::INT, false, true)); 478 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::INT, true, BuiltInTypes::FLOAT, false, true)); 479 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::INT, true, BuiltInTypes::BOOL, false, true)); 480 | 481 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::FLOAT, true, BuiltInTypes::STRING, false, true)); 482 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::FLOAT, true, BuiltInTypes::INT, false, true)); 483 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::FLOAT, true, BuiltInTypes::FLOAT, false, true)); 484 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::FLOAT, true, BuiltInTypes::BOOL, false, true)); 485 | 486 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::BOOL, true, BuiltInTypes::STRING, false, true)); 487 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::BOOL, true, BuiltInTypes::INT, false, true)); 488 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::BOOL, true, BuiltInTypes::FLOAT, false, true)); 489 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::BOOL, true, BuiltInTypes::BOOL, false, true)); 490 | } 491 | 492 | public function test_ScalarSubTypes_NotMatch_NullableNonScalarBuiltInSuperTypes_WeakMode() 493 | { 494 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, true, BuiltInTypes::STRING, false, true)); 495 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, true, BuiltInTypes::INT, false, true)); 496 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, true, BuiltInTypes::FLOAT, false, true)); 497 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, true, BuiltInTypes::BOOL, false, true)); 498 | 499 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::STRING, false, true)); 500 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::INT, false, true)); 501 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::FLOAT, false, true)); 502 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::BOOL, false, true)); 503 | 504 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, BuiltInTypes::STRING, false, true)); 505 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, BuiltInTypes::INT, false, true)); 506 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, BuiltInTypes::FLOAT, false, true)); 507 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, BuiltInTypes::BOOL, false, true)); 508 | 509 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::STRING, false, true)); 510 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::INT, false, true)); 511 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::FLOAT, false, true)); 512 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::BOOL, false, true)); 513 | } 514 | 515 | public function test_NullableScalarSubTypes_NotMatch_ScalarSuperTypes_WeakMode() 516 | { 517 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, BuiltInTypes::STRING, true, true)); 518 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, BuiltInTypes::INT, true, true)); 519 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, BuiltInTypes::FLOAT, true, true)); 520 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, BuiltInTypes::BOOL, true, true)); 521 | 522 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::INT, false, BuiltInTypes::STRING, true, true)); 523 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::INT, false, BuiltInTypes::INT, true, true)); 524 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::INT, false, BuiltInTypes::FLOAT, true, true)); 525 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::INT, false, BuiltInTypes::BOOL, true, true)); 526 | 527 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::FLOAT, false, BuiltInTypes::STRING, true, true)); 528 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::FLOAT, false, BuiltInTypes::INT, true, true)); 529 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::FLOAT, false, BuiltInTypes::FLOAT, true, true)); 530 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::FLOAT, false, BuiltInTypes::BOOL, true, true)); 531 | 532 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::BOOL, false, BuiltInTypes::STRING, true, true)); 533 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::BOOL, false, BuiltInTypes::INT, true, true)); 534 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::BOOL, false, BuiltInTypes::FLOAT, true, true)); 535 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::BOOL, false, BuiltInTypes::BOOL, true, true)); 536 | } 537 | 538 | public function test_NullableScalarSubTypes_NotMatch_NonScalarBuiltInSuperTypes_WeakMode() 539 | { 540 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, false, BuiltInTypes::STRING, true, true)); 541 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, false, BuiltInTypes::INT, true, true)); 542 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, false, BuiltInTypes::FLOAT, true, true)); 543 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, false, BuiltInTypes::BOOL, true, true)); 544 | 545 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::STRING, true, true)); 546 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::INT, true, true)); 547 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::FLOAT, true, true)); 548 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::BOOL, true, true)); 549 | 550 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, BuiltInTypes::STRING, true, true)); 551 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, BuiltInTypes::INT, true, true)); 552 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, BuiltInTypes::FLOAT, true, true)); 553 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, BuiltInTypes::BOOL, true, true)); 554 | 555 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::STRING, true, true)); 556 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::INT, true, true)); 557 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::FLOAT, true, true)); 558 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::BOOL, true, true)); 559 | } 560 | 561 | public function test_NullableScalarSubTypes_Match_NullableScalarSuperTypes_WeakMode() 562 | { 563 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, true, BuiltInTypes::STRING, true, true)); 564 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, true, BuiltInTypes::INT, true, true)); 565 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, true, BuiltInTypes::FLOAT, true, true)); 566 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, true, BuiltInTypes::BOOL, true, true)); 567 | 568 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::INT, true, BuiltInTypes::STRING, true, true)); 569 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::INT, true, BuiltInTypes::INT, true, true)); 570 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::INT, true, BuiltInTypes::FLOAT, true, true)); 571 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::INT, true, BuiltInTypes::BOOL, true, true)); 572 | 573 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::FLOAT, true, BuiltInTypes::STRING, true, true)); 574 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::FLOAT, true, BuiltInTypes::INT, true, true)); 575 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::FLOAT, true, BuiltInTypes::FLOAT, true, true)); 576 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::FLOAT, true, BuiltInTypes::BOOL, true, true)); 577 | 578 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::BOOL, true, BuiltInTypes::STRING, true, true)); 579 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::BOOL, true, BuiltInTypes::INT, true, true)); 580 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::BOOL, true, BuiltInTypes::FLOAT, true, true)); 581 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::BOOL, true, BuiltInTypes::BOOL, true, true)); 582 | } 583 | 584 | public function test_NullableScalarSubTypes_NotMatch_NullableNonScalarBuiltInSuperTypes_WeakMode() 585 | { 586 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, true, BuiltInTypes::STRING, true, true)); 587 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, true, BuiltInTypes::INT, true, true)); 588 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, true, BuiltInTypes::FLOAT, true, true)); 589 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, true, BuiltInTypes::BOOL, true, true)); 590 | 591 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::STRING, true, true)); 592 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::INT, true, true)); 593 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::FLOAT, true, true)); 594 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::BOOL, true, true)); 595 | 596 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, BuiltInTypes::STRING, true, true)); 597 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, BuiltInTypes::INT, true, true)); 598 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, BuiltInTypes::FLOAT, true, true)); 599 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, BuiltInTypes::BOOL, true, true)); 600 | 601 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::STRING, true, true)); 602 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::INT, true, true)); 603 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::FLOAT, true, true)); 604 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::BOOL, true, true)); 605 | } 606 | 607 | public function test_ScalarSubTypes_InvariantMatch_ScalarSuperTypes_StrictMode() 608 | { 609 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, false, BuiltInTypes::STRING, false, false)); 610 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, BuiltInTypes::INT, false, false)); 611 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, BuiltInTypes::FLOAT, false, false)); 612 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, BuiltInTypes::BOOL, false, false)); 613 | 614 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::INT, false, BuiltInTypes::STRING, false, false)); 615 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::INT, false, BuiltInTypes::INT, false, false)); 616 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::INT, false, BuiltInTypes::FLOAT, false, false)); 617 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::INT, false, BuiltInTypes::BOOL, false, false)); 618 | 619 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::FLOAT, false, BuiltInTypes::STRING, false, false)); 620 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::FLOAT, false, BuiltInTypes::INT, false, false)); 621 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::FLOAT, false, BuiltInTypes::FLOAT, false, false)); 622 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::FLOAT, false, BuiltInTypes::BOOL, false, false)); 623 | 624 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::BOOL, false, BuiltInTypes::STRING, false, false)); 625 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::BOOL, false, BuiltInTypes::INT, false, false)); 626 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::BOOL, false, BuiltInTypes::FLOAT, false, false)); 627 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::BOOL, false, BuiltInTypes::BOOL, false, false)); 628 | } 629 | 630 | public function test_ScalarSubTypes_NotMatch_NonScalarBuiltInSuperTypes_StrictMode() 631 | { 632 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, false, BuiltInTypes::STRING, false, false)); 633 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, false, BuiltInTypes::INT, false, false)); 634 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, false, BuiltInTypes::FLOAT, false, false)); 635 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, false, BuiltInTypes::BOOL, false, false)); 636 | 637 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::STRING, false, false)); 638 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::INT, false, false)); 639 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::FLOAT, false, false)); 640 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::BOOL, false, false)); 641 | 642 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, BuiltInTypes::STRING, false, false)); 643 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, BuiltInTypes::INT, false, false)); 644 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, BuiltInTypes::FLOAT, false, false)); 645 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, BuiltInTypes::BOOL, false, false)); 646 | 647 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::STRING, false, false)); 648 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::INT, false, false)); 649 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::FLOAT, false, false)); 650 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::BOOL, false, false)); 651 | } 652 | 653 | public function test_ScalarSubTypes_InvariantMatch_NullableScalarSuperTypes_StrictMode() 654 | { 655 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, true, BuiltInTypes::STRING, false, false)); 656 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, true, BuiltInTypes::INT, false, false)); 657 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, true, BuiltInTypes::FLOAT, false, false)); 658 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, true, BuiltInTypes::BOOL, false, false)); 659 | 660 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::INT, true, BuiltInTypes::STRING, false, false)); 661 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::INT, true, BuiltInTypes::INT, false, false)); 662 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::INT, true, BuiltInTypes::FLOAT, false, false)); 663 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::INT, true, BuiltInTypes::BOOL, false, false)); 664 | 665 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::FLOAT, true, BuiltInTypes::STRING, false, false)); 666 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::FLOAT, true, BuiltInTypes::INT, false, false)); 667 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::FLOAT, true, BuiltInTypes::FLOAT, false, false)); 668 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::FLOAT, true, BuiltInTypes::BOOL, false, false)); 669 | 670 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::BOOL, true, BuiltInTypes::STRING, false, false)); 671 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::BOOL, true, BuiltInTypes::INT, false, false)); 672 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::BOOL, true, BuiltInTypes::FLOAT, false, false)); 673 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::BOOL, true, BuiltInTypes::BOOL, false, false)); 674 | } 675 | 676 | public function test_ScalarSubTypes_NotMatch_NullableNonScalarBuiltInSuperTypes_StrictMode() 677 | { 678 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, true, BuiltInTypes::STRING, false, false)); 679 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, true, BuiltInTypes::INT, false, false)); 680 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, true, BuiltInTypes::FLOAT, false, false)); 681 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, true, BuiltInTypes::BOOL, false, false)); 682 | 683 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::STRING, false, false)); 684 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::INT, false, false)); 685 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::FLOAT, false, false)); 686 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::BOOL, false, false)); 687 | 688 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, BuiltInTypes::STRING, false, false)); 689 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, BuiltInTypes::INT, false, false)); 690 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, BuiltInTypes::FLOAT, false, false)); 691 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, BuiltInTypes::BOOL, false, false)); 692 | 693 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::STRING, false, false)); 694 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::INT, false, false)); 695 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::FLOAT, false, false)); 696 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::BOOL, false, false)); 697 | } 698 | 699 | public function test_NullableScalarSubTypes_NotMatch_ScalarSuperTypes_StrictMode() 700 | { 701 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, BuiltInTypes::STRING, true, false)); 702 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, BuiltInTypes::INT, true, false)); 703 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, BuiltInTypes::FLOAT, true, false)); 704 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, false, BuiltInTypes::BOOL, true, false)); 705 | 706 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::INT, false, BuiltInTypes::STRING, true, false)); 707 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::INT, false, BuiltInTypes::INT, true, false)); 708 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::INT, false, BuiltInTypes::FLOAT, true, false)); 709 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::INT, false, BuiltInTypes::BOOL, true, false)); 710 | 711 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::FLOAT, false, BuiltInTypes::STRING, true, false)); 712 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::FLOAT, false, BuiltInTypes::INT, true, false)); 713 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::FLOAT, false, BuiltInTypes::FLOAT, true, false)); 714 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::FLOAT, false, BuiltInTypes::BOOL, true, false)); 715 | 716 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::BOOL, false, BuiltInTypes::STRING, true, false)); 717 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::BOOL, false, BuiltInTypes::INT, true, false)); 718 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::BOOL, false, BuiltInTypes::FLOAT, true, false)); 719 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::BOOL, false, BuiltInTypes::BOOL, true, false)); 720 | } 721 | 722 | public function test_NullableScalarSubTypes_NotMatch_NonScalarBuiltInSuperTypes_StrictMode() 723 | { 724 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, false, BuiltInTypes::STRING, true, false)); 725 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, false, BuiltInTypes::INT, true, false)); 726 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, false, BuiltInTypes::FLOAT, true, false)); 727 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, false, BuiltInTypes::BOOL, true, false)); 728 | 729 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::STRING, true, false)); 730 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::INT, true, false)); 731 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::FLOAT, true, false)); 732 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, false, BuiltInTypes::BOOL, true, false)); 733 | 734 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, BuiltInTypes::STRING, true, false)); 735 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, BuiltInTypes::INT, true, false)); 736 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, BuiltInTypes::FLOAT, true, false)); 737 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, false, BuiltInTypes::BOOL, true, false)); 738 | 739 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::STRING, true, false)); 740 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::INT, true, false)); 741 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::FLOAT, true, false)); 742 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, false, BuiltInTypes::BOOL, true, false)); 743 | } 744 | 745 | public function test_NullableScalarSubTypes_InvariantMatch_NullableScalarSuperTypes_StrictMode() 746 | { 747 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::STRING, true, BuiltInTypes::STRING, true, false)); 748 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, true, BuiltInTypes::INT, true, false)); 749 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, true, BuiltInTypes::FLOAT, true, false)); 750 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::STRING, true, BuiltInTypes::BOOL, true, false)); 751 | 752 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::INT, true, BuiltInTypes::STRING, true, false)); 753 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::INT, true, BuiltInTypes::INT, true, false)); 754 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::INT, true, BuiltInTypes::FLOAT, true, false)); 755 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::INT, true, BuiltInTypes::BOOL, true, false)); 756 | 757 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::FLOAT, true, BuiltInTypes::STRING, true, false)); 758 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::FLOAT, true, BuiltInTypes::INT, true, false)); 759 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::FLOAT, true, BuiltInTypes::FLOAT, true, false)); 760 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::FLOAT, true, BuiltInTypes::BOOL, true, false)); 761 | 762 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::BOOL, true, BuiltInTypes::STRING, true, false)); 763 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::BOOL, true, BuiltInTypes::INT, true, false)); 764 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::BOOL, true, BuiltInTypes::FLOAT, true, false)); 765 | $this->assertTrue(MatchTester::isMatch(BuiltInTypes::BOOL, true, BuiltInTypes::BOOL, true, false)); 766 | } 767 | 768 | public function test_NullableScalarSubTypes_NotMatch_NullableNonScalarBuiltInSuperTypes_StrictMode() 769 | { 770 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, true, BuiltInTypes::STRING, true, false)); 771 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, true, BuiltInTypes::INT, true, false)); 772 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, true, BuiltInTypes::FLOAT, true, false)); 773 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ARRAY, true, BuiltInTypes::BOOL, true, false)); 774 | 775 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::STRING, true, false)); 776 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::INT, true, false)); 777 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::FLOAT, true, false)); 778 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::VOID, true, BuiltInTypes::BOOL, true, false)); 779 | 780 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, BuiltInTypes::STRING, true, false)); 781 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, BuiltInTypes::INT, true, false)); 782 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, BuiltInTypes::FLOAT, true, false)); 783 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::CALLABLE, true, BuiltInTypes::BOOL, true, false)); 784 | 785 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::STRING, true, false)); 786 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::INT, true, false)); 787 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::FLOAT, true, false)); 788 | $this->assertFalse(MatchTester::isMatch(BuiltInTypes::ITERABLE, true, BuiltInTypes::BOOL, true, false)); 789 | } 790 | } 791 | -------------------------------------------------------------------------------- /tests/Php71/BasePhp71Test.php: -------------------------------------------------------------------------------- 1 | markTestSkipped('PHP >= 7.1.0'); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/TypeTest.php: -------------------------------------------------------------------------------- 1 | createTypeInstance(null, 0, false, false); 23 | 24 | $this->assertSame(null, $type->typeName); 25 | $this->assertFalse($type->isNullable); 26 | $this->assertFalse($type->isByReference); 27 | $this->assertFalse($type->isWeak); 28 | $this->assertFalse($type->allowsCovariance); 29 | $this->assertFalse($type->allowsContravariance); 30 | } 31 | 32 | public function testNullableFlag() 33 | { 34 | $type = $this->createTypeInstance(null, Type::NULLABLE, false, false); 35 | 36 | $this->assertSame(null, $type->typeName); 37 | $this->assertTrue($type->isNullable); 38 | $this->assertFalse($type->isByReference); 39 | $this->assertFalse($type->isWeak); 40 | $this->assertFalse($type->allowsCovariance); 41 | $this->assertFalse($type->allowsContravariance); 42 | } 43 | 44 | public function testReferenceFlag() 45 | { 46 | $type = $this->createTypeInstance(null, Type::REFERENCE, false, false); 47 | 48 | $this->assertSame(null, $type->typeName); 49 | $this->assertFalse($type->isNullable); 50 | $this->assertTrue($type->isByReference); 51 | $this->assertFalse($type->isWeak); 52 | $this->assertFalse($type->allowsCovariance); 53 | $this->assertFalse($type->allowsContravariance); 54 | } 55 | 56 | public function testWeakFlag() 57 | { 58 | $type = $this->createTypeInstance(null, Type::WEAK, false, false); 59 | 60 | $this->assertSame(null, $type->typeName); 61 | $this->assertFalse($type->isNullable); 62 | $this->assertFalse($type->isByReference); 63 | $this->assertTrue($type->isWeak); 64 | $this->assertFalse($type->allowsCovariance); 65 | $this->assertFalse($type->allowsContravariance); 66 | } 67 | 68 | public function testMultipleFlags() 69 | { 70 | $type = $this->createTypeInstance(null, Type::NULLABLE | Type::REFERENCE | Type::WEAK, false, false); 71 | 72 | $this->assertSame(null, $type->typeName); 73 | $this->assertTrue($type->isNullable); 74 | $this->assertTrue($type->isByReference); 75 | $this->assertTrue($type->isWeak); 76 | $this->assertFalse($type->allowsCovariance); 77 | $this->assertFalse($type->allowsContravariance); 78 | } 79 | 80 | public function testAllowsCovarianceArg() 81 | { 82 | $type = $this->createTypeInstance(null, 0, true, false); 83 | 84 | $this->assertSame(null, $type->typeName); 85 | $this->assertFalse($type->isNullable); 86 | $this->assertFalse($type->isByReference); 87 | $this->assertFalse($type->isWeak); 88 | $this->assertTrue($type->allowsCovariance); 89 | $this->assertFalse($type->allowsContravariance); 90 | } 91 | 92 | public function testAllowsContravarianceArg() 93 | { 94 | $type = $this->createTypeInstance(null, 0, false, true); 95 | 96 | $this->assertSame(null, $type->typeName); 97 | $this->assertFalse($type->isNullable); 98 | $this->assertFalse($type->isByReference); 99 | $this->assertFalse($type->isWeak); 100 | $this->assertFalse($type->allowsCovariance); 101 | $this->assertTrue($type->allowsContravariance); 102 | } 103 | 104 | public function testStringTypeName() 105 | { 106 | $type = $this->createTypeInstance(Type::class, 0, false, false); 107 | 108 | $this->assertSame(Type::class, $type->typeName); 109 | $this->assertFalse($type->isNullable); 110 | $this->assertFalse($type->isByReference); 111 | $this->assertFalse($type->isWeak); 112 | $this->assertFalse($type->allowsCovariance); 113 | $this->assertFalse($type->allowsContravariance); 114 | } 115 | 116 | public function testNonStringTypeName() 117 | { 118 | $type = $this->createTypeInstance(1, 0, false, false); 119 | 120 | $this->assertSame('1', $type->typeName); 121 | $this->assertFalse($type->isNullable); 122 | $this->assertFalse($type->isByReference); 123 | $this->assertFalse($type->isWeak); 124 | $this->assertFalse($type->allowsCovariance); 125 | $this->assertFalse($type->allowsContravariance); 126 | } 127 | 128 | public function testByRefMustBeIdentical() 129 | { 130 | $type = $this->createTypeInstance(Type::class, 0, false, false); 131 | 132 | $this->assertSame(Type::class, $type->typeName); 133 | $this->assertFalse($type->isByReference); 134 | 135 | $this->assertTrue($type->isSatisfiedBy(Type::class, false, false)); 136 | $this->assertFalse($type->isSatisfiedBy(Type::class, false, true)); 137 | 138 | $type = $this->createTypeInstance(Type::class, Type::REFERENCE, false, false); 139 | 140 | $this->assertSame(Type::class, $type->typeName); 141 | $this->assertTrue($type->isByReference); 142 | 143 | $this->assertTrue($type->isSatisfiedBy(Type::class, false, true)); 144 | $this->assertFalse($type->isSatisfiedBy(Type::class, false, false)); 145 | } 146 | 147 | public function testIdenticalTypesAlwaysMatch() 148 | { 149 | $type = $this->createTypeInstance(Type::class, 0, false, false); 150 | 151 | $this->assertSame(Type::class, $type->typeName); 152 | $this->assertFalse($type->isNullable); 153 | 154 | $this->assertTrue($type->isSatisfiedBy(Type::class, false, false)); 155 | 156 | $type = $this->createTypeInstance(Type::class, Type::NULLABLE, false, false); 157 | 158 | $this->assertSame(Type::class, $type->typeName); 159 | $this->assertTrue($type->isNullable); 160 | 161 | $this->assertTrue($type->isSatisfiedBy(Type::class, true, false)); 162 | } 163 | 164 | public function testValidCovariantTypeMatches() 165 | { 166 | $type = $this->createTypeInstance(Type::class, Type::NULLABLE, true, false); 167 | 168 | $this->assertSame(Type::class, $type->typeName); 169 | $this->assertTrue($type->isNullable); 170 | 171 | $this->assertTrue($type->isSatisfiedBy(Type::class, false, false)); 172 | } 173 | 174 | public function testInvalidCovariantTypeDoesNotMatch() 175 | { 176 | $type = $this->createTypeInstance(Type::class, 0, true, false); 177 | 178 | $this->assertSame(Type::class, $type->typeName); 179 | $this->assertFalse($type->isNullable); 180 | 181 | $this->assertFalse($type->isSatisfiedBy(Type::class, true, false)); 182 | } 183 | 184 | public function testValidCovariantTypeMatchesDoesNotMatchWhenCovarianceIsNotAllowed() 185 | { 186 | $type = $this->createTypeInstance(Type::class, Type::NULLABLE, false, false); 187 | 188 | $this->assertSame(Type::class, $type->typeName); 189 | $this->assertTrue($type->isNullable); 190 | 191 | $this->assertFalse($type->isSatisfiedBy(Type::class, false, false)); 192 | } 193 | 194 | public function testCovarianceRespectsWeakMode() 195 | { 196 | $type = $this->createTypeInstance(BuiltInTypes::STRING, 0, true, false); 197 | 198 | $this->assertSame(BuiltInTypes::STRING, $type->typeName); 199 | $this->assertFalse($type->isWeak); 200 | 201 | $this->assertFalse($type->isSatisfiedBy(BuiltInTypes::INT, false, false)); 202 | 203 | $type = $this->createTypeInstance(BuiltInTypes::STRING, Type::WEAK, true, false); 204 | 205 | $this->assertSame(BuiltInTypes::STRING, $type->typeName); 206 | $this->assertTrue($type->isWeak); 207 | 208 | $this->assertTrue($type->isSatisfiedBy(BuiltInTypes::INT, false, false)); 209 | } 210 | 211 | public function testValidContravariantTypeMatches() 212 | { 213 | $type = $this->createTypeInstance(Type::class, 0, false, true); 214 | 215 | $this->assertSame(Type::class, $type->typeName); 216 | $this->assertFalse($type->isNullable); 217 | $this->assertTrue($type->isSatisfiedBy(Type::class, true, false)); 218 | } 219 | 220 | public function testInvalidContravariantTypeDoesNotMatch() 221 | { 222 | $type = $this->createTypeInstance(Type::class, Type::NULLABLE, false, true); 223 | 224 | $this->assertSame(Type::class, $type->typeName); 225 | $this->assertTrue($type->isNullable); 226 | 227 | $this->assertFalse($type->isSatisfiedBy(Type::class, false, false)); 228 | } 229 | 230 | public function testValidContravariantTypeDoesNotMatchWhenContravarianceIsNotAllowed() 231 | { 232 | $type = $this->createTypeInstance(Type::class, 0, false, false); 233 | 234 | $this->assertSame(Type::class, $type->typeName); 235 | $this->assertFalse($type->isNullable); 236 | 237 | $this->assertFalse($type->isSatisfiedBy(Type::class, true, false)); 238 | } 239 | 240 | public function testContravarianceRespectsWeakMode() 241 | { 242 | $type = $this->createTypeInstance(BuiltInTypes::STRING, 0, false, true); 243 | 244 | $this->assertSame(BuiltInTypes::STRING, $type->typeName); 245 | $this->assertFalse($type->isWeak); 246 | 247 | $this->assertFalse($type->isSatisfiedBy(BuiltInTypes::INT, false, false)); 248 | 249 | $type = $this->createTypeInstance(BuiltInTypes::STRING, Type::WEAK, false, true); 250 | 251 | $this->assertSame(BuiltInTypes::STRING, $type->typeName); 252 | $this->assertTrue($type->isWeak); 253 | 254 | $this->assertTrue($type->isSatisfiedBy(BuiltInTypes::INT, false, false)); 255 | } 256 | 257 | public function testInvarianceRespectsWeakMode() 258 | { 259 | $type = $this->createTypeInstance(BuiltInTypes::STRING, 0, false, false); 260 | 261 | $this->assertSame(BuiltInTypes::STRING, $type->typeName); 262 | $this->assertFalse($type->isWeak); 263 | 264 | $this->assertFalse($type->isSatisfiedBy(BuiltInTypes::INT, false, false)); 265 | 266 | $type = $this->createTypeInstance(BuiltInTypes::STRING, Type::WEAK, false, false); 267 | 268 | $this->assertSame(BuiltInTypes::STRING, $type->typeName); 269 | $this->assertTrue($type->isWeak); 270 | 271 | $this->assertTrue($type->isSatisfiedBy(BuiltInTypes::INT, false, false)); 272 | 273 | $type = $this->createTypeInstance(BuiltInTypes::STRING, Type::WEAK | Type::NULLABLE, false, false); 274 | 275 | $this->assertSame(BuiltInTypes::STRING, $type->typeName); 276 | $this->assertTrue($type->isWeak); 277 | 278 | $this->assertFalse($type->isSatisfiedBy(BuiltInTypes::INT, false, false)); 279 | } 280 | } 281 | --------------------------------------------------------------------------------