HEX
Server: nginx/1.30.4
System: Linux d-twindigital-web-1.host-ed.eu 4.18.0-553.141.2.el8_10.x86_64 #1 SMP Wed Jul 8 10:28:18 EDT 2026 x86_64
User: u_twindigital_html (1009)
PHP: 8.3.30
Disabled: NONE
Upload Files
File: //bin/phpstan.phar
#!/usr/bin/env php
<?php
Phar::mapPhar('phpstan.phar');
require 'phar://phpstan.phar/bin/phpstan';
__HALT_COMPILER(); ?>
>��phpstan.phar
BACKERS.md>��mZ>-�L�CODE_OF_CONDUCT.md���mZ�+6��LICENSE1��mZ1 w~��	README.md|R��mZ|R�?��appveyor.yml���mZ��k�bin/phpstan���mZ���l��	build.xml��mZ̵>>�
composer.jsonW	��mZW	�c��
composer.lock����mZ���]J�conf/config.level0.neon��mZ�gӶconf/config.level1.neon��mZDQ"Ѷconf/config.level2.neon(��mZ(=ic�conf/config.level3.neon/��mZ/$���conf/config.level4.neonR��mZR\�HE�conf/config.level5.neon���mZ�&*B�conf/config.level6.neonE��mZE=��conf/config.level7.neonx��mZxb��4�conf/config.levelmax.neon!��mZ!*۔}�conf/config.neon��mZ%�f!�	phpcs.xmlj
��mZj
fd��src/AnalysedCodeException.phps��mZs��}�src/Analyser/Analyser.phpB��mZB�U��src/Analyser/Error.php��mZp�PҶ'src/Analyser/LookForAssignsSettings.php���mZ�����src/Analyser/NameScope.php`��mZ`�'(�"src/Analyser/NodeScopeResolver.php#���mZ#��F�V�src/Analyser/Scope.phpC���mZC���oҶsrc/Analyser/SpecifiedTypes.php���mZ��a��src/Analyser/StatementList.php��mZ�n[��src/Analyser/TypeSpecifier.php�-��mZ�-�L��+src/Analyser/UndefinedVariableException.phpw��mZw񣄐�#src/Analyser/VariableTypeHolder.php
��mZ
��ƶsrc/Broker/Broker.php�-��mZ�-��ˁ�src/Broker/BrokerFactory.php?��mZ?u��(src/Broker/ClassAutoloadingException.php���mZ��M���%src/Broker/ClassNotFoundException.php���mZ��	��(src/Broker/FunctionNotFoundException.php���mZ��ng�src/Cache/Cache.php$��mZ$��&�src/Cache/CacheStorage.php0��mZ0��q�src/Cache/FileCacheStorage.php}��mZ}�hҧ� src/Cache/MemoryCacheStorage.php��mZ��4�"src/Command/AnalyseApplication.php��mZ�n0�src/Command/AnalyseCommand.php�$��mZ�$�Z�{�src/Command/AnalysisResult.php���mZ��"S��7src/Command/ErrorFormatter/CheckstyleErrorFormatter.php���mZ��Ti��-src/Command/ErrorFormatter/ErrorFormatter.php��mZSޭ�0src/Command/ErrorFormatter/RawErrorFormatter.phpv��mZv#����2src/Command/ErrorFormatter/TableErrorFormatter.phpm��mZmh�o��"src/Command/ErrorsConsoleStyle.phpO��mZO���H�,src/DependencyInjection/ContainerFactory.php<��mZ<�.�src/File/FileExcluder.php���mZ���z�src/File/FileHelper.php2��mZ2{z=�src/Parser/CachedParser.php/��mZ/<�Ʋ�src/Parser/DirectParser.php���mZ������*src/Parser/FunctionCallStatementFinder.php���mZ�7.sܶsrc/Parser/Parser.php]��mZ]o�
�src/PhpDoc/PhpDocBlock.php�
��mZ�
i��=�!src/PhpDoc/PhpDocNodeResolver.php��mZK�~i�#src/PhpDoc/PhpDocStringResolver.php���mZ��z�"src/PhpDoc/ResolvedPhpDocBlock.php���mZ���k#�src/PhpDoc/Tag/MethodTag.phpT��mZTR�6v�%src/PhpDoc/Tag/MethodTagParameter.phpO��mZOA�u�src/PhpDoc/Tag/ParamTag.phpu��mZu�#��src/PhpDoc/Tag/PropertyTag.php,��mZ,1����src/PhpDoc/Tag/ReturnTag.php���mZ���$��src/PhpDoc/Tag/VarTag.php���mZ��b��src/PhpDoc/TypeNodeResolver.php�%��mZ�%�����!src/PhpDoc/TypeStringResolver.php���mZ�Ѷ!�9src/Reflection/Annotations/AnnotationMethodReflection.php���mZ���/��;src/Reflection/Annotations/AnnotationPropertyReflection.php���mZ�Ԣ"�Csrc/Reflection/Annotations/AnnotationsMethodParameterReflection.phpg��mZg3���Isrc/Reflection/Annotations/AnnotationsMethodsClassReflectionExtension.php�
��mZ�
ȋfܶLsrc/Reflection/Annotations/AnnotationsPropertiesClassReflectionExtension.php/��mZ/.%�b�6src/Reflection/BrokerAwareClassReflectionExtension.php���mZ�u��'src/Reflection/BrokerAwareExtension.php���mZ��
9�*src/Reflection/ClassConstantReflection.php���mZ���"J�8src/Reflection/ClassConstantWithVisibilityReflection.php��mZ@����(src/Reflection/ClassMemberReflection.php��mZA���"src/Reflection/ClassReflection.phpA%��mZA%�)��%src/Reflection/FunctionReflection.phpY!��mZY!4���,src/Reflection/FunctionReflectionFactory.php8��mZ8��;�#src/Reflection/MethodReflection.php���mZ�K٥$�2src/Reflection/MethodsClassReflectionExtension.phpj��mZj��\�7src/Reflection/MissingMethodFromReflectionException.php���mZ��t��9src/Reflection/MissingPropertyFromReflectionException.php���mZ�KY��2src/Reflection/ObsoleteClassConstantReflection.php6��mZ6&�a�&src/Reflection/ParameterReflection.phpM��mZM~Fo�%src/Reflection/ParametersAcceptor.php���mZ�E`��0src/Reflection/ParametersAcceptorWithPhpDocs.php���mZ����%src/Reflection/Php/DummyParameter.phpJ��mZJ�}v�2src/Reflection/Php/PhpClassReflectionExtension.php�)��mZ�)�fH�:src/Reflection/Php/PhpFunctionFromParserNodeReflection.php,
��mZ,
�#�V�8src/Reflection/Php/PhpMethodFromParserNodeReflection.phpk��mZk��ն*src/Reflection/Php/PhpMethodReflection.php�.��mZ�.�ƅ�1src/Reflection/Php/PhpMethodReflectionFactory.php���mZ���[=�;src/Reflection/Php/PhpParameterFromParserNodeReflection.phpu��mZu��%_�-src/Reflection/Php/PhpParameterReflection.php���mZ�Nz{�,src/Reflection/Php/PhpPropertyReflection.phpX��mZXTN�[�3src/Reflection/Php/UniversalObjectCrateProperty.php���mZ�)��Dsrc/Reflection/Php/UniversalObjectCratesClassReflectionExtension.php���mZ�zf<��>src/Reflection/PhpDefect/PhpDefectClassReflectionExtension.php���mZ��L���8src/Reflection/PhpDefect/PhpDefectPropertyReflection.php$��mZ$Q��5src/Reflection/PropertiesClassReflectionExtension.phpw��mZw�{~��%src/Reflection/PropertyReflection.php*��mZ*��{U�*src/Rules/Arrays/AllowedArrayKeysTypes.phpV��mZV�?��.src/Rules/Arrays/AppendedArrayItemTypeRule.phpI��mZI�e�ݶ5src/Rules/Arrays/DuplicateKeysInLiteralArraysRule.php�	��mZ�	���2src/Rules/Arrays/InvalidKeyInArrayDimFetchRule.php���mZ�.�I��.src/Rules/Arrays/InvalidKeyInArrayItemRule.php��mZ���Ŷ*src/Rules/Arrays/IterableInForeachRule.php���mZ�8�
�"src/Rules/Cast/UselessCastRule.phpf��mZf�lN>�'src/Rules/ClassCaseSensitivityCheck.php���mZ�����'src/Rules/Classes/ClassConstantRule.php���mZ�vH���5src/Rules/Classes/ExistingClassInClassExtendsRule.php���mZ��W9:�3src/Rules/Classes/ExistingClassInInstanceOfRule.php���mZ�nb���1src/Rules/Classes/ExistingClassInTraitUseRule.php���mZ�&���:src/Rules/Classes/ExistingClassesInClassImplementsRule.php���mZ��٦F�;src/Rules/Classes/ExistingClassesInInterfaceExtendsRule.php���mZ��S�.src/Rules/Classes/ImpossibleInstanceOfRule.php���mZ�4�x��'src/Rules/Classes/InstantiationRule.php���mZ�_���4src/Rules/Classes/RequireParentConstructCallRule.php��mZ���P�5src/Rules/Classes/UnusedConstructorParametersRule.php-��mZ-���m�<src/Rules/Comparison/ImpossibleCheckTypeFunctionCallRule.php��mZ��\�=src/Rules/Comparison/StrictComparisonOfDifferentTypesRule.phpW��mZWw_f�$src/Rules/Constants/ConstantRule.php6��mZ6�UL4�5src/Rules/Exceptions/CaughtExceptionExistenceRule.phpX��mZX���$�src/Rules/FoundTypeResult.php���mZ�Pr��)src/Rules/FunctionCallParametersCheck.php:��mZ:==��%src/Rules/FunctionDefinitionCheck.php���mZ���V��%src/Rules/FunctionReturnTypeCheck.php�
��mZ�
��[T�?src/Rules/Functions/CallToCountOnlyWithArrayOrCountableRule.php.��mZ.��ஶ4src/Rules/Functions/CallToFunctionParametersRule.php���mZ�f��5src/Rules/Functions/CallToNonExistentFunctionRule.php��mZ��	��-src/Rules/Functions/ClosureReturnTypeRule.phpb��mZbd3�%�=src/Rules/Functions/ExistingClassesInClosureTypehintsRule.php���mZ���R�6src/Rules/Functions/ExistingClassesInTypehintsRule.php���mZ����)src/Rules/Functions/InnerFunctionRule.php��mZ���6src/Rules/Functions/NonExistentDefinedFunctionRule.php9��mZ97�!�,src/Rules/Functions/PrintfParametersRule.php)��mZ)j���&src/Rules/Functions/ReturnTypeRule.phpO��mZO�[�V�-src/Rules/Functions/UnusedClosureUsesRule.php���mZ�����3src/Rules/Methods/CallMethodsOnPossiblyNullRule.phpE��mZE�w�&�%src/Rules/Methods/CallMethodsRule.php���mZ�T���+src/Rules/Methods/CallStaticMethodsRule.php���mZ���1�4src/Rules/Methods/ExistingClassesInTypehintsRule.php6��mZ6&$"Ķ$src/Rules/Methods/ReturnTypeRule.phpm��mZm�2��4src/Rules/Namespaces/ExistingNamesInGroupUseRule.php���mZ�'pe�/src/Rules/Namespaces/ExistingNamesInUseRule.php�
��mZ�
׎�'�/src/Rules/PhpDoc/IncompatiblePhpDocTypeRule.php)��mZ)k��p�.src/Rules/PhpDoc/InvalidPhpDocTagValueRule.php���mZ�$�߶;src/Rules/Properties/AccessPropertiesOnPossiblyNullRule.phpV��mZV��-src/Rules/Properties/AccessPropertiesRule.php
��mZ
�&�l�3src/Rules/Properties/AccessStaticPropertiesRule.phpr��mZr5���Bsrc/Rules/Properties/DefaultValueTypesAssignedToPropertiesRule.phpW��mZW`��8src/Rules/Properties/ExistingClassesInPropertiesRule.php ��mZ ӑW��+src/Rules/Properties/PropertyDescriptor.phpQ��mZQ"E4e�1src/Rules/Properties/PropertyReflectionFinder.php���mZ�J��7src/Rules/Properties/ReadingWriteOnlyPropertiesRule.phpo��mZoa��H�6src/Rules/Properties/TypesAssignedToPropertiesRule.phpk	��mZk	XCGu�8src/Rules/Properties/WritingToReadOnlyPropertiesRule.php�	��mZ�	R��src/Rules/Registry.php���mZ�l�v�src/Rules/RegistryFactory.php���mZ�8���src/Rules/Rule.php���mZ�U��src/Rules/RuleLevelHelper.php���mZ�Z�P�+src/Rules/UnusedFunctionParametersCheck.php���mZ�2k��Asrc/Rules/Variables/DefinedVariableInAnonymousFunctionUseRule.php7��mZ7��#Զ+src/Rules/Variables/DefinedVariableRule.php\��mZ\��䵶(src/Rules/Variables/ThisVariableRule.phpO��mZOJD��4src/Rules/Variables/VariableCertaintyInIssetRule.php���mZ�����+src/Rules/Variables/VariableCloningRule.phpz��mZz؝�>� src/ShouldNotHappenException.php���mZ�8g$A�src/Testing/RuleTestCase.php
��mZ
���src/Testing/TestCase.phpf��mZfp�4�src/TrinaryLogic.phpV	��mZV	��src/Type/ArrayType.phpB��mZB�?q{�src/Type/BooleanType.phpq��mZq��ʎ�src/Type/CallableType.php!��mZ!��Uösrc/Type/CommentHelper.phpK��mZK_��,�src/Type/CompoundType.php���mZ��r >�src/Type/CompoundTypeHelper.phpV��mZV�愶/src/Type/DynamicFunctionReturnTypeExtension.php���mZ��k �-src/Type/DynamicMethodReturnTypeExtension.php���mZ����3src/Type/DynamicStaticMethodReturnTypeExtension.php
��mZ
L�:u�src/Type/ErrorType.php���mZ�^�0�src/Type/FalseBooleanType.php�
��mZ�
�Q�src/Type/FileTypeMapper.phpp��mZp��]"�src/Type/FloatType.php�
��mZ�
�1ֶsrc/Type/IntegerType.phpE��mZE[1�M�src/Type/IntersectionType.php���mZ��M�Ƕ!src/Type/IterableIterableType.phpf��mZf#��src/Type/IterableTypeTrait.phpg��mZg+�=ʶ"src/Type/JustNullableTypeTrait.php���mZ�6;�1�src/Type/MixedType.php�
��mZ�
��ZԶ src/Type/NestedArrayItemType.php���mZ�jr���src/Type/NeverType.php�	��mZ�	�Jq�'src/Type/NonexistentParentClassType.phpW��mZW�g[�src/Type/NullType.php1
��mZ1
�M�src/Type/ObjectType.php!��mZ!�E��#src/Type/ObjectWithoutClassType.php�
��mZ�
-�
�<src/Type/Php/AllArgumentBasedFunctionReturnTypeExtension.php���mZ���̶>src/Type/Php/ArgumentBasedArrayFunctionReturnTypeExtension.php���mZ�_�U�9src/Type/Php/ArgumentBasedFunctionReturnTypeExtension.php/��mZ/V��жAsrc/Type/Php/ArrayFilterFunctionReturnTypeReturnTypeExtension.php/��mZ/tx��>src/Type/Php/CallbackBasedArrayFunctionReturnTypeExtension.php}��mZ}�mO�9src/Type/Php/CallbackBasedFunctionReturnTypeExtension.php���mZ���%�src/Type/RecursionGuard.php���mZ�֪r!�src/Type/ResourceType.phpK��mZK溢q�!src/Type/StaticResolvableType.php���mZ�ѝ�H�src/Type/StaticType.php���mZ�H�g�src/Type/StringType.php���mZ��D�w�src/Type/ThisType.php���mZ�m�*a�src/Type/TrueBooleanType.php�
��mZ�
����#src/Type/TrueOrFalseBooleanType.phpp
��mZp
��R�src/Type/Type.php��mZ{�%��src/Type/TypeCombinator.php��mZb�K�src/Type/TypeWithClassName.php���mZ�[G�~�src/Type/TypehintHelper.php]��mZ]����src/Type/UnionType.phpQ��mZQ��_N�src/Type/UnionTypeHelper.php��mZ�\�u�src/Type/VoidType.php�	��mZ�	�4�vendor/autoload.php���mZ�����vendor/bin/php-parse��mZ���vendor/composer/ClassLoader.php�4��mZ�4Q����vendor/composer/LICENSE0��mZ0��%vendor/composer/autoload_classmap.php�&��mZ�&r���"vendor/composer/autoload_files.php���mZ�<�Ͷ'vendor/composer/autoload_namespaces.php���mZ�����!vendor/composer/autoload_psr4.php���mZ��t�E�!vendor/composer/autoload_real.php7��mZ7����#vendor/composer/autoload_static.php:L��mZ:L<(e�vendor/composer/installed.jsonǂ��mZǂG���3vendor/jean85/pretty-package-versions/composer.json���mZ�H5l\�<vendor/jean85/pretty-package-versions/src/PrettyVersions.phpN��mZN�Ҕ�5vendor/jean85/pretty-package-versions/src/Version.php���mZ����
�$vendor/nette/bootstrap/composer.json���mZ�B�k+�!vendor/nette/bootstrap/license.md�
��mZ�
.��<�5vendor/nette/bootstrap/src/Bootstrap/Configurator.php�+��mZ�+J���<vendor/nette/bootstrap/src/Bridges/Framework/TracyBridge.php���mZ�U�R;�vendor/nette/di/composer.json���mZ�i�f��vendor/nette/di/license.md�
��mZ�
.��<�6vendor/nette/di/src/Bridges/DITracy/ContainerPanel.phpp��mZp)�Hvendor/nette/di/src/Bridges/DITracy/templates/ContainerPanel.panel.phtmlA��mZA�:��Fvendor/nette/di/src/Bridges/DITracy/templates/ContainerPanel.tab.phtml���mZ���[϶#vendor/nette/di/src/DI/Compiler.php�=��mZ�=���g�,vendor/nette/di/src/DI/CompilerExtension.php��mZg�/�5vendor/nette/di/src/DI/Config/Adapters/IniAdapter.php���mZ�AN�L�6vendor/nette/di/src/DI/Config/Adapters/NeonAdapter.php��mZe>NJ�5vendor/nette/di/src/DI/Config/Adapters/PhpAdapter.php���mZ�N��,�)vendor/nette/di/src/DI/Config/Helpers.php���mZ�7�¶*vendor/nette/di/src/DI/Config/IAdapter.php���mZ��Ӄ�(vendor/nette/di/src/DI/Config/Loader.php?
��mZ?
�+ӕ�$vendor/nette/di/src/DI/Container.php�"��mZ�"uW�ö+vendor/nette/di/src/DI/ContainerBuilder.php9p��mZ9p���*vendor/nette/di/src/DI/ContainerLoader.php�
��mZ�
�?�,vendor/nette/di/src/DI/DependencyChecker.php���mZ�l)#�8vendor/nette/di/src/DI/Extensions/ConstantsExtension.php	��mZ	rm2�1vendor/nette/di/src/DI/Extensions/DIExtension.php:��mZ:�5��8vendor/nette/di/src/DI/Extensions/DecoratorExtension.phpQ��mZQ�IM�9vendor/nette/di/src/DI/Extensions/ExtensionsExtension.php���mZ�rMY�5vendor/nette/di/src/DI/Extensions/InjectExtension.php���mZ�ԡX�2vendor/nette/di/src/DI/Extensions/PhpExtension.php���mZ��J�x�"vendor/nette/di/src/DI/Helpers.php���mZ�R%�4�'vendor/nette/di/src/DI/PhpGenerator.phpf$��mZf$a(��(vendor/nette/di/src/DI/PhpReflection.phpB��mZBQ�v8�,vendor/nette/di/src/DI/ServiceDefinition.php���mZ����$vendor/nette/di/src/DI/Statement.php���mZ��%��%vendor/nette/di/src/DI/exceptions.php���mZ�T��ݶ!vendor/nette/finder/composer.json���mZ�[����vendor/nette/finder/license.md�
��mZ�
.��<�(vendor/nette/finder/src/Utils/Finder.php�#��mZ�#���vendor/nette/neon/composer.json���mZ�UQ�vendor/nette/neon/license.md�
��mZ�
.��<�&vendor/nette/neon/src/Neon/Decoder.php�*��mZ�*����&vendor/nette/neon/src/Neon/Encoder.php}��mZ}o�?��%vendor/nette/neon/src/Neon/Entity.php]��mZ]�m9��(vendor/nette/neon/src/Neon/Exception.php��mZa�qH�#vendor/nette/neon/src/Neon/Neon.php/��mZ/8bXh�vendor/nette/neon/src/neon.php���mZ��ѹ�(vendor/nette/php-generator/composer.json��mZI��%vendor/nette/php-generator/license.md�
��mZ�
.��<�9vendor/nette/php-generator/src/PhpGenerator/ClassType.php�)��mZ�)��K��7vendor/nette/php-generator/src/PhpGenerator/Closure.php��mZAl_=�8vendor/nette/php-generator/src/PhpGenerator/Constant.php���mZ��gI�7vendor/nette/php-generator/src/PhpGenerator/Factory.php���mZ��Ń�>vendor/nette/php-generator/src/PhpGenerator/GlobalFunction.phpO��mZO�E�ֶ7vendor/nette/php-generator/src/PhpGenerator/Helpers.phpb��mZb�_�6vendor/nette/php-generator/src/PhpGenerator/Method.php���mZ�
j�Ŷ9vendor/nette/php-generator/src/PhpGenerator/Parameter.php��mZ����7vendor/nette/php-generator/src/PhpGenerator/PhpFile.php
��mZ
�����:vendor/nette/php-generator/src/PhpGenerator/PhpLiteral.php���mZ��E�~�<vendor/nette/php-generator/src/PhpGenerator/PhpNamespace.php���mZ��[Ӫ�8vendor/nette/php-generator/src/PhpGenerator/Property.php���mZ�E��Cvendor/nette/php-generator/src/PhpGenerator/Traits/CommentAware.php���mZ�0ۯ��Cvendor/nette/php-generator/src/PhpGenerator/Traits/FunctionLike.php���mZ��K��@vendor/nette/php-generator/src/PhpGenerator/Traits/NameAware.php_��mZ_ӂ�ѶFvendor/nette/php-generator/src/PhpGenerator/Traits/VisibilityAware.php��mZ���'vendor/nette/robot-loader/composer.json���mZ�k��$vendor/nette/robot-loader/license.md�
��mZ�
.��<�9vendor/nette/robot-loader/src/RobotLoader/RobotLoader.php!)��mZ!)3�ZA� vendor/nette/utils/composer.json
��mZ
U7�vendor/nette/utils/license.md�
��mZ�
.��<�4vendor/nette/utils/src/Iterators/CachingIterator.php{��mZ{��g�+vendor/nette/utils/src/Iterators/Filter.php���mZ��W�}�+vendor/nette/utils/src/Iterators/Mapper.phpS��mZS�,/�4vendor/nette/utils/src/Iterators/RecursiveFilter.php8��mZ8�a"��*vendor/nette/utils/src/Utils/ArrayHash.phpq��mZq���*vendor/nette/utils/src/Utils/ArrayList.php�	��mZ�	8�L��'vendor/nette/utils/src/Utils/Arrays.php$��mZ$Gd�m�)vendor/nette/utils/src/Utils/Callback.php���mZ�m3M��)vendor/nette/utils/src/Utils/DateTime.php���mZ�Y���+vendor/nette/utils/src/Utils/FileSystem.php?��mZ?xff�%vendor/nette/utils/src/Utils/Html.php�6��mZ�6��M�,vendor/nette/utils/src/Utils/IHtmlString.php��mZR[���,vendor/nette/utils/src/Utils/ITranslator.php���mZ��I/S�&vendor/nette/utils/src/Utils/Image.phpM��mZM���!�%vendor/nette/utils/src/Utils/Json.php���mZ�M���'vendor/nette/utils/src/Utils/Object.phpH��mZHǩ�-�,vendor/nette/utils/src/Utils/ObjectMixin.phpM?��mZM?|���*vendor/nette/utils/src/Utils/Paginator.php���mZ�p�4 �'vendor/nette/utils/src/Utils/Random.php<��mZ<�>��+vendor/nette/utils/src/Utils/Reflection.php���mZ��S�7�,vendor/nette/utils/src/Utils/SmartObject.php!��mZ!g�V�,vendor/nette/utils/src/Utils/StaticClass.phpu��mZu�BO�(vendor/nette/utils/src/Utils/Strings.php�>��mZ�>��v�+vendor/nette/utils/src/Utils/Validators.php�"��mZ�"�˚�+vendor/nette/utils/src/Utils/exceptions.php��mZÐe��vendor/nikic/php-parser/LICENSE���mZ�q~|�%vendor/nikic/php-parser/bin/php-parse��mZ���%vendor/nikic/php-parser/composer.jsonj��mZj>R	��4vendor/nikic/php-parser/lib/PhpParser/Autoloader.php���mZ�+����1vendor/nikic/php-parser/lib/PhpParser/Builder.php���mZ�D\�8vendor/nikic/php-parser/lib/PhpParser/Builder/Class_.php���mZ���ֿ�=vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.php���mZ�p� E�>vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php��mZ����;vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.phpL��mZL]%o��<vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php���mZ�K j�8vendor/nikic/php-parser/lib/PhpParser/Builder/Method.php���mZ�^��<vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php���mZ�BA�H�7vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php���mZ��TO+�:vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php�	��mZ�	9~��8vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php���mZ�8��t�6vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php��mZ-�;�9vendor/nikic/php-parser/lib/PhpParser/BuilderAbstract.php��mZ��39�8vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.phpt
��mZt
�Ӂ�1vendor/nikic/php-parser/lib/PhpParser/Comment.php��mZo�ζ5vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.phpM��mZM��MӶ/vendor/nikic/php-parser/lib/PhpParser/Error.php���mZ�8}r�6vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php��mZe���Avendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.phpG��mZGS��?vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.phpP��mZP�_z�/vendor/nikic/php-parser/lib/PhpParser/Lexer.php�:��mZ�:��)�9vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php���mZ����4�.vendor/nikic/php-parser/lib/PhpParser/Node.php���mZ�����2vendor/nikic/php-parser/lib/PhpParser/Node/Arg.php���mZ�f@~�5vendor/nikic/php-parser/lib/PhpParser/Node/Const_.php���mZ�ܲ��3vendor/nikic/php-parser/lib/PhpParser/Node/Expr.phpk��mZk�Pp@�Avendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php���mZ�`}�n�=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.phph��mZh�C�¶:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php���mZ�����:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php���mZ����<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php���mZ��%���Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.phpx��mZx�*�Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.phpw��mZw���!�Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.phpx��mZxu�0F�Cvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.phpt��mZt��&�@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.phpq��mZqx�EֶBvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.phps��mZs���@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.phpq��mZqZI�@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.phpq��mZq�y��Avendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.phpr��mZr[Wr�@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.phpq��mZq��:�Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.phpw��mZw!���Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.phpx��mZx2�ֶ=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php���mZ��&%�<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php��mZ��X�Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.phpx��mZxH�遶Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.phpw��mZw�p׶Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.phpx��mZx���Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.phpx��mZx����Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.phpw��mZw���@�Evendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.phpw��mZwW|�]�Cvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.phpt��mZt�G~�@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.phpq��mZq��p�Bvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.phps��mZs€V�Dvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.phpu��mZu�>�m�Kvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php|��mZ|ق��Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.phpw��mZw��2�Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.phpx��mZx��J@�Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.phpw��mZw�<U�Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.phpx��mZxL|,�Bvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.phps��mZs҆
��@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.phpq��mZq�59�@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.phpq��mZq2+l�Evendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.phpv��mZv��<�Ivendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.phpz��mZz�C::�Avendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.phpr��mZr��p�@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.phpq��mZqc]��Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.phpw��mZwI�
�Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.phpx��mZx��}�Dvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.phpu��mZu��˶Kvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php|��mZ|�Lwu�Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.phpx��mZx�(|D�>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php��mZ�
Ok�>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php&��mZ&�Wbc�8vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php��mZ0�3��?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.phph��mZh����>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.phph��mZh�8g�?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.phpi��mZi�ۯڶ=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.phpg��mZg��6��@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.phpj��mZj�>JW�@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.phpj��mZjj�*�?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.phph��mZhb��!�Cvendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php���mZ���L�:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php��mZ�G�;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php���mZ�/ #�>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php���mZ��'�>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php8��mZ8�g�:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php��mZ
ܾn�9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php���mZ��!öAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php ��mZ c���9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php��mZ�\�9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php���mZ�H����<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php��mZ\DF�<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php+��mZ+W�_T�?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php���mZ���>��:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php��mZf&q��9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.phpV��mZVP;ة�>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php���mZ�C�ɀ�8vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.phpU��mZU��h
�;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php��mZ�
X�;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php��mZ9=��:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php��mZjIT��:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php��mZ�S,��:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php��mZ�0ͶAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php���mZ�m��Ͷ=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php?��mZ?��]V�>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php���mZ����Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php���mZ�Ad#*�;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.phpp��mZp�C�b�>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php��mZ=K���=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php$��mZ$k���<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php%��mZ%��a!�=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php(��mZ(5��ڶ:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php���mZ��6��;vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.phpP��mZP:INp�3vendor/nikic/php-parser/lib/PhpParser/Node/Name.php���mZ�SGL0�Bvendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php���mZ�ĝi��<vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php���mZ����w�;vendor/nikic/php-parser/lib/PhpParser/Node/NullableType.php8��mZ8pR�ö4vendor/nikic/php-parser/lib/PhpParser/Node/Param.php���mZ��oK�5vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.phpH��mZH/��=vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php���mZ���(��>vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.phpN��mZN��a�Hvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.phpT��mZT 	��=vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php,��mZ,	�c�@vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php.��mZ.Ez��Gvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php���mZ�-(+<�Dvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php���mZ�}u�Evendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php���mZ�J�V�Jvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php���mZ�B��Evendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php���mZ��M��Gvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php���mZ����Kvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php���mZ��"8F�Gvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php���mZ������=vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php���mZ���&϶3vendor/nikic/php-parser/lib/PhpParser/Node/Stmt.phpk��mZk��D�:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.phpN��mZN���Ŷ9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php���mZ�s;}۶:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php���mZ��yc�>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php���mZ�mqhK�=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.phpz��mZz9H帶?vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php
��mZ
t�BJ�:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php���mZ�����:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.phpN��mZN$�k�=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.phpZ��mZZ�<��Bvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php���mZ�/��<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php���mZ�Zѿ�7vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php���mZ�R�z�9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php)��mZ)6+�;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php���mZ��^(y�9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php"��mZ"]}J��<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php'��mZ'�ܢ�8vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.phpA��mZA�C���<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.phpG��mZG�9�Ƕ=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php���mZ��#%�;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php;��mZ;��ն9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php(��mZ(+Å�<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php��mZ�-��@vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php}��mZ}���7vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php��mZ��*��>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php��mZ�=\�>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php���mZ�mR9��9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php��mZ���>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php:��mZ:DR�7vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php���mZ��‘�<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php.��mZ.ְ�<�Dvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php���mZ�&y���;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php9��mZ9�B
�=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php���mZ�1ា;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.phpH��mZHc�L�;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php���mZ��y�:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php!��mZ!z��<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php��mZ5hW��Fvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php���mZ�݄嘶Lvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php���mZ���#�Qvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.phpe��mZenQ�L�:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php���mZ���?^�<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php���mZ���Ѷ:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php4��mZ4��I�:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.phpp��mZp��l�8vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php���mZ�V��x�:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php���mZ���ӥ�6vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php���mZ���:�4vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php���mZ�j�ն7vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php?��mZ?5�
�@vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php@��mZ@_4��5vendor/nikic/php-parser/lib/PhpParser/NodeVisitor.php���mZ�$Oo{�Bvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php
(��mZ
(:�Q�=vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php<��mZ<!S(̶0vendor/nikic/php-parser/lib/PhpParser/Parser.phpP��mZP��J@�9vendor/nikic/php-parser/lib/PhpParser/Parser/Multiple.phpT��mZTo	k޶5vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.phpHk��mZHkZ�¶5vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php�!��mZ�!wL��7vendor/nikic/php-parser/lib/PhpParser/Parser/Tokens.phph��mZh�VKѶ8vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php�t��mZ�tL�[X�7vendor/nikic/php-parser/lib/PhpParser/ParserFactory.php-��mZ-*�R@�@vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php����mZ��Q���?vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php�2��mZ�2!Ν�4vendor/nikic/php-parser/lib/PhpParser/Serializer.php��mZ3<��8vendor/nikic/php-parser/lib/PhpParser/Serializer/XML.phpZ��mZZ�Ȑ�6vendor/nikic/php-parser/lib/PhpParser/Unserializer.php#��mZ#�Ƕ:vendor/nikic/php-parser/lib/PhpParser/Unserializer/XML.phpO��mZO}����)vendor/nikic/php-parser/lib/bootstrap.php���mZ�]����(vendor/ocramius/package-versions/LICENSE#��mZ#"Y�ȶ.vendor/ocramius/package-versions/composer.json���mZ�c1�Ivendor/ocramius/package-versions/src/PackageVersions/FallbackVersions.php$
��mZ$
�e	>�Bvendor/ocramius/package-versions/src/PackageVersions/Installer.php��mZ��L�Avendor/ocramius/package-versions/src/PackageVersions/Versions.php���mZ��;4�*vendor/phpstan/phpdoc-parser/composer.json���mZ�)���Ivendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php
��mZ
�x��Evendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php���mZ��" �Evendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php���mZ��j�¶Evendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php>��mZ>ʶ�B�Gvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php@��mZ@���7�@vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php���mZ�wu�{�Dvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php���mZ���]�Fvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php?��mZ?K���Dvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php���mZ���J�Avendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php:��mZ:��S�-vendor/phpstan/phpdoc-parser/src/Ast/Node.php���mZ���R+�Cvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.phpP��mZP5{a�Cvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php���mZ��j2o�Bvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.phpZ��mZZ|?��Kvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php���mZ��J�ɶAvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php'��mZ'�`��?vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php���mZ�����:vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.phpp��mZp�1*�=vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php���mZ�Yʔ�Bvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php���mZ��fc:�>vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php4��mZ4
j�w�Dvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php���mZ��\�g�Bvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php���mZ�讉�Bvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php���mZ�xb���?vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php���mZ���u<�;vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php5��mZ5|�Y��=vendor/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php���mZ��K�@vendor/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php/��mZ/�;���Bvendor/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.phpU��mZU�Vdt�>vendor/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php7��mZ7?oe5�:vendor/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php���mZ�74��6vendor/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php���mZ�7P��;vendor/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.phpN��mZN��0vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.phpD��mZD۫��;vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php[��mZ[H�}Z�;vendor/phpstan/phpdoc-parser/src/Parser/ParserException.php���mZ���o0�8vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php���mZ���BZ�9vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.phpk
��mZk
j2gѶ6vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php�
��mZ�
����&vendor/symfony/console/Application.php���mZ�h��I�#vendor/symfony/console/CHANGELOG.md���mZ�d�>�*vendor/symfony/console/Command/Command.phpwK��mZwK��̶.vendor/symfony/console/Command/HelpCommand.php\
��mZ\
C��.vendor/symfony/console/Command/ListCommand.php�
��mZ�
��$�0vendor/symfony/console/Command/LockableTrait.php��mZh|9��?vendor/symfony/console/CommandLoader/CommandLoaderInterface.phpU��mZU���?vendor/symfony/console/CommandLoader/ContainerCommandLoader.phpu��mZu�:��=vendor/symfony/console/CommandLoader/FactoryCommandLoader.phpl��mZl���0�(vendor/symfony/console/ConsoleEvents.php/��mZ/���Dvendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php��mZ�1�Y�<vendor/symfony/console/Descriptor/ApplicationDescription.php���mZ����=�0vendor/symfony/console/Descriptor/Descriptor.php�
��mZ�
� ��9vendor/symfony/console/Descriptor/DescriptorInterface.php���mZ���x�4vendor/symfony/console/Descriptor/JsonDescriptor.php���mZ�"Ɠ��8vendor/symfony/console/Descriptor/MarkdownDescriptor.php���mZ�z�Y��4vendor/symfony/console/Descriptor/TextDescriptor.php�3��mZ�3)�p�3vendor/symfony/console/Descriptor/XmlDescriptor.php�%��mZ�%�L%2�4vendor/symfony/console/Event/ConsoleCommandEvent.phpb��mZb����2vendor/symfony/console/Event/ConsoleErrorEvent.php���mZ�˹��-vendor/symfony/console/Event/ConsoleEvent.php���mZ���w�6vendor/symfony/console/Event/ConsoleExceptionEvent.php���mZ�c%��6vendor/symfony/console/Event/ConsoleTerminateEvent.phpM��mZM�ƶ6vendor/symfony/console/EventListener/ErrorListener.php�
��mZ�
GϨ��=vendor/symfony/console/Exception/CommandNotFoundException.php��mZOa���7vendor/symfony/console/Exception/ExceptionInterface.php���mZ���K�=vendor/symfony/console/Exception/InvalidArgumentException.php���mZ��n�8�;vendor/symfony/console/Exception/InvalidOptionException.php=��mZ=R���3vendor/symfony/console/Exception/LogicException.php���mZ�Ϋ�5vendor/symfony/console/Exception/RuntimeException.php���mZ�N���4vendor/symfony/console/Formatter/OutputFormatter.php���mZ�E�d�=vendor/symfony/console/Formatter/OutputFormatterInterface.php���mZ�^��%�9vendor/symfony/console/Formatter/OutputFormatterStyle.phpO��mZOkyk�Bvendor/symfony/console/Formatter/OutputFormatterStyleInterface.phpE��mZE�н�>vendor/symfony/console/Formatter/OutputFormatterStyleStack.php�
��mZ�
A��6vendor/symfony/console/Helper/DebugFormatterHelper.php���mZ����Ƕ2vendor/symfony/console/Helper/DescriptorHelper.php8
��mZ8
��@�1vendor/symfony/console/Helper/FormatterHelper.php���mZ�8�Η�(vendor/symfony/console/Helper/Helper.phpp��mZp�ж1vendor/symfony/console/Helper/HelperInterface.php���mZ�e�U�+vendor/symfony/console/Helper/HelperSet.php�	��mZ�	��y�2vendor/symfony/console/Helper/InputAwareHelper.php��mZl10)�/vendor/symfony/console/Helper/ProcessHelper.phpL��mZL	m��-vendor/symfony/console/Helper/ProgressBar.php�G��mZ�G����3vendor/symfony/console/Helper/ProgressIndicator.php!��mZ!W�)��0vendor/symfony/console/Helper/QuestionHelper.php?<��mZ?<t����7vendor/symfony/console/Helper/SymfonyQuestionHelper.phpd��mZddvG�'vendor/symfony/console/Helper/Table.php�R��mZ�R�ݲ߶+vendor/symfony/console/Helper/TableCell.phpw��mZwE�)�0vendor/symfony/console/Helper/TableSeparator.phpV��mZV�d‘�,vendor/symfony/console/Helper/TableStyle.php���mZ���V�*vendor/symfony/console/Input/ArgvInput.php,��mZ,
a$¶+vendor/symfony/console/Input/ArrayInput.phpt��mZt�Փ�&vendor/symfony/console/Input/Input.php���mZ�fn�.vendor/symfony/console/Input/InputArgument.php(
��mZ(
@���4vendor/symfony/console/Input/InputAwareInterface.php���mZ�[U�^�0vendor/symfony/console/Input/InputDefinition.php�-��mZ�-J�c��/vendor/symfony/console/Input/InputInterface.php���mZ��SL��,vendor/symfony/console/Input/InputOption.php��mZ|�e�9vendor/symfony/console/Input/StreamableInputInterface.php���mZ�ZDD��,vendor/symfony/console/Input/StringInput.php�	��mZ�	U�q�vendor/symfony/console/LICENSE+��mZ+���g�/vendor/symfony/console/Logger/ConsoleLogger.php���mZ���`�0vendor/symfony/console/Output/BufferedOutput.php���mZ��ZPJ�/vendor/symfony/console/Output/ConsoleOutput.php���mZ�d=�]�8vendor/symfony/console/Output/ConsoleOutputInterface.phpL��mZL@����,vendor/symfony/console/Output/NullOutput.php���mZ��^�F�(vendor/symfony/console/Output/Output.phpf��mZf�߈W�1vendor/symfony/console/Output/OutputInterface.php	
��mZ	
#*��.vendor/symfony/console/Output/StreamOutput.php
��mZ
�L�}�2vendor/symfony/console/Question/ChoiceQuestion.phpV��mZV��ζ8vendor/symfony/console/Question/ConfirmationQuestion.php\��mZ\'��,vendor/symfony/console/Question/Question.phpE��mZE�ڶ vendor/symfony/console/README.md���mZ�!'�k�4vendor/symfony/console/Resources/bin/hiddeninput.exe$��mZ$���v�,vendor/symfony/console/Style/OutputStyle.phpE��mZE߉T�/vendor/symfony/console/Style/StyleInterface.php`��mZ`��\�-vendor/symfony/console/Style/SymfonyStyle.phpn0��mZn0O����#vendor/symfony/console/Terminal.php���mZ�
�/�3vendor/symfony/console/Tester/ApplicationTester.php��mZ�V��/vendor/symfony/console/Tester/CommandTester.phpf��mZfd�y�$vendor/symfony/console/composer.json���mZ�u\'vendor/symfony/console/phpunit.xml.dist���mZ����f�"vendor/symfony/finder/CHANGELOG.md���mZ��/!�/vendor/symfony/finder/Comparator/Comparator.php��mZ�]G׶3vendor/symfony/finder/Comparator/DateComparator.php���mZ��t6��5vendor/symfony/finder/Comparator/NumberComparator.phpT
��mZT
�����9vendor/symfony/finder/Exception/AccessDeniedException.php���mZ�綬�6vendor/symfony/finder/Exception/ExceptionInterface.php0��mZ0�啶 vendor/symfony/finder/Finder.php�K��mZ�K;�vendor/symfony/finder/Glob.php���mZ��7���7vendor/symfony/finder/Iterator/CustomFilterIterator.php+��mZ+!�J�:vendor/symfony/finder/Iterator/DateRangeFilterIterator.php���mZ��n#�;vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php	��mZ	�߶Avendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php�	��mZ�	+&U�9vendor/symfony/finder/Iterator/FileTypeFilterIterator.php}��mZ}��a�<vendor/symfony/finder/Iterator/FilecontentFilterIterator.php���mZ����߶9vendor/symfony/finder/Iterator/FilenameFilterIterator.php���mZ���B��1vendor/symfony/finder/Iterator/FilterIterator.php��mZt;��=vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php���mZ�G5<�5vendor/symfony/finder/Iterator/PathFilterIterator.php���mZ�鐿j�=vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php���mZ��u�Q�:vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php���mZ���
Ķ3vendor/symfony/finder/Iterator/SortableIterator.php*
��mZ*
�"��vendor/symfony/finder/LICENSE+��mZ+���g�vendor/symfony/finder/README.md���mZ�#L�%vendor/symfony/finder/SplFileInfo.phph��mZhY�i�#vendor/symfony/finder/composer.json���mZ�g��x�&vendor/symfony/finder/phpunit.xml.distA��mZAf"%`�(vendor/symfony/polyfill-mbstring/LICENSE+��mZ+%*߱�-vendor/symfony/polyfill-mbstring/Mbstring.php�V��mZ�V�WA�*vendor/symfony/polyfill-mbstring/README.mds��mZs!�wg�@vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php�I��mZ�I�҈�@vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php9J��mZ9J|Q��.vendor/symfony/polyfill-mbstring/bootstrap.php��mZ���.vendor/symfony/polyfill-mbstring/composer.jsono��mZo����# Backers

Development of PHPStan is made possible thanks to these awesome backers!
You can become one of them by [pledging on Patreon](https://www.patreon.com/phpstan).

Check out all the tiers - higher ones include additional goodies like placing
the logo of your company in PHPStan's README.

# $50+

* MessageBird

# $10+

* Scott Arciszewski
* Tomáš Votruba
* Adam Lundrigan
* Jobs Dev

# $5+

* Pavel Vondrášek
* Haralan Dobrev
* Tomas Pesek
* Jan Kuchař
* Sebastian Bergmann
* Oleg Samorai
* Lukas Unger
* Masaru Yamagishi
* Vašek Brychta
* Tommy Muehle
* Stefan Zielke
* Dennis Haarbrink
* Jakub Chábek
* Carlos C Soto
* Jan Endel
* Adam Žurek

# $1+

* Oliver Klee
* Bronek Bialek
* Rudolph Gottesheim
* Ian Den Hartog
* Andrew Barlow
* Michal Mleczko
* Lucas Dos Santos Abreu
* Martin Lukeš
* Ondřej Vodáček
# Contributor Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
  address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project maintainer at <ondrej@mirtes.cz>. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]

[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

MIT License

Copyright (c) 2016 Ondřej Mirtes

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

# PHPStan - PHP Static Analysis Tool

[![Build Status](https://travis-ci.org/phpstan/phpstan.svg)](https://travis-ci.org/phpstan/phpstan)
[![Latest Stable Version](https://poser.pugx.org/phpstan/phpstan/v/stable)](https://packagist.org/packages/phpstan/phpstan)
[![License](https://poser.pugx.org/phpstan/phpstan/license)](https://packagist.org/packages/phpstan/phpstan)
[![PHPStan](https://img.shields.io/badge/PHPStan-enabled-brightgreen.svg?style=flat)](https://github.com/phpstan/phpstan)

[![Donate on PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://paypal.me/phpstan)

PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs
even before you write tests for the code.

![PHPStan](build/phpstan.gif)

PHPStan moves PHP closer to compiled languages in the sense that the correctness of each line of the code
can be checked before you run the actual line.

**[Read more about PHPStan on Medium.com »](https://medium.com/@ondrejmirtes/phpstan-2939cd0ad0e3)**

**[Try out PHPStan on the on-line playground! »](https://phpstan.org/)**

## Is PHPStan helping you to avoid bugs in production?
## Consider [supporting it on Patreon](https://www.patreon.com/phpstan) so I'm able to make it even more awesome!

*I offer to issue invoices for contributions on PayPal and Patreon! [Contact me](mailto:ondrej@mirtes.cz) for details.*

It currently performs the following checks on your code:

* Existence of classes and interfaces in `instanceof`, `catch`, typehints, other language constructs and even annotations. PHP does not do this and just stays silent instead.
* Existence of variables while respecting scopes of branches and loops.
* Existence and visibility of called methods and functions.
* Existence and visibility of accessed properties and constants.
* Correct types assigned to properties.
* Correct number and types of parameters passed to constructors, methods and functions.
* Correct types returned from methods and functions.
* Correct number of parameters passed to `sprintf`/`printf` calls based on format strings.
* Useless casts like `(string) 'foo'`.
* Unused constructor parameters - they can either be deleted or the author forgot to
use them in the method body.
* Require calling `parent::__construct()` if the parent constructor exists.
* Only valid array key types are used (only integers, strings, floats, booleans and nulls).
* Duplicate array keys in literal arrays.
* Only iterables are passed to `foreach`.
* Correct case when referencing classes. Class names are case insensitive, but taking advantage of this is dangerous with autoloading on case-insensitive filesystems.
* Impossible checks (dead code) of incompatible types with `instanceof`, `===`, `!==` and various function checks like `is_int` or `is_null`.
* Always-defined and never-defined variables in `isset()` call.
* Validating phpDocs - finding incompatible types between phpDocs and native typehints.
* That only objects are passed to the `clone` keyword.

## Extensibility

Unique feature of PHPStan is the ability to define and statically check "magic" behaviour of classes -
accessing properties that are not defined in the class but are created in `__get` and `__set`
and invoking methods using `__call`.

See [Class reflection extensions](#class-reflection-extensions) and [Dynamic return type extensions](#dynamic-return-type-extensions).

You can also install official framework-specific extensions:

* [Doctrine](https://github.com/phpstan/phpstan-doctrine)
* [PHPUnit](https://github.com/phpstan/phpstan-phpunit)
* [Nette Framework](https://github.com/phpstan/phpstan-nette)
* [Dibi - Database Abstraction Library](https://github.com/phpstan/phpstan-dibi)
* [PHP-Parser](https://github.com/phpstan/phpstan-php-parser)

Unofficial extensions for other frameworks and libraries are also available:

* [Phony](https://github.com/eloquent/phpstan-phony)
* [Symfony Framework](https://github.com/lookyman/phpstan-symfony)
* [Prophecy](https://github.com/Jan0707/phpstan-prophecy)

New extensions are becoming available on a regular basis!

## Prerequisites

PHPStan requires PHP >= 7.0. You have to run it in environment with PHP 7.x but the actual code does not have to use
PHP 7.x features. (Code written for PHP 5.6 and earlier can run on 7.x mostly unmodified.)

PHPStan works best with modern object-oriented code. The more strongly-typed your code is, the more information
you give PHPStan to work with.

Properly annotated and typehinted code (class properties, function and method arguments, return types) helps
not only static analysis tools but also other people that work with the code to understand it.

## Installation

To start performing analysis on your code, require PHPStan in [Composer](https://getcomposer.org/):

```
composer require --dev phpstan/phpstan
```

Composer will install PHPStan's executable in its `bin-dir` which defaults to `vendor/bin`.

If you have conflicting dependencies or you want to install PHPStan globally, the best way is via a PHAR archive. You will always find the latest stable PHAR archive below the [release notes](https://github.com/phpstan/phpstan/releases). You can also use the [phpstan/phpstan-shim](https://packagist.org/packages/phpstan/phpstan-shim) package to install PHPStan via Composer without the risk of conflicting dependencies.

You can also use [PHPStan via Docker](https://github.com/phpstan/docker-image).

## First run

To let PHPStan analyse your codebase, you have use the `analyse` command and point it to the right directories.

So, for example if you have your classes in directories `src` and `tests`, you can run PHPStan like this:

```bash
vendor/bin/phpstan analyse src tests
```

PHPStan will probably find some errors, but don't worry, your code might be just fine. Errors found
on the first run tend to be:

* Extra arguments passed to functions (e. g. function requires two arguments, the code passes three)
* Extra arguments passed to print/sprintf functions (e. g. format string contains one placeholder, the code passes two values to replace)
* Obvious errors in dead code
* Magic behaviour that needs to be defined. See [Extensibility](#extensibility).

After fixing the obvious mistakes in the code, look to the following section
for all the configuration options that will bring the number of reported errors to zero
making PHPStan suitable to run as part of your continuous integration script.

## Rule levels

If you want to use PHPStan but your codebase isn't up to speed with strong typing
and PHPStan's strict checks, you can choose from currently 8 levels
(0 is the loosest and 7 is the strictest) by passing `--level` to `analyse` command. Default level is `0`.

This feature enables incremental adoption of PHPStan checks. You can start using PHPStan
with a lower rule level and increase it when you feel like it.

You can also use `--level max` as an alias for the highest level. This will ensure that you will always use the highest level when upgrading to new versions of PHPStan. Please note that this can create a significant obstacle when upgrading to a newer version because you might have to fix a lot of code to bring the number of errors down to zero.

## Configuration

Config file is passed to the `phpstan` executable with `-c` option:

```bash
vendor/bin/phpstan analyse -l 4 -c phpstan.neon src tests
```

When using a custom project config file, you have to pass the `--level` (`-l`)
option to `analyse` command (default value does not apply here).

[NEON file format](https://ne-on.org/) is very similar to YAML.
All the following options are part of the `parameters` section.

### Autoloading

PHPStan uses Composer autoloader so the easiest way how to autoload classes
is through the `autoload`/`autoload-dev` sections in composer.json.

#### Specify paths to scan

If PHPStan complains about some non-existent classes and you're sure the classes
exist in the codebase AND you don't want to use Composer autoloader for some reason,
you can specify directories to scan and concrete files to include using
`autoload_directories` and `autoload_files` array parameters:

```
parameters:
	autoload_directories:
		- %rootDir%/../../../build
	autoload_files:
		- %rootDir%/../../../generated/routes/GeneratedRouteList.php
```

`%rootDir%` is expanded to the root directory where PHPStan resides.

#### Autoloading for global installation

PHPStan supports global installation using [`composer global`](https://getcomposer.org/doc/03-cli.md#global) or via a [PHAR archive](#installation).
In this case, it's not part of the project autoloader, but it supports autodiscovery of the Composer autoloader
from current working directory residing in `vendor/`:

```bash
cd /path/to/project
phpstan analyse src tests # looks for autoloader at /path/to/project/vendor/autoload.php
```

If you have your dependencies installed at a different path
or you're running PHPStan from a different directory,
you can specify the path to the autoloader with the `--autoload-file|-a` option:

```bash
phpstan analyse --autoload-file=/path/to/autoload.php src tests
```

### Exclude files from analysis

If your codebase contains some files that are broken on purpose
(e. g. to test behaviour of your application on files with invalid PHP code),
you can exclude them using the `excludes_analyse` array parameter. String at each line
is used as a pattern for the [`fnmatch`](https://secure.php.net/manual/en/function.fnmatch.php) function.

```
parameters:
	excludes_analyse:
		- %rootDir%/../../../tests/*/data/*
```

### Include custom extensions

If your codebase contains php files with extensions other than the standard .php extension then you can add them
to the `fileExtensions` array parameter:

```
parameters:
	fileExtensions:
		- php
		- module
		- inc
```

### Universal object crates

Classes without predefined structure are common in PHP applications.
They are used as universal holders of data - any property can be set and read on them. Notable examples
include `stdClass`, `SimpleXMLElement` (these are enabled by default), objects with results of database queries etc.
Use `universalObjectCratesClasses` array parameter to let PHPStan know which classes
with these characteristics are used in your codebase:

```
parameters:
	universalObjectCratesClasses:
		- Dibi\Row
		- Ratchet\ConnectionInterface
```

### Add non-obviously assigned variables to scope

If you use some variables from a try block in your catch blocks, set `polluteCatchScopeWithTryAssignments` boolean parameter to `true`.

```php
try {
	$author = $this->getLoggedInUser();
	$post = $this->postRepository->getById($id);
} catch (PostNotFoundException $e) {
	// $author is probably defined here
	throw new ArticleByAuthorCannotBePublished($author);
}
```

If you are enumerating over all possible situations in if-elseif branches
and PHPStan complains about undefined variables after the conditions, you can write
an else branch with throwing an exception:

```php
if (somethingIsTrue()) {
	$foo = true;
} elseif (orSomethingElseIsTrue()) {
	$foo = false;
} else {
	throw new ShouldNotHappenException();
}

doFoo($foo);
```

I recommend leaving `polluteCatchScopeWithTryAssignments` set to `false` because it leads to a clearer and more maintainable code.

### Custom early terminating method calls

Previous example showed that if a condition branches end with throwing an exception, that branch does not have
to define a variable used after the condition branches end.

But exceptions are not the only way how to terminate execution of a method early. Some specific method calls
can be perceived by project developers also as early terminating - like a `redirect()` that stops execution
by throwing an internal exception.

```php
if (somethingIsTrue()) {
	$foo = true;
} elseif (orSomethingElseIsTrue()) {
	$foo = false;
} else {
	$this->redirect('homepage');
}

doFoo($foo);
```

These methods can be configured by specifying a class on whose instance they are called like this:

```
parameters:
	earlyTerminatingMethodCalls:
		Nette\Application\UI\Presenter:
			- redirect
			- redirectUrl
			- sendJson
			- sendResponse
```

### Ignore error messages with regular expresions

If some issue in your code base is not easy to fix or just simply want to deal with it later,
you can exclude error messages from the analysis result with regular expressions:

```
parameters:
	ignoreErrors:
		- '#Call to an undefined method [a-zA-Z0-9\\_]+::method\(\)#'
		- '#Call to an undefined method [a-zA-Z0-9\\_]+::expects\(\)#'
		- '#Access to an undefined property PHPUnit_Framework_MockObject_MockObject::\$[a-zA-Z0-9_]+#'
		- '#Call to an undefined method PHPUnit_Framework_MockObject_MockObject::[a-zA-Z0-9_]+\(\)#'
```

If some of the patterns do not occur in the result anymore, PHPStan will let you know
and you will have to remove the pattern from the configuration. You can turn off
this behaviour by setting `reportUnmatchedIgnoredErrors` to `false` in PHPStan configuration.

### Bootstrap file

If you need to initialize something in PHP runtime before PHPStan runs (like your own autoloader),
you can provide your own bootstrap file:

```
parameters:
	bootstrap: %rootDir%/../../../phpstan-bootstrap.php
```

### Custom rules

PHPStan allows writing custom rules to check for specific situations in your own codebase. Your rule class
needs to implement the `PHPStan\Rules\Rule` interface and registered as a service in the configuration file:

```
services:
	-
		class: MyApp\PHPStan\Rules\DefaultValueTypesAssignedToPropertiesRule
		tags:
			- phpstan.rules.rule
```

For inspiration on how to implement a rule turn to [src/Rules](https://github.com/phpstan/phpstan/tree/master/src/Rules)
to see a lot of built-in rules.

Check out also [phpstan-strict-rules](https://github.com/phpstan/phpstan-strict-rules) repository for extra strict and opinionated rules for PHPStan!

### Custom error formatters

By default, PHPStan outputs found errors into tables grouped by files to be easily human-readable. To change the output, you can use the `--errorFormat` CLI option. There's an additional built-in `raw` format with one-per-line errors intended for easy parsing. You can also create your own error formatter by implementing the `PHPStan\Command\ErrorFormatter\ErrorFormatter` interface:

```php
interface ErrorFormatter
{

	/**
	 * Formats the errors and outputs them to the console.
	 *
	 * @param \PHPStan\Command\AnalysisResult $analysisResult
	 * @param \Symfony\Component\Console\Style\OutputStyle $style
	 * @return int Error code.
	 */
	public function formatErrors(
		AnalysisResult $analysisResult,
		\Symfony\Component\Console\Style\OutputStyle $style
	): int;

}
```

Register the formatter in your `phpstan.neon`:

```
errorFormatter.awesome:
	class: App\PHPStan\AwesomeErrorFormatter
```

Use the name part after `errorFormatter.` as the CLI option value:

```bash
vendor/bin/phpstan analyse -c phpstan.neon -l 4 --errorFormat awesome src tests
```

## Class reflection extensions

Classes in PHP can expose "magical" properties and methods decided in run-time using
class methods like `__get`, `__set` and `__call`. Because PHPStan is all about static analysis
(testing code for errors without running it), it has to know about those properties and methods beforehand.

When PHPStan stumbles upon a property or a method that is unknown to built-in class reflection, it iterates
over all registered class reflection extensions until it finds one that defines the property or method.

Class reflection extension cannot have `PHPStan\Broker\Broker` (service for obtaining class reflections) injected in the constructor due to circular reference issue, but the extensions can implement `PHPStan\Reflection\BrokerAwareClassReflectionExtension` interface to obtain Broker via a setter.

### Properties class reflection extensions

This extension type must implement the following interface:

```php
namespace PHPStan\Reflection;

interface PropertiesClassReflectionExtension
{

	public function hasProperty(ClassReflection $classReflection, string $propertyName): bool;

	public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection;

}
```

Most likely you will also have to implement a new `PropertyReflection` class:

```php
namespace PHPStan\Reflection;

interface PropertyReflection
{

	public function getType(): Type;

	public function getDeclaringClass(): ClassReflection;

	public function isStatic(): bool;

	public function isPrivate(): bool;

	public function isPublic(): bool;

}
```

This is how you register the extension in project's PHPStan config file:

```
services:
	-
		class: App\PHPStan\PropertiesFromAnnotationsClassReflectionExtension
		tags:
			- phpstan.broker.propertiesClassReflectionExtension
```

### Methods class reflection extensions

This extension type must implement the following interface:

```php
namespace PHPStan\Reflection;

interface MethodsClassReflectionExtension
{

	public function hasMethod(ClassReflection $classReflection, string $methodName): bool;

	public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection;

}
```

Most likely you will also have to implement a new `MethodReflection` class:

```php
namespace PHPStan\Reflection;

interface MethodReflection
{

	public function getDeclaringClass(): ClassReflection;

	public function getPrototype(): self;

	public function isStatic(): bool;

	public function isPrivate(): bool;

	public function isPublic(): bool;

	public function getName(): string;

	/**
	 * @return \PHPStan\Reflection\ParameterReflection[]
	 */
	public function getParameters(): array;

	public function isVariadic(): bool;

	public function getReturnType(): Type;

}
```

This is how you register the extension in project's PHPStan config file:

```
services:
	-
		class: App\PHPStan\EnumMethodsClassReflectionExtension
		tags:
			- phpstan.broker.methodsClassReflectionExtension
```

## Dynamic return type extensions

If the return type of a method is not always the same, but depends on an argument passed to the method,
you can specify the return type by writing and registering an extension.

Because you have to write the code with the type-resolving logic, it can be as complex as you want.

After writing the sample extension, the variable `$mergedArticle` will have the correct type:

```php
$mergedArticle = $this->entityManager->merge($article);
// $mergedArticle will have the same type as $article
```

This is the interface for dynamic return type extension:

```php
namespace PHPStan\Type;

use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;

interface DynamicMethodReturnTypeExtension
{

	public function getClass(): string;

	public function isMethodSupported(MethodReflection $methodReflection): bool;

	public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type;

}
```

And this is how you'd write the extension that correctly resolves the EntityManager::merge() return type:

```php
public function getClass(): string
{
	return \Doctrine\ORM\EntityManager::class;
}

public function isMethodSupported(MethodReflection $methodReflection): bool
{
	return $methodReflection->getName() === 'merge';
}

public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type
{
	if (count($methodCall->args) === 0) {
		return $methodReflection->getReturnType();
	}
	$arg = $methodCall->args[0]->value;

	return $scope->getType($arg);
}
```

And finally, register the extension to PHPStan in the project's config file:

```
services:
	-
		class: App\PHPStan\EntityManagerDynamicReturnTypeExtension
		tags:
			- phpstan.broker.dynamicMethodReturnTypeExtension
```

There's also an analogous functionality for:

* **static methods** using `DynamicStaticMethodReturnTypeExtension` interface
and `phpstan.broker.dynamicStaticMethodReturnTypeExtension` service tag.
* **functions** using `DynamicFunctionReturnTypeExtension` interface and `phpstan.broker.dynamicFunctionReturnTypeExtension` service tag.

## Known issues

* If `include` or `require` are used in the analysed code (instead of `include_once` or `require_once`),
PHPStan will throw `Cannot redeclare class` error. Use the `_once` variants to avoid this error.
* If PHPStan crashes without outputting any error, it's quite possible that it's
because of a low memory limit set on your system. **Run PHPStan again** to read a couple of hints
what you can do to prevent the crashes.

## Code of Conduct

This project adheres to a [Contributor Code of Conduct](https://github.com/phpstan/phpstan/blob/master/CODE_OF_CONDUCT.md). By participating in this project and its community, you are expected to uphold this code.

## Contributing

Any contributions are welcome.

### Building

You can either run the whole build including linting and coding standards using

```bash
vendor/bin/phing
```

or run only tests using

```bash
vendor/bin/phing tests
```
build: false
clone_depth: 50
platform:
  - x64
environment:
  matrix:
    - dependencies: lowest
      php_version: 7.0
    - dependencies: highest
      php_version: 7.0
    - dependencies: lowest
      php_version: 7.1
    - dependencies: highest
      php_version: 7.1

  project_directory: c:\projects\phpstan
  composer_directory: c:\tools\composer
  composer_executable: c:\tools\composer\composer.phar
  php_archive_directory: c:\tools\php-archive
  php_directory: c:\tools\php
clone_folder: c:\projects\phpstan
cache:
  - c:\tools\composer
  - c:\tools\php-archive
  - '%LOCALAPPDATA%\Composer'
init:
  - ps: $Env:PATH = $Env:php_directory + ';' + $Env:composer_directory + ';' + $Env:PATH
  - ps: $Env:ANSICON = '121x90 (121x90)'
install:
  # Download requested PHP version
  - ps: If ((Test-Path $Env:php_archive_directory) -eq $False) { New-Item -Path $Env:php_archive_directory -ItemType 'directory' }
  - ps: $requested_php_version = %{If ($Env:dependencies -eq 'lowest') { $Env:php_version + '.0' } Else { (((choco search php --exact --all-versions -r | Select-String -pattern $Env:php_version) -replace '[php|]', '') | %{ New-Object System.Version $_ } | Sort-Object | Select-Object -Last 1).ToString() }}
  - ps: $php_version_url = %{If ($Env:dependencies -eq 'lowest') { 'http://windows.php.net/downloads/releases/archives/php-' + $requested_php_version + '-nts-Win32-VC14-' + $Env:platform + '.zip' } Else { 'http://windows.php.net/downloads/releases/php-' + $requested_php_version + '-nts-Win32-VC14-' + $Env:platform + '.zip' }}
  - ps: $php_version_file = $Env:php_archive_directory + '\php-' + $requested_php_version + '.zip'
  - ps: If ((Test-Path $php_version_file) -eq $False) { appveyor-retry appveyor DownloadFile $php_version_url -FileName $php_version_file }

  # Prepare PHP
  - ps: New-Item -Path $Env:php_directory -ItemType 'directory'
  - ps: cd $Env:php_directory
  - ps: 7z x $php_version_file
  - ps: Copy-Item php.ini-production -Destination php.ini
  - ps: Add-Content -Path php.ini -Value 'memory_limit=1G'
  - ps: Add-Content -Path php.ini -Value 'date.timezone="UTC"'
  - ps: Add-Content -Path php.ini -Value 'extension_dir=ext'
  - ps: Add-Content -Path php.ini -Value 'extension=php_curl.dll'
  - ps: Add-Content -Path php.ini -Value 'extension=php_intl.dll'
  - ps: Add-Content -Path php.ini -Value 'extension=php_mbstring.dll'
  - ps: Add-Content -Path php.ini -Value 'extension=php_openssl.dll'
  - ps: Add-Content -Path php.ini -Value 'extension=php_gd2.dll'
  - ps: Add-Content -Path php.ini -Value 'extension=php_mysqli.dll'
  - ps: php --version

  # Prepare composer
  - ps: If ((Test-Path $Env:composer_directory) -eq $False) { New-Item -Path $Env:composer_directory -ItemType 'directory' }
  - ps: If ((Test-Path $Env:composer_executable) -eq $False) { appveyor-retry appveyor DownloadFile https://getcomposer.org/composer.phar -FileName $Env:composer_executable }
  - ps: Set-Content -Path ($Env:composer_directory + '\composer.bat') -Value ('@php ' + $Env:composer_executable + ' %*')
  - composer self-update

  # Install dependencies
  - ps: cd $Env:project_directory
  - IF %dependencies%==lowest composer update --prefer-lowest --no-interaction --no-progress
  - IF %dependencies%==highest composer update --no-interaction --no-progress

  # Apply patch to jakub-onderka/php-parallel-lint
  - ps: appveyor-retry appveyor DownloadFile https://github.com/slevomat/PHP-Parallel-Lint/commit/50e939edf81619be100186f9c6192d97decad173.diff -FileName php-parallel-lint.patch
  - git apply --directory vendor/jakub-onderka/php-parallel-lint -p1 --unsafe-paths --verbose php-parallel-lint.patch
  - ps: Remove-Item -Path php-parallel-lint.patch
test_script:
  - ps: cd $Env:project_directory
  - vendor\bin\phing
<?php declare(strict_types=1);

use PHPStan\Command\AnalyseCommand;

gc_disable(); // performance boost

$autoloaderInWorkingDirectory = getcwd() . '/vendor/autoload.php';
if (is_file($autoloaderInWorkingDirectory)) {
	require_once $autoloaderInWorkingDirectory;
}

if (!class_exists('PHPStan\Command\AnalyseCommand', true)) {
	$composerAutoloadFile = 'phar://phpstan.phar/vendor/autoload.php';
	if (!is_file($composerAutoloadFile)) {
		$composerAutoloadFile = 'phar://phpstan.phar/../../autoload.php';
	}

	require_once $composerAutoloadFile;
}

$version = 'Version unknown';
try {
	$version = \PHPStanVendor\Jean85\PrettyVersions::getVersion('phpstan/phpstan')->getPrettyVersion();
} catch (\OutOfBoundsException $e) {

}

$application = new \PHPStanVendor\Symfony\Component\Console\Application(
	'PHPStan - PHP Static Analysis Tool',
	$version
);
$application->setCatchExceptions(false);
$application->add(new \PHPStan\Command\AnalyseCommand());
$application->run();
<?xml version="1.0" encoding="utf-8"?>
<project name="PHPStan" default="check">

	<target name="check" depends="
		composer-validate,
		composer-install,
		lint,
		cs,
		tests,
		phpstan
	"/>

	<target name="composer-validate">
		<exec
				executable="composer"
				logoutput="true"
				passthru="true"
				checkreturn="true"
		>
			<arg value="validate"/>
		</exec>
	</target>

	<target name="composer-install">
		<exec
				executable="composer"
				logoutput="true"
				passthru="true"
				checkreturn="true"
		>
			<arg value="install"/>
		</exec>
	</target>

	<target name="lint">
		<exec
				executable="vendor/bin/parallel-lint"
				logoutput="true"
				passthru="true"
				checkreturn="true"
		>
			<arg value="--exclude"/>
			<arg path="tests/PHPStan/Analyser/data"/>
			<arg value="--exclude"/>
			<arg path="tests/PHPStan/Rules/Methods/data"/>
			<arg value="--exclude"/>
			<arg path="tests/PHPStan/Rules/Functions/data"/>
			<arg path="src" />
			<arg path="tests" />
		</exec>
	</target>

	<target name="cs">
		<exec
				executable="vendor/bin/phpcs"
				logoutput="true"
				passthru="true"
				checkreturn="true"
		>
			<arg value="--extensions=php"/>
			<arg value="--encoding=utf-8"/>
			<arg value="--tab-width=4"/>
			<arg value="--ignore=tests/*/data,tests/*/traits"/>
			<arg value="-sp"/>
			<arg path="src"/>
			<arg path="tests"/>
		</exec>
	</target>

	<target name="cs-fix">
		<exec
				executable="vendor/bin/phpcbf"
				logoutput="true"
				passthru="true"
				checkreturn="true"
		>
			<arg value="--extensions=php"/>
			<arg value="--encoding=utf-8"/>
			<arg value="--tab-width=4"/>
			<arg value="--ignore=tests/*/data,tests/*/traits"/>
			<arg value="-sp"/>
			<arg path="src"/>
			<arg path="tests"/>
		</exec>
	</target>

	<target name="tests">
		<exec
				executable="vendor/bin/phpunit"
				logoutput="true"
				passthru="true"
				checkreturn="true"
		>
			<arg value="-c"/>
			<arg value="tests/phpunit.xml"/>
			<arg path="tests"/>
		</exec>
	</target>

	<target name="phpstan">
		<php expression="PHP_VERSION_ID &lt; 70100 ?'true':'false'" returnProperty="isPHP70" level="verbose" />
		<property name="phpstan.config" value="build/phpstan-generated.neon"/>
		<touch file="${phpstan.config}"/>
		<append
			destFile="${phpstan.config}"
			text="includes: [ phpstan.neon"
			append="false"
		></append>
		<if>
			<os family="windows" />
			<then>
				<append
						destFile="${phpstan.config}"
						text=", ignore-windows-errors.neon"
				></append>
			</then>
		</if>
		<if>
			<equals arg1="${isPHP70}" arg2="true" />
			<then>
				<append
						destFile="${phpstan.config}"
						text=", ignore-php7.0-errors.neon"
				></append>
			</then>
		</if>
		<append
				destFile="${phpstan.config}"
				text=" ]"
		></append>
		<exec
				executable="php"
				logoutput="true"
				passthru="true"
				checkreturn="true"
		>
			<arg path="bin/phpstan"/>
			<arg value="analyse"/>
			<arg value="-c"/>
			<arg path="${phpstan.config}"/>
			<arg value="-l"/>
			<arg value="7"/>
			<arg path="src"/>
			<arg path="tests"/>
		</exec>
	</target>

</project>
{
    "name": "phpstan/phpstan",
    "description": "PHPStan - PHP Static Analysis Tool",
    "license": [
        "MIT"
    ],
    "bin": [
        "bin/phpstan"
    ],
    "extra": {
        "branch-alias": {
            "dev-master": "0.9-dev"
        }
    },
    "require": {
        "php": "~7.0",
        "nette/bootstrap": "^2.4 || ^3.0",
        "nette/di": "^2.4.7 || ^3.0",
        "nette/robot-loader": "^3.0.1",
        "nette/utils": "^2.4.5 || ^3.0",
        "nikic/php-parser": "^3.1",
        "symfony/console": "~3.2",
        "symfony/finder": "~3.2",
        "jean85/pretty-package-versions": "^1.0.3",
        "phpstan/phpdoc-parser": "^0.2",
        "dg/composer-cleaner": "^1.0",
        "phpstan/package-patches": "^1.0"
    },
    "autoload": {
        "psr-4": {
            "PHPStan\\": [
                "src/",
                "build/PHPStan"
            ]
        },
        "classmap": [
            "vendor"
        ]
    },
    "autoloader-suffix": "PhpStanPhare59541bcc7cac9b35ca54db6365bf377baf4a488",
    "config": {
        "cleaner-ignore": {
            "phpstan/phpstan-doctrine": [
                "extension.neon",
                "rules.neon"
            ],
            "phpstan/phpstan-guzzle": [
                "extension.neon",
                "rules.neon"
            ],
            "phpstan/phpstan-nette": [
                "extension.neon",
                "rules.neon"
            ],
            "phpstan/phpstan-dibi": [
                "extension.neon",
                "rules.neon"
            ]
        }
    },
    "repositories": [
        {
            "type": "package",
            "package": {
                "type": "metapackage",
                "name": "phpstan/package-patches",
                "version": "1.0.0",
                "require": {
                    "netresearch/composer-patches-plugin": "~1.0"
                },
                "extra": {
                    "patches": {
                        "nette/di": [
                            {
                                "title": "Fixed including of paths with scheme in config loader",
                                "url": "/Users/ondrej/Development/phpstan-compiler/src/Compiler/../../patches/nette/di/include-scheme.patch"
                            }
                        ]
                    }
                }
            }
        }
    ]
}
{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
        "This file is @generated automatically"
    ],
    "content-hash": "ff8a442fee4c9073c627607e2833db09",
    "packages": [
        {
            "name": "dg/composer-cleaner",
            "version": "v1.1",
            "source": {
                "type": "git",
                "url": "https://github.com/dg/composer-cleaner.git",
                "reference": "417979b0169b2fc28fd05e48ceb20f87a3113d4e"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/dg/composer-cleaner/zipball/417979b0169b2fc28fd05e48ceb20f87a3113d4e",
                "reference": "417979b0169b2fc28fd05e48ceb20f87a3113d4e",
                "shasum": ""
            },
            "require": {
                "composer-plugin-api": "^1.0",
                "php": ">=5.4.0"
            },
            "require-dev": {
                "nette/tester": "^1.7"
            },
            "type": "composer-plugin",
            "extra": {
                "class": "DG\\ComposerCleaner\\Plugin"
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "David Grudl",
                    "homepage": "https://davidgrudl.com"
                }
            ],
            "description": "Victor The Cleaner: removes unnecessary files from vendor directory.",
            "keywords": [
                "composer"
            ],
            "time": "2017-05-02T12:58:25+00:00"
        },
        {
            "name": "jean85/pretty-package-versions",
            "version": "1.1",
            "source": {
                "type": "git",
                "url": "https://github.com/Jean85/pretty-package-versions.git",
                "reference": "d457344b6a035ef99236bdda4729ad7eeb233f54"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/d457344b6a035ef99236bdda4729ad7eeb233f54",
                "reference": "d457344b6a035ef99236bdda4729ad7eeb233f54",
                "shasum": ""
            },
            "require": {
                "ocramius/package-versions": "^1.2.0",
                "php": "^7.0"
            },
            "require-dev": {
                "phpunit/phpunit": "^6.0"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Jean85\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Alessandro Lai",
                    "email": "alessandro.lai85@gmail.com"
                }
            ],
            "description": "A wrapper for ocramius/pretty-package-versions to get pretty versions strings",
            "keywords": [
                "composer",
                "package",
                "release",
                "versions"
            ],
            "time": "2018-01-21T13:54:22+00:00"
        },
        {
            "name": "netresearch/composer-patches-plugin",
            "version": "1.2.1",
            "source": {
                "type": "git",
                "url": "https://github.com/netresearch/composer-patches-plugin.git",
                "reference": "3a3de792955eb7e6bad2b5e892b63a1f6d9be000"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/netresearch/composer-patches-plugin/zipball/3a3de792955eb7e6bad2b5e892b63a1f6d9be000",
                "reference": "3a3de792955eb7e6bad2b5e892b63a1f6d9be000",
                "shasum": ""
            },
            "require": {
                "composer-plugin-api": "^1.0"
            },
            "require-dev": {
                "composer/composer": "1.*"
            },
            "type": "composer-plugin",
            "extra": {
                "class": "Netresearch\\Composer\\Patches\\Plugin",
                "branch-alias": {
                    "dev-master": "1.2.x-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "GPL-2.0"
            ],
            "authors": [
                {
                    "name": "Christian Opitz",
                    "email": "christian.opitz@netresearch.de"
                }
            ],
            "description": "Composer patches plugin",
            "keywords": [
                "composer",
                "patches",
                "plugin"
            ],
            "time": "2016-01-06T11:59:02+00:00"
        },
        {
            "name": "nette/bootstrap",
            "version": "v2.4.5",
            "source": {
                "type": "git",
                "url": "https://github.com/nette/bootstrap.git",
                "reference": "804925787764d708a7782ea0d9382a310bb21968"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/nette/bootstrap/zipball/804925787764d708a7782ea0d9382a310bb21968",
                "reference": "804925787764d708a7782ea0d9382a310bb21968",
                "shasum": ""
            },
            "require": {
                "nette/di": "~2.4.7",
                "nette/utils": "~2.4",
                "php": ">=5.6.0"
            },
            "conflict": {
                "nette/nette": "<2.2"
            },
            "require-dev": {
                "latte/latte": "~2.2",
                "nette/application": "~2.3",
                "nette/caching": "~2.3",
                "nette/database": "~2.3",
                "nette/forms": "~2.3",
                "nette/http": "~2.4.0",
                "nette/mail": "~2.3",
                "nette/robot-loader": "^2.4.2 || ^3.0",
                "nette/safe-stream": "~2.2",
                "nette/security": "~2.3",
                "nette/tester": "~2.0",
                "tracy/tracy": "^2.4.1"
            },
            "suggest": {
                "nette/robot-loader": "to use Configurator::createRobotLoader()",
                "tracy/tracy": "to use Configurator::enableTracy()"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.4-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause",
                "GPL-2.0",
                "GPL-3.0"
            ],
            "authors": [
                {
                    "name": "David Grudl",
                    "homepage": "https://davidgrudl.com"
                },
                {
                    "name": "Nette Community",
                    "homepage": "https://nette.org/contributors"
                }
            ],
            "description": "🅱 Nette Bootstrap: the simple way to configure and bootstrap your Nette application.",
            "homepage": "https://nette.org",
            "keywords": [
                "bootstrapping",
                "configurator",
                "nette"
            ],
            "time": "2017-08-20T17:36:59+00:00"
        },
        {
            "name": "nette/di",
            "version": "v2.4.10",
            "source": {
                "type": "git",
                "url": "https://github.com/nette/di.git",
                "reference": "a4b3be935b755f23aebea1ce33d7e3c832cdff98"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/nette/di/zipball/a4b3be935b755f23aebea1ce33d7e3c832cdff98",
                "reference": "a4b3be935b755f23aebea1ce33d7e3c832cdff98",
                "shasum": ""
            },
            "require": {
                "ext-tokenizer": "*",
                "nette/neon": "^2.3.3 || ~3.0.0",
                "nette/php-generator": "^2.6.1 || ~3.0.0",
                "nette/utils": "^2.4.3 || ~3.0.0",
                "php": ">=5.6.0"
            },
            "conflict": {
                "nette/bootstrap": "<2.4",
                "nette/nette": "<2.2"
            },
            "require-dev": {
                "nette/tester": "^2.0",
                "tracy/tracy": "^2.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.4-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause",
                "GPL-2.0",
                "GPL-3.0"
            ],
            "authors": [
                {
                    "name": "David Grudl",
                    "homepage": "https://davidgrudl.com"
                },
                {
                    "name": "Nette Community",
                    "homepage": "https://nette.org/contributors"
                }
            ],
            "description": "💎 Nette Dependency Injection Container: Flexible, compiled and full-featured DIC with perfectly usable autowiring and support for all new PHP 7.1 features.",
            "homepage": "https://nette.org",
            "keywords": [
                "compiled",
                "di",
                "dic",
                "factory",
                "ioc",
                "nette",
                "static"
            ],
            "time": "2017-08-31T22:42:00+00:00"
        },
        {
            "name": "nette/finder",
            "version": "v2.4.1",
            "source": {
                "type": "git",
                "url": "https://github.com/nette/finder.git",
                "reference": "4d43a66d072c57d585bf08a3ef68d3587f7e9547"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/nette/finder/zipball/4d43a66d072c57d585bf08a3ef68d3587f7e9547",
                "reference": "4d43a66d072c57d585bf08a3ef68d3587f7e9547",
                "shasum": ""
            },
            "require": {
                "nette/utils": "^2.4 || ~3.0.0",
                "php": ">=5.6.0"
            },
            "conflict": {
                "nette/nette": "<2.2"
            },
            "require-dev": {
                "nette/tester": "^2.0",
                "tracy/tracy": "^2.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.4-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause",
                "GPL-2.0",
                "GPL-3.0"
            ],
            "authors": [
                {
                    "name": "David Grudl",
                    "homepage": "https://davidgrudl.com"
                },
                {
                    "name": "Nette Community",
                    "homepage": "https://nette.org/contributors"
                }
            ],
            "description": "Nette Finder: Files Searching",
            "homepage": "https://nette.org",
            "time": "2017-07-10T23:47:08+00:00"
        },
        {
            "name": "nette/neon",
            "version": "v2.4.2",
            "source": {
                "type": "git",
                "url": "https://github.com/nette/neon.git",
                "reference": "9eacd50553b26b53a3977bfb2fea2166d4331622"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/nette/neon/zipball/9eacd50553b26b53a3977bfb2fea2166d4331622",
                "reference": "9eacd50553b26b53a3977bfb2fea2166d4331622",
                "shasum": ""
            },
            "require": {
                "ext-iconv": "*",
                "ext-json": "*",
                "php": ">=5.6.0"
            },
            "require-dev": {
                "nette/tester": "~2.0",
                "tracy/tracy": "^2.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.4-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause",
                "GPL-2.0",
                "GPL-3.0"
            ],
            "authors": [
                {
                    "name": "David Grudl",
                    "homepage": "https://davidgrudl.com"
                },
                {
                    "name": "Nette Community",
                    "homepage": "https://nette.org/contributors"
                }
            ],
            "description": "Nette NEON: parser & generator for Nette Object Notation",
            "homepage": "http://ne-on.org",
            "time": "2017-07-11T18:29:08+00:00"
        },
        {
            "name": "nette/php-generator",
            "version": "v3.0.1",
            "source": {
                "type": "git",
                "url": "https://github.com/nette/php-generator.git",
                "reference": "eb2dbc9c3409e9db40568109ca4994d51373b60c"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/nette/php-generator/zipball/eb2dbc9c3409e9db40568109ca4994d51373b60c",
                "reference": "eb2dbc9c3409e9db40568109ca4994d51373b60c",
                "shasum": ""
            },
            "require": {
                "nette/utils": "^2.4.2 || ~3.0.0",
                "php": ">=7.0"
            },
            "conflict": {
                "nette/nette": "<2.2"
            },
            "require-dev": {
                "nette/tester": "^2.0",
                "tracy/tracy": "^2.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause",
                "GPL-2.0",
                "GPL-3.0"
            ],
            "authors": [
                {
                    "name": "David Grudl",
                    "homepage": "https://davidgrudl.com"
                },
                {
                    "name": "Nette Community",
                    "homepage": "https://nette.org/contributors"
                }
            ],
            "description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 7.1 features.",
            "homepage": "https://nette.org",
            "keywords": [
                "code",
                "nette",
                "php",
                "scaffolding"
            ],
            "time": "2017-07-11T19:07:13+00:00"
        },
        {
            "name": "nette/robot-loader",
            "version": "v3.0.2",
            "source": {
                "type": "git",
                "url": "https://github.com/nette/robot-loader.git",
                "reference": "b703b4f5955831b0bcaacbd2f6af76021b056826"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/nette/robot-loader/zipball/b703b4f5955831b0bcaacbd2f6af76021b056826",
                "reference": "b703b4f5955831b0bcaacbd2f6af76021b056826",
                "shasum": ""
            },
            "require": {
                "ext-tokenizer": "*",
                "nette/finder": "^2.3 || ^3.0",
                "nette/utils": "^2.4 || ^3.0",
                "php": ">=5.6.0"
            },
            "conflict": {
                "nette/nette": "<2.2"
            },
            "require-dev": {
                "nette/tester": "^2.0",
                "tracy/tracy": "^2.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.0-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause",
                "GPL-2.0",
                "GPL-3.0"
            ],
            "authors": [
                {
                    "name": "David Grudl",
                    "homepage": "https://davidgrudl.com"
                },
                {
                    "name": "Nette Community",
                    "homepage": "https://nette.org/contributors"
                }
            ],
            "description": "🍀 Nette RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.",
            "homepage": "https://nette.org",
            "keywords": [
                "autoload",
                "class",
                "interface",
                "nette",
                "trait"
            ],
            "time": "2017-07-18T00:09:56+00:00"
        },
        {
            "name": "nette/utils",
            "version": "v2.4.8",
            "source": {
                "type": "git",
                "url": "https://github.com/nette/utils.git",
                "reference": "f1584033b5af945b470533b466b81a789d532034"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/nette/utils/zipball/f1584033b5af945b470533b466b81a789d532034",
                "reference": "f1584033b5af945b470533b466b81a789d532034",
                "shasum": ""
            },
            "require": {
                "php": ">=5.6.0"
            },
            "conflict": {
                "nette/nette": "<2.2"
            },
            "require-dev": {
                "nette/tester": "~2.0",
                "tracy/tracy": "^2.3"
            },
            "suggest": {
                "ext-gd": "to use Image",
                "ext-iconv": "to use Strings::webalize() and toAscii()",
                "ext-intl": "for script transliteration in Strings::webalize() and toAscii()",
                "ext-json": "to use Nette\\Utils\\Json",
                "ext-mbstring": "to use Strings::lower() etc...",
                "ext-xml": "to use Strings::length() etc. when mbstring is not available"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.4-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "src/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause",
                "GPL-2.0",
                "GPL-3.0"
            ],
            "authors": [
                {
                    "name": "David Grudl",
                    "homepage": "https://davidgrudl.com"
                },
                {
                    "name": "Nette Community",
                    "homepage": "https://nette.org/contributors"
                }
            ],
            "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.",
            "homepage": "https://nette.org",
            "keywords": [
                "array",
                "core",
                "datetime",
                "images",
                "json",
                "nette",
                "paginator",
                "password",
                "slugify",
                "string",
                "unicode",
                "utf-8",
                "utility",
                "validation"
            ],
            "time": "2017-08-20T17:32:29+00:00"
        },
        {
            "name": "nikic/php-parser",
            "version": "v3.1.4",
            "source": {
                "type": "git",
                "url": "https://github.com/nikic/PHP-Parser.git",
                "reference": "e57b3a09784f846411aa7ed664eedb73e3399078"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/e57b3a09784f846411aa7ed664eedb73e3399078",
                "reference": "e57b3a09784f846411aa7ed664eedb73e3399078",
                "shasum": ""
            },
            "require": {
                "ext-tokenizer": "*",
                "php": ">=5.5"
            },
            "require-dev": {
                "phpunit/phpunit": "~4.0|~5.0"
            },
            "bin": [
                "bin/php-parse"
            ],
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.0-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "PhpParser\\": "lib/PhpParser"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Nikita Popov"
                }
            ],
            "description": "A PHP parser written in PHP",
            "keywords": [
                "parser",
                "php"
            ],
            "time": "2018-01-25T21:31:33+00:00"
        },
        {
            "name": "ocramius/package-versions",
            "version": "1.2.0",
            "source": {
                "type": "git",
                "url": "https://github.com/Ocramius/PackageVersions.git",
                "reference": "ad8a245decad4897cc6b432743913dad0d69753c"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/ad8a245decad4897cc6b432743913dad0d69753c",
                "reference": "ad8a245decad4897cc6b432743913dad0d69753c",
                "shasum": ""
            },
            "require": {
                "composer-plugin-api": "^1.0",
                "php": "~7.0"
            },
            "require-dev": {
                "composer/composer": "^1.3",
                "ext-zip": "*",
                "humbug/humbug": "dev-master",
                "phpunit/phpunit": "^6.4"
            },
            "type": "composer-plugin",
            "extra": {
                "class": "PackageVersions\\Installer",
                "branch-alias": {
                    "dev-master": "2.0.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "PackageVersions\\": "src/PackageVersions"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Marco Pivetta",
                    "email": "ocramius@gmail.com"
                }
            ],
            "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)",
            "time": "2017-11-24T11:07:03+00:00"
        },
        {
            "name": "phpstan/package-patches",
            "version": "1.0.0",
            "require": {
                "netresearch/composer-patches-plugin": "~1.0"
            },
            "type": "metapackage",
            "extra": {
                "patches": {
                    "nette/di": [
                        {
                            "title": "Fixed including of paths with scheme in config loader",
                            "url": "/Users/ondrej/Development/phpstan-compiler/src/Compiler/../../patches/nette/di/include-scheme.patch"
                        }
                    ]
                }
            }
        },
        {
            "name": "phpstan/phpdoc-parser",
            "version": "0.2",
            "source": {
                "type": "git",
                "url": "https://github.com/phpstan/phpdoc-parser.git",
                "reference": "02f909f134fe06f0cd4790d8627ee24efbe84d6a"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/02f909f134fe06f0cd4790d8627ee24efbe84d6a",
                "reference": "02f909f134fe06f0cd4790d8627ee24efbe84d6a",
                "shasum": ""
            },
            "require": {
                "php": "~7.0"
            },
            "require-dev": {
                "consistence/coding-standard": "^2.0.0",
                "jakub-onderka/php-parallel-lint": "^0.9.2",
                "phing/phing": "^2.16.0",
                "phpstan/phpstan": "^0.9",
                "phpunit/phpunit": "^6.3",
                "slevomat/coding-standard": "^3.3.0"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "0.1-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "PHPStan\\PhpDocParser\\": [
                        "src/"
                    ]
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "PHPDoc parser with support for nullable, intersection and generic types",
            "time": "2018-01-13T18:19:41+00:00"
        },
        {
            "name": "psr/log",
            "version": "1.0.2",
            "source": {
                "type": "git",
                "url": "https://github.com/php-fig/log.git",
                "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
                "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.0"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.0.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Psr\\Log\\": "Psr/Log/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "PHP-FIG",
                    "homepage": "http://www.php-fig.org/"
                }
            ],
            "description": "Common interface for logging libraries",
            "homepage": "https://github.com/php-fig/log",
            "keywords": [
                "log",
                "psr",
                "psr-3"
            ],
            "time": "2016-10-10T12:19:37+00:00"
        },
        {
            "name": "symfony/console",
            "version": "v3.4.3",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/console.git",
                "reference": "8394c8ef121949e8f858f13bc1e34f05169e4e7d"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/console/zipball/8394c8ef121949e8f858f13bc1e34f05169e4e7d",
                "reference": "8394c8ef121949e8f858f13bc1e34f05169e4e7d",
                "shasum": ""
            },
            "require": {
                "php": "^5.5.9|>=7.0.8",
                "symfony/debug": "~2.8|~3.0|~4.0",
                "symfony/polyfill-mbstring": "~1.0"
            },
            "conflict": {
                "symfony/dependency-injection": "<3.4",
                "symfony/process": "<3.3"
            },
            "require-dev": {
                "psr/log": "~1.0",
                "symfony/config": "~3.3|~4.0",
                "symfony/dependency-injection": "~3.4|~4.0",
                "symfony/event-dispatcher": "~2.8|~3.0|~4.0",
                "symfony/lock": "~3.4|~4.0",
                "symfony/process": "~3.3|~4.0"
            },
            "suggest": {
                "psr/log": "For using the console logger",
                "symfony/event-dispatcher": "",
                "symfony/lock": "",
                "symfony/process": ""
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.4-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Symfony\\Component\\Console\\": ""
                },
                "exclude-from-classmap": [
                    "/Tests/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony Console Component",
            "homepage": "https://symfony.com",
            "time": "2018-01-03T07:37:34+00:00"
        },
        {
            "name": "symfony/debug",
            "version": "v4.0.3",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/debug.git",
                "reference": "9ae4223a661b56a9abdce144de4886cca37f198f"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/debug/zipball/9ae4223a661b56a9abdce144de4886cca37f198f",
                "reference": "9ae4223a661b56a9abdce144de4886cca37f198f",
                "shasum": ""
            },
            "require": {
                "php": "^7.1.3",
                "psr/log": "~1.0"
            },
            "conflict": {
                "symfony/http-kernel": "<3.4"
            },
            "require-dev": {
                "symfony/http-kernel": "~3.4|~4.0"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "4.0-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Symfony\\Component\\Debug\\": ""
                },
                "exclude-from-classmap": [
                    "/Tests/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony Debug Component",
            "homepage": "https://symfony.com",
            "time": "2018-01-03T17:15:19+00:00"
        },
        {
            "name": "symfony/finder",
            "version": "v3.4.3",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/finder.git",
                "reference": "613e26310776f49a1773b6737c6bd554b8bc8c6f"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/finder/zipball/613e26310776f49a1773b6737c6bd554b8bc8c6f",
                "reference": "613e26310776f49a1773b6737c6bd554b8bc8c6f",
                "shasum": ""
            },
            "require": {
                "php": "^5.5.9|>=7.0.8"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.4-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Symfony\\Component\\Finder\\": ""
                },
                "exclude-from-classmap": [
                    "/Tests/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony Finder Component",
            "homepage": "https://symfony.com",
            "time": "2018-01-03T07:37:34+00:00"
        },
        {
            "name": "symfony/polyfill-mbstring",
            "version": "v1.6.0",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/polyfill-mbstring.git",
                "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296",
                "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "suggest": {
                "ext-mbstring": "For best performance"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.6-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Symfony\\Polyfill\\Mbstring\\": ""
                },
                "files": [
                    "bootstrap.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony polyfill for the Mbstring extension",
            "homepage": "https://symfony.com",
            "keywords": [
                "compatibility",
                "mbstring",
                "polyfill",
                "portable",
                "shim"
            ],
            "time": "2017-10-11T12:05:26+00:00"
        }
    ],
    "packages-dev": [],
    "aliases": [],
    "minimum-stability": "stable",
    "stability-flags": [],
    "prefer-stable": false,
    "prefer-lowest": false,
    "platform": {
        "php": "~7.0"
    },
    "platform-dev": []
}
parameters:
	customRulesetUsed: false

services:
	-
		class: PHPStan\Rules\Arrays\DuplicateKeysInLiteralArraysRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Classes\ClassConstantRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Classes\ExistingClassInInstanceOfRule
		tags:
			- phpstan.rules.rule

		arguments:
			checkClassCaseSensitivity: %checkClassCaseSensitivity%

	-
		class: PHPStan\Rules\Classes\ExistingClassesInClassImplementsRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Classes\ExistingClassesInInterfaceExtendsRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Classes\ExistingClassInClassExtendsRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Classes\ExistingClassInTraitUseRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Classes\InstantiationRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Classes\RequireParentConstructCallRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Classes\UnusedConstructorParametersRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Exceptions\CaughtExceptionExistenceRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Functions\CallToFunctionParametersRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Functions\CallToNonExistentFunctionRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Functions\ExistingClassesInClosureTypehintsRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Functions\ExistingClassesInTypehintsRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Functions\InnerFunctionRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Functions\NonExistentDefinedFunctionRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Functions\PrintfParametersRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Functions\UnusedClosureUsesRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Methods\CallMethodsRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Methods\CallStaticMethodsRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Methods\ExistingClassesInTypehintsRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Namespaces\ExistingNamesInGroupUseRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Namespaces\ExistingNamesInUseRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Properties\AccessPropertiesRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Properties\AccessStaticPropertiesRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Properties\ExistingClassesInPropertiesRule
		tags:
			- phpstan.rules.rule

		arguments:
			checkClassCaseSensitivity: %checkClassCaseSensitivity%

	-
		class: PHPStan\Rules\Properties\WritingToReadOnlyPropertiesRule
		arguments:
			checkThisOnly: %checkThisOnly%

		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Properties\ReadingWriteOnlyPropertiesRule
		arguments:
			checkThisOnly: %checkThisOnly%

		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Variables\DefinedVariableRule
		arguments:
			cliArgumentsVariablesRegistered: %cliArgumentsVariablesRegistered%
			checkMaybeUndefinedVariables: %checkMaybeUndefinedVariables%

		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Variables\DefinedVariableInAnonymousFunctionUseRule
		arguments:
			checkMaybeUndefinedVariables: %checkMaybeUndefinedVariables%

		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Variables\ThisVariableRule
		tags:
			- phpstan.rules.rule

includes:
	- config.level0.neon

parameters:
	checkMaybeUndefinedVariables: true

services:
	-
		class: PHPStan\Rules\Constants\ConstantRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Variables\VariableCertaintyInIssetRule
		tags:
			- phpstan.rules.rule

includes:
	- config.level1.neon

parameters:
	checkClassCaseSensitivity: true
	checkThisOnly: false

services:
	-
		class: PHPStan\Rules\PhpDoc\InvalidPhpDocTagValueRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\PhpDoc\IncompatiblePhpDocTypeRule
		tags:
			- phpstan.rules.rule

includes:
	- config.level2.neon

services:
	-
		class: PHPStan\Rules\Arrays\AppendedArrayItemTypeRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Arrays\InvalidKeyInArrayDimFetchRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Arrays\InvalidKeyInArrayItemRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Arrays\IterableInForeachRule
		arguments:
			checkUnionTypes: %checkUnionTypes%

		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Functions\ClosureReturnTypeRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Functions\ReturnTypeRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Methods\ReturnTypeRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Properties\DefaultValueTypesAssignedToPropertiesRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Properties\TypesAssignedToPropertiesRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Variables\VariableCloningRule
		arguments:
			checkNullables: %checkNullables%

		tags:
			- phpstan.rules.rule

includes:
	- config.level3.neon

services:
	-
		class: PHPStan\Rules\Cast\UselessCastRule
		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Classes\ImpossibleInstanceOfRule
		arguments:
			checkAlwaysTrueInstanceof: %checkAlwaysTrueInstanceof%

		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Comparison\ImpossibleCheckTypeFunctionCallRule
		arguments:
			checkAlwaysTrueCheckTypeFunctionCall: %checkAlwaysTrueCheckTypeFunctionCall%

		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Comparison\StrictComparisonOfDifferentTypesRule
		tags:
			- phpstan.rules.rule

includes:
	- config.level4.neon

parameters:
	checkFunctionArgumentTypes: true
	checkArgumentsPassedByReference: true

services:
	-
		class: PHPStan\Rules\Functions\CallToCountOnlyWithArrayOrCountableRule
		tags:
			- phpstan.rules.rule

includes:
	- config.level5.neon

parameters:
	checkUnionTypes: true

includes:
	- config.level6.neon

parameters:
	checkNullables: true

services:
	-
		class: PHPStan\Rules\Properties\AccessPropertiesOnPossiblyNullRule
		arguments:
			checkThisOnly: %checkThisOnly%

		tags:
			- phpstan.rules.rule

	-
		class: PHPStan\Rules\Methods\CallMethodsOnPossiblyNullRule
		arguments:
			checkThisOnly: %checkThisOnly%

		tags:
			- phpstan.rules.rule

includes:
	- config.level7.neon

parameters:
	bootstrap: null
	excludes_analyse: []
	autoload_directories: []
	autoload_files: []
	fileExtensions:
		- php

	checkAlwaysTrueCheckTypeFunctionCall: false
	checkAlwaysTrueInstanceof: false
	checkClassCaseSensitivity: false
	checkFunctionArgumentTypes: false
	checkArgumentsPassedByReference: false
	checkMaybeUndefinedVariables: false
	checkNullables: false
	checkThisOnly: true
	checkUnionTypes: false
	polluteScopeWithLoopInitialAssignments: true
	polluteCatchScopeWithTryAssignments: false
	ignoreErrors: []
	internalErrorsCountLimit: 50
	reportUnmatchedIgnoredErrors: true
	universalObjectCratesClasses:
		- stdClass
		- SimpleXMLElement

	earlyTerminatingMethodCalls: []
	memoryLimitFile: %tmpDir%/.memory_limit

services:
	0:
		class: PhpParser\BuilderFactory

	1:
		class: PhpParser\Lexer

	2:
		class: PhpParser\NodeTraverser
		setup:
			- addVisitor(@PhpParser\NodeVisitor\NameResolver)

	3:
		class: PhpParser\NodeVisitor\NameResolver

	4:
		class: PhpParser\Parser\Php7

	5:
		class: PhpParser\PrettyPrinter\Standard

	6:
		class: PHPStan\PhpDocParser\Lexer\Lexer

	7:
		class: PHPStan\PhpDocParser\Parser\TypeParser

	8:
		class: PHPStan\PhpDocParser\Parser\ConstExprParser

	9:
		class: PHPStan\PhpDocParser\Parser\PhpDocParser

	10:
		class: PHPStan\PhpDoc\PhpDocNodeResolver

	11:
		class: PHPStan\PhpDoc\PhpDocStringResolver

	12:
		class: PHPStan\PhpDoc\TypeNodeResolver

	13:
		class: PHPStan\PhpDoc\TypeStringResolver

	14:
		class: PHPStan\Analyser\Analyser
		arguments:
			ignoreErrors: %ignoreErrors%
			reportUnmatchedIgnoredErrors: %reportUnmatchedIgnoredErrors%
			bootstrapFile: %bootstrap%
			internalErrorsCountLimit: %internalErrorsCountLimit%

	15:
		class: PHPStan\Analyser\NodeScopeResolver
		arguments:
			polluteScopeWithLoopInitialAssignments: %polluteScopeWithLoopInitialAssignments%
			polluteCatchScopeWithTryAssignments: %polluteCatchScopeWithTryAssignments%
			earlyTerminatingMethodCalls: %earlyTerminatingMethodCalls%

	16:
		class: PHPStan\Analyser\TypeSpecifier

	17:
		class: PHPStan\Cache\Cache
		arguments:
			storage: @cacheStorage

	18:
		class: PHPStan\Command\AnalyseApplication
		arguments:
			memoryLimitFile: %memoryLimitFile%
			fileExtensions: %fileExtensions%

	19:
		class: PHPStan\File\FileHelper
		arguments:
			workingDirectory: %currentWorkingDirectory%

	20:
		class: PHPStan\File\FileExcluder
		arguments:
			analyseExcludes: %excludes_analyse%

	21:
		class: PHPStan\Parser\CachedParser
		arguments:
			originalParser: @directParser

	22:
		class: PHPStan\Parser\FunctionCallStatementFinder

	23:
		implement: PHPStan\Reflection\FunctionReflectionFactory

	24:
		class: PHPStan\Reflection\Annotations\AnnotationsMethodsClassReflectionExtension

	25:
		class: PHPStan\Reflection\Annotations\AnnotationsPropertiesClassReflectionExtension

	26:
		class: PHPStan\Reflection\Php\PhpClassReflectionExtension

	27:
		class: PHPStan\Reflection\PhpDefect\PhpDefectClassReflectionExtension

	28:
		implement: PHPStan\Reflection\Php\PhpMethodReflectionFactory

	29:
		class: PHPStan\Reflection\Php\UniversalObjectCratesClassReflectionExtension
		tags:
			- phpstan.broker.propertiesClassReflectionExtension

		arguments:
			classes: %universalObjectCratesClasses%

	30:
		class: PHPStan\Rules\ClassCaseSensitivityCheck

	31:
		class: PHPStan\Rules\FunctionCallParametersCheck
		arguments:
			checkArgumentTypes: %checkFunctionArgumentTypes%
			checkArgumentsPassedByReference: %checkArgumentsPassedByReference%

	32:
		class: PHPStan\Rules\FunctionDefinitionCheck
		arguments:
			checkClassCaseSensitivity: %checkClassCaseSensitivity%
			checkThisOnly: %checkThisOnly%

	33:
		class: PHPStan\Rules\FunctionReturnTypeCheck

	34:
		class: PHPStan\Rules\Properties\PropertyDescriptor

	35:
		class: PHPStan\Rules\Properties\PropertyReflectionFinder

	36:
		class: PHPStan\Rules\RegistryFactory

	37:
		class: PHPStan\Rules\RuleLevelHelper
		arguments:
			checkNullables: %checkNullables%
			checkThisOnly: %checkThisOnly%
			checkUnionTypes: %checkUnionTypes%

	38:
		class: PHPStan\Rules\UnusedFunctionParametersCheck

	39:
		class: PHPStan\Type\FileTypeMapper

	40:
		class: PHPStan\Type\Php\AllArgumentBasedFunctionReturnTypeExtension
		tags:
			- phpstan.broker.dynamicFunctionReturnTypeExtension

	41:
		class: PHPStan\Type\Php\ArgumentBasedArrayFunctionReturnTypeExtension
		tags:
			- phpstan.broker.dynamicFunctionReturnTypeExtension

	42:
		class: PHPStan\Type\Php\ArgumentBasedFunctionReturnTypeExtension
		tags:
			- phpstan.broker.dynamicFunctionReturnTypeExtension

	43:
		class: PHPStan\Type\Php\ArrayFilterFunctionReturnTypeReturnTypeExtension
		tags:
			- phpstan.broker.dynamicFunctionReturnTypeExtension

	44:
		class: PHPStan\Type\Php\CallbackBasedArrayFunctionReturnTypeExtension
		tags:
			- phpstan.broker.dynamicFunctionReturnTypeExtension

	45:
		class: PHPStan\Type\Php\CallbackBasedFunctionReturnTypeExtension
		tags:
			- phpstan.broker.dynamicFunctionReturnTypeExtension

	broker:
		class: PHPStan\Broker\Broker
		factory: @brokerFactory::create

	brokerFactory:
		class: PHPStan\Broker\BrokerFactory

	cacheStorage:
		class: PHPStan\Cache\FileCacheStorage
		arguments:
			directory: %tmpDir%/cache/PHPStan

		autowired: false

	directParser:
		class: PHPStan\Parser\DirectParser
		autowired: false

	registry:
		class: PHPStan\Rules\Registry
		factory: @PHPStan\Rules\RegistryFactory::create

	errorFormatter.raw:
		class: PHPStan\Command\ErrorFormatter\RawErrorFormatter

	errorFormatter.table:
		class: PHPStan\Command\ErrorFormatter\TableErrorFormatter

	errorFormatter.checkstyle:
		class: PHPStan\Command\ErrorFormatter\CheckstyleErrorFormatter

<?xml version="1.0"?>
<ruleset name="PHPStan">
	<rule ref="vendor/consistence/coding-standard/Consistence/ruleset.xml">
		<exclude name="Squiz.Functions.GlobalFunction.Found"/>
		<exclude name="Consistence.Exceptions.ExceptionDeclaration"/>
	</rule>
	<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/ruleset.xml">
		<exclude name="SlevomatCodingStandard.Classes.ClassConstantVisibility.MissingConstantVisibility"/>
		<exclude name="SlevomatCodingStandard.Files.TypeNameMatchesFileName"/>
		<exclude name="SlevomatCodingStandard.Namespaces.FullyQualifiedClassNameAfterKeyword"/>
		<exclude name="SlevomatCodingStandard.Namespaces.UseOnlyWhitelistedNamespaces"/>
		<exclude name="SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly"/>
		<exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingTraversableParameterTypeHintSpecification"/>
		<exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingTraversableReturnTypeHintSpecification"/>
		<exclude name="SlevomatCodingStandard.Namespaces.FullyQualifiedClassNameInAnnotation.NonFullyQualifiedClassName"/>
		<exclude name="SlevomatCodingStandard.Namespaces.FullyQualifiedGlobalConstants"/>
		<exclude name="SlevomatCodingStandard.Namespaces.FullyQualifiedGlobalFunctions"/>
		<exclude name="SlevomatCodingStandard.TypeHints.NullableTypeForNullDefaultValue"/>
		<exclude name="SlevomatCodingStandard.ControlStructures.RequireYodaComparison.RequiredYodaComparison"/>
	</rule>
	<rule ref="Squiz.PHP.InnerFunctions.NotAllowed">
		<exclude-pattern>tests/TestCase.php</exclude-pattern>
		<exclude-pattern>tests/PHPStan/Analyser/NodeScopeResolverTest.php</exclude-pattern>
	</rule>
	<rule ref="Squiz.Operators.ValidLogicalOperators.NotAllowed">
		<exclude-pattern>tests/PHPStan/Analyser/NodeScopeResolverTest.php</exclude-pattern>
	</rule>
	<rule ref="SlevomatCodingStandard.Namespaces.AlphabeticallySortedUses">
		<properties>
			<property name="caseSensitive" value="false"/>
		</properties>
	</rule>
	<rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes">
		<properties>
			<property name="newlinesCountBetweenOpenTagAndDeclare" value="0"/>
		</properties>
	</rule>
	<rule ref="SlevomatCodingStandard.TypeHints.TypeHintDeclaration">
		<properties>
			<property name="usefulAnnotations" type="array" value="
				@dataProvider,
				@requires
			"/>
			<property name="enableNullableTypeHints" type="false" />
			<property name="enableVoidTypeHint" type="false" />
		</properties>
	</rule>
	<rule ref="Generic.Strings.UnnecessaryStringConcat.Found">
		<exclude-pattern>tests/PHPStan/Analyser/NodeScopeResolverTest.php</exclude-pattern>
	</rule>
</ruleset>
<?php declare(strict_types = 1);

namespace PHPStan;

abstract class AnalysedCodeException extends \Exception
{

}
<?php declare(strict_types = 1);

namespace PHPStan\Analyser;

use PHPStan\Broker\Broker;
use PHPStan\File\FileHelper;
use PHPStan\Parser\Parser;
use PHPStan\Rules\Registry;

class Analyser
{

	/**
	 * @var \PHPStan\Parser\Parser
	 */
	private $parser;

	/**
	 * @var \PHPStan\Rules\Registry
	 */
	private $registry;

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	/**
	 * @var \PHPStan\Analyser\NodeScopeResolver
	 */
	private $nodeScopeResolver;

	/**
	 * @var \PhpParser\PrettyPrinter\Standard
	 */
	private $printer;

	/**
	 * @var \PHPStan\Analyser\TypeSpecifier
	 */
	private $typeSpecifier;

	/**
	 * @var string[]
	 */
	private $ignoreErrors;

	/**
	 * @var string|null
	 */
	private $bootstrapFile;

	/**
	 * @var bool
	 */
	private $reportUnmatchedIgnoredErrors;

	/**
	 * @var int
	 */
	private $internalErrorsCountLimit;

	/**
	 * @param \PHPStan\Broker\Broker $broker
	 * @param \PHPStan\Parser\Parser $parser
	 * @param \PHPStan\Rules\Registry $registry
	 * @param \PHPStan\Analyser\NodeScopeResolver $nodeScopeResolver
	 * @param \PhpParser\PrettyPrinter\Standard $printer
	 * @param \PHPStan\Analyser\TypeSpecifier $typeSpecifier
	 * @param \PHPStan\File\FileHelper $fileHelper
	 * @param string[] $ignoreErrors
	 * @param string|null $bootstrapFile
	 * @param bool $reportUnmatchedIgnoredErrors
	 * @param int $internalErrorsCountLimit
	 */
	public function __construct(
		\PHPStan\Broker\Broker $broker,
		\PHPStan\Parser\Parser $parser,
		\PHPStan\Rules\Registry $registry,
		\PHPStan\Analyser\NodeScopeResolver $nodeScopeResolver,
		\PhpParser\PrettyPrinter\Standard $printer,
		\PHPStan\Analyser\TypeSpecifier $typeSpecifier,
		\PHPStan\File\FileHelper $fileHelper,
		array $ignoreErrors,
		string $bootstrapFile = null,
		bool $reportUnmatchedIgnoredErrors,
		int $internalErrorsCountLimit
	)
	{
		$this->broker = $broker;
		$this->parser = $parser;
		$this->registry = $registry;
		$this->nodeScopeResolver = $nodeScopeResolver;
		$this->printer = $printer;
		$this->typeSpecifier = $typeSpecifier;
		$this->ignoreErrors = $ignoreErrors;
		$this->bootstrapFile = $bootstrapFile !== null ? $fileHelper->normalizePath($bootstrapFile) : null;
		$this->reportUnmatchedIgnoredErrors = $reportUnmatchedIgnoredErrors;
		$this->internalErrorsCountLimit = $internalErrorsCountLimit;
	}

	/**
	 * @param string[] $files
	 * @param bool $onlyFiles
	 * @param \Closure|null $preFileCallback
	 * @param \Closure|null $postFileCallback
	 * @param bool $debug
	 * @return string[]|\PHPStan\Analyser\Error[] errors
	 */
	public function analyse(
		array $files,
		bool $onlyFiles,
		\Closure $preFileCallback = null,
		\Closure $postFileCallback = null,
		bool $debug = false
	): array
	{
		$errors = [];

		if ($this->bootstrapFile !== null) {
			if (!is_file($this->bootstrapFile)) {
				return [
					sprintf('Bootstrap file %s does not exist.', $this->bootstrapFile),
				];
			}
			try {
				require_once $this->bootstrapFile;
			} catch (\Throwable $e) {
				return [$e->getMessage()];
			}
		}

		foreach ($this->ignoreErrors as $ignoreError) {
			try {
				\PHPStanVendor\Nette\Utils\Strings::match('', $ignoreError);
			} catch (\PHPStanVendor\Nette\Utils\RegexpException $e) {
				$errors[] = $e->getMessage();
			}
		}

		if (count($errors) > 0) {
			return $errors;
		}

		$this->nodeScopeResolver->setAnalysedFiles($files);
		$internalErrorsCount = 0;
		$reachedInternalErrorsCountLimit = false;
		foreach ($files as $file) {
			try {
				$fileErrors = [];
				if ($preFileCallback !== null) {
					$preFileCallback($file);
				}
				$this->nodeScopeResolver->processNodes(
					$this->parser->parseFile($file),
					new \PHPStan\Analyser\Scope($this->broker, $this->printer, $this->typeSpecifier, $file),
					function (\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope) use (&$fileErrors) {
						foreach ($this->registry->getRules(get_class($node)) as $rule) {
							$ruleErrors = $this->createErrors(
								$node,
								$scope->getAnalysedContextFile(),
								$rule->processNode($node, $scope)
							);
							$fileErrors = array_merge($fileErrors, $ruleErrors);
						}
					}
				);
				if ($postFileCallback !== null) {
					$postFileCallback($file);
				}

				$errors = array_merge($errors, $fileErrors);
			} catch (\PhpParser\Error $e) {
				$errors[] = new \PHPStan\Analyser\Error($e->getMessage(), $file, $e->getStartLine() !== -1 ? $e->getStartLine() : null, false);
			} catch (\PHPStan\AnalysedCodeException $e) {
				$errors[] = new \PHPStan\Analyser\Error($e->getMessage(), $file, null, false);
			} catch (\Throwable $t) {
				if ($debug) {
					throw $t;
				}
				$internalErrorsCount++;
				$internalErrorMessage = sprintf('Internal error: %s', $t->getMessage());
				$internalErrorMessage .= sprintf(
					'%sRun PHPStan with --debug option and post the stack trace to:%s%s',
					"\n",
					"\n",
					'https://github.com/phpstan/phpstan/issues/new'
				);
				$errors[] = new \PHPStan\Analyser\Error($internalErrorMessage, $file);
				if ($internalErrorsCount >= $this->internalErrorsCountLimit) {
					$reachedInternalErrorsCountLimit = true;
					break;
				}
			}
		}

		$unmatchedIgnoredErrors = $this->ignoreErrors;
		$addErrors = [];
		$errors = array_values(array_filter($errors, function (\PHPStan\Analyser\Error $error) use (&$unmatchedIgnoredErrors, &$addErrors): bool {
			foreach ($this->ignoreErrors as $i => $ignore) {
				if (\PHPStanVendor\Nette\Utils\Strings::match($error->getMessage(), $ignore) !== null) {
					unset($unmatchedIgnoredErrors[$i]);
					if (!$error->canBeIgnored()) {
						$addErrors[] = sprintf(
							'Error message "%s" cannot be ignored, use excludes_analyse instead.',
							$error->getMessage()
						);
						return true;
					}
					return false;
				}
			}

			return true;
		}));

		$errors = array_merge($errors, $addErrors);

		if (!$onlyFiles && $this->reportUnmatchedIgnoredErrors && !$reachedInternalErrorsCountLimit) {
			foreach ($unmatchedIgnoredErrors as $unmatchedIgnoredError) {
				$errors[] = sprintf(
					'Ignored error pattern %s was not matched in reported errors.',
					$unmatchedIgnoredError
				);
			}
		}

		if ($reachedInternalErrorsCountLimit) {
			$errors[] = sprintf('Reached internal errors count limit of %d, exiting...', $this->internalErrorsCountLimit);
		}

		return $errors;
	}

	/**
	 * @param \PhpParser\Node $node
	 * @param string $file
	 * @param string[] $messages
	 * @return \PHPStan\Analyser\Error[]
	 */
	private function createErrors(\PhpParser\Node $node, string $file, array $messages): array
	{
		$errors = [];
		foreach ($messages as $message) {
			$errors[] = new \PHPStan\Analyser\Error($message, $file, $node->getLine());
		}

		return $errors;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Analyser;

class Error
{

	/**
	 * @var string
	 */
	private $message;

	/**
	 * @var string
	 */
	private $file;

	/**
	 * @var int|NULL
	 */
	private $line;

	/**
	 * @var bool
	 */
	private $canBeIgnored;

	public function __construct(string $message, string $file, int $line = null, bool $canBeIgnored = true)
	{
		$this->message = $message;
		$this->file = $file;
		$this->line = $line;
		$this->canBeIgnored = $canBeIgnored;
	}

	public function getMessage(): string
	{
		return $this->message;
	}

	public function getFile(): string
	{
		return $this->file;
	}

	/**
	 * @return int|NULL
	 */
	public function getLine()
	{
		return $this->line;
	}

	public function canBeIgnored(): bool
	{
		return $this->canBeIgnored;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Analyser;

class LookForAssignsSettings
{

	const EARLY_TERMINATION_CONTINUE = 1;
	const EARLY_TERMINATION_BREAK = 2;
	const EARLY_TERMINATION_STOP = 4;
	const EARLY_TERMINATION_ALL = self::EARLY_TERMINATION_CONTINUE
		+ self::EARLY_TERMINATION_BREAK
		+ self::EARLY_TERMINATION_STOP;

	/**
	 * @var int
	 */
	private $respectEarlyTermination;

	private function __construct(
		int $respectEarlyTermination
	)
	{
		$this->respectEarlyTermination = $respectEarlyTermination;
	}

	public static function default(): self
	{
		return new self(
			self::EARLY_TERMINATION_ALL
		);
	}

	public static function insideLoop(): self
	{
		return new self(
			self::EARLY_TERMINATION_STOP + self::EARLY_TERMINATION_BREAK
		);
	}

	public static function afterLoop(): self
	{
		return new self(
			self::EARLY_TERMINATION_STOP
		);
	}

	public static function insideFinally(): self
	{
		return new self(
			0
		);
	}

	public function shouldSkipBranch(\PhpParser\Node $earlyTerminationStatement): bool
	{
		return $this->isRespected($earlyTerminationStatement);
	}

	private function isRespected(\PhpParser\Node $earlyTerminationStatement): bool
	{
		if (
			$earlyTerminationStatement instanceof \PhpParser\Node\Stmt\Break_
		) {
			return ($this->respectEarlyTermination & self::EARLY_TERMINATION_BREAK) === self::EARLY_TERMINATION_BREAK;
		}

		if (
			$earlyTerminationStatement instanceof \PhpParser\Node\Stmt\Continue_
		) {
			return ($this->respectEarlyTermination & self::EARLY_TERMINATION_CONTINUE) === self::EARLY_TERMINATION_CONTINUE;
		}

		return ($this->respectEarlyTermination & self::EARLY_TERMINATION_STOP) === self::EARLY_TERMINATION_STOP;
	}

	public function shouldIntersectVariables(\PhpParser\Node $earlyTerminationStatement = null): bool
	{
		if ($earlyTerminationStatement === null) {
			return true;
		}

		if ($this->shouldSkipBranch($earlyTerminationStatement)) {
			throw new \PHPStan\ShouldNotHappenException();
		}

		return $earlyTerminationStatement instanceof \PhpParser\Node\Stmt\Break_
			|| $earlyTerminationStatement instanceof \PhpParser\Node\Stmt\Continue_
			|| ($this->respectEarlyTermination & self::EARLY_TERMINATION_STOP) === 0;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Analyser;

class NameScope
{

	/**
	 * @var string|null
	 */
	private $namespace;

	/**
	 * @var string[] alias(string) => fullName(string)
	 */
	private $uses;

	/**
	 * @var string|null
	 */
	private $className;

	public function __construct(string $namespace = null, array $uses = [], string $className = null)
	{
		$this->namespace = $namespace;
		$this->uses = $uses;
		$this->className = $className;
	}

	/**
	 * @return string|null
	 */
	public function getClassName()
	{
		return $this->className;
	}

	public function resolveStringName(string $name): string
	{
		if (strpos($name, '\\') === 0) {
			return ltrim($name, '\\');
		}

		$nameParts = explode('\\', $name);
		$firstNamePart = $nameParts[0];
		if (isset($this->uses[$firstNamePart])) {
			if (count($nameParts) === 1) {
				return $this->uses[$firstNamePart];
			}
			array_shift($nameParts);
			return sprintf('%s\\%s', $this->uses[$firstNamePart], implode('\\', $nameParts));
		}

		if ($this->namespace !== null) {
			return sprintf('%s\\%s', $this->namespace, $name);
		}

		return $name;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Analyser;
use PHPStan\Broker\Broker;
use PHPStan\File\FileHelper;
use PHPStan\Parser\Parser;
use PHPStan\PhpDoc\PhpDocBlock;
use PHPStan\PhpDoc\Tag\ParamTag;
use PHPStan\TrinaryLogic;
use PHPStan\Type\ArrayType;
use PHPStan\Type\CommentHelper;
use PHPStan\Type\FileTypeMapper;
use PHPStan\Type\IntegerType;
use PHPStan\Type\MixedType;
use PHPStan\Type\NestedArrayItemType;
use PHPStan\Type\NullType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;

class NodeScopeResolver
{

	/** @var \PHPStan\Broker\Broker */
	private $broker;

	/** @var \PHPStan\Parser\Parser */
	private $parser;

	/** @var \PhpParser\PrettyPrinter\Standard */
	private $printer;

	/** @var \PHPStan\Type\FileTypeMapper */
	private $fileTypeMapper;

	/** @var \PHPStan\File\FileHelper */
	private $fileHelper;

	/** @var bool */
	private $polluteScopeWithLoopInitialAssignments;

	/** @var bool */
	private $polluteCatchScopeWithTryAssignments;

	/** @var string[][] className(string) => methods(string[]) */
	private $earlyTerminatingMethodCalls;

	/** @var \PHPStan\Reflection\ClassReflection|null */
	private $anonymousClassReflection;

	/** @var bool[] filePath(string) => bool(true) */
	private $analysedFiles;

	public function __construct(
		\PHPStan\Broker\Broker $broker,
		\PHPStan\Parser\Parser $parser,
		\PhpParser\PrettyPrinter\Standard $printer,
		\PHPStan\Type\FileTypeMapper $fileTypeMapper,
		\PHPStan\File\FileHelper $fileHelper,
		bool $polluteScopeWithLoopInitialAssignments,
		bool $polluteCatchScopeWithTryAssignments,
		array $earlyTerminatingMethodCalls
	)
	{
		$this->broker = $broker;
		$this->parser = $parser;
		$this->printer = $printer;
		$this->fileTypeMapper = $fileTypeMapper;
		$this->fileHelper = $fileHelper;
		$this->polluteScopeWithLoopInitialAssignments = $polluteScopeWithLoopInitialAssignments;
		$this->polluteCatchScopeWithTryAssignments = $polluteCatchScopeWithTryAssignments;
		$this->earlyTerminatingMethodCalls = $earlyTerminatingMethodCalls;
	}

	/**
	 * @param string[] $files
	 */
	public function setAnalysedFiles(array $files)
	{
		$this->analysedFiles = array_fill_keys($files, true);
	}

	/**
	 * @param \PhpParser\Node[] $nodes
	 * @param \PHPStan\Analyser\Scope $scope
	 * @param \Closure $nodeCallback
	 * @param \PHPStan\Analyser\Scope $closureBindScope
	 */
	public function processNodes(
		array $nodes,
		\PHPStan\Analyser\Scope $scope,
		\Closure $nodeCallback,
		\PHPStan\Analyser\Scope $closureBindScope = null
	)
	{
		/** @var \PhpParser\Node|string $node */
		foreach ($nodes as $i => $node) {
			if (!($node instanceof \PhpParser\Node)) {
				continue;
			}

			if ($scope->getInFunctionCall() !== null && $node instanceof \PhpParser\Node\Arg) {
				$functionCall = $scope->getInFunctionCall();
				$value = $node->value;

				$parametersAcceptor = $this->findParametersAcceptorInFunctionCall($functionCall, $scope);

				if ($parametersAcceptor !== null) {
					$parameters = $parametersAcceptor->getParameters();
					$assignByReference = false;
					if (isset($parameters[$i])) {
						$assignByReference = $parameters[$i]->isPassedByReference();
					} elseif (count($parameters) > 0 && $parametersAcceptor->isVariadic()) {
						$lastParameter = $parameters[count($parameters) - 1];
						$assignByReference = $lastParameter->isPassedByReference();
					}
					if ($assignByReference && $value instanceof \PhpParser\Node\Expr\Variable && is_string($value->name)) {
						$scope = $scope->assignVariable($value->name, new \PHPStan\Type\MixedType(), \PHPStan\TrinaryLogic::createYes());
					}
				}
			}

			$nodeScope = $scope;
			if ($i === 0 && $closureBindScope !== null) {
				$nodeScope = $closureBindScope;
			}

			$this->processNode($node, $nodeScope, $nodeCallback);
			$scope = $this->lookForAssigns($scope, $node, \PHPStan\TrinaryLogic::createYes());

			if ($node instanceof \PhpParser\Node\Stmt\If_) {
				if ($this->findEarlyTermination($node->stmts, $scope) !== null) {
					$scope = $scope->filterByFalseyValue($node->cond);
					$this->processNode($node->cond, $scope, function (\PhpParser\Node $node, \PHPStan\Analyser\Scope $inScope) use (&$scope) {
						$this->specifyFetchedPropertyForInnerScope($node, $inScope, true, $scope);
					});
				}
			} elseif ($node instanceof \PhpParser\Node\Stmt\Declare_) {
				foreach ($node->declares as $declare) {
					if (
						$declare->key === 'strict_types'
						&& $declare->value instanceof \PhpParser\Node\Scalar\LNumber
						&& $declare->value->value === 1
					) {
						$scope = $scope->enterDeclareStrictTypes();
						break;
					}
				}
			} elseif (
				$node instanceof \PhpParser\Node\Expr\FuncCall
				&& $node->name instanceof \PhpParser\Node\Name
				&& (string) $node->name === 'assert'
				&& isset($node->args[0])
			) {
				$scope = $scope->filterByTruthyValue($node->args[0]->value);
			}
		}
	}

	private function specifyProperty(\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Expr $expr): \PHPStan\Analyser\Scope
	{
		if ($expr instanceof \PhpParser\Node\Expr\PropertyFetch) {
			return $scope->specifyFetchedPropertyFromIsset($expr);
		} elseif (
			$expr instanceof \PhpParser\Node\Expr\StaticPropertyFetch
			&& $expr->class instanceof \PhpParser\Node\Name
			&& (string) $expr->class === 'static'
		) {
			return $scope->specifyFetchedStaticPropertyFromIsset($expr);
		}

		return $scope;
	}

	private function specifyFetchedPropertyForInnerScope(\PhpParser\Node $node, \PHPStan\Analyser\Scope $inScope, bool $inEarlyTermination, Scope &$scope)
	{
		if ($inEarlyTermination === $inScope->isNegated()) {
			if ($node instanceof \PhpParser\Node\Expr\Isset_) {
				foreach ($node->vars as $var) {
					$scope = $this->specifyProperty($scope, $var);
				}
			} elseif (
				$node instanceof \PhpParser\Node\Expr\FuncCall
				&& $node->name instanceof \PhpParser\Node\Name
				&& $this->broker->resolveFunctionName($node->name, $scope) === 'property_exists'
				&& count($node->args) === 2
				&& $node->args[1]->value instanceof  \PhpParser\Node\Scalar\String_
			) {
				$scope = $scope->specifyFetchedPropertyFromIsset(
					new \PhpParser\Node\Expr\PropertyFetch($node->args[0]->value, $node->args[1]->value->value)
				);
			}
		} else {
			if ($node instanceof \PhpParser\Node\Expr\Empty_) {
				$scope = $this->specifyProperty($scope, $node->expr);
				$scope = $this->assignVariable($scope, $node->expr, \PHPStan\TrinaryLogic::createYes());
			}
		}
	}

	private function lookForArrayDestructuringArray(\PHPStan\Analyser\Scope $scope, \PhpParser\Node $node): \PHPStan\Analyser\Scope
	{
		if ($node instanceof \PhpParser\Node\Expr\Array_) {
			foreach ($node->items as $item) {
				if ($item === null) {
					continue;
				}
				$scope = $this->lookForArrayDestructuringArray($scope, $item->value);
			}
		} elseif ($node instanceof \PhpParser\Node\Expr\Variable && is_string($node->name)) {
			$scope = $scope->assignVariable($node->name, new \PHPStan\Type\MixedType(), \PHPStan\TrinaryLogic::createYes());
		} elseif ($node instanceof \PhpParser\Node\Expr\ArrayDimFetch && $node->var instanceof \PhpParser\Node\Expr\Variable && is_string($node->var->name)) {
			$scope = $scope->assignVariable(
				$node->var->name,
				new \PHPStan\Type\MixedType(),
				\PHPStan\TrinaryLogic::createYes()
			);
		} elseif ($node instanceof \PhpParser\Node\Expr\List_) {
			foreach ($node->items as $item) {
				/** @var \PhpParser\Node\Expr\ArrayItem|null $itemValue */
				$itemValue = $item;
				if ($itemValue === null) {
					continue;
				}
				$itemValue = $itemValue->value;
				if ($itemValue instanceof \PhpParser\Node\Expr\Variable && is_string($itemValue->name)) {
					$scope = $scope->assignVariable($itemValue->name, new \PHPStan\Type\MixedType(), \PHPStan\TrinaryLogic::createYes());
				} else {
					$scope = $this->lookForArrayDestructuringArray($scope, $itemValue);
				}
			}
		}

		return $scope;
	}

	private function enterForeach(\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Stmt\Foreach_ $node): \PHPStan\Analyser\Scope
	{
		if ($node->keyVar !== null && $node->keyVar instanceof \PhpParser\Node\Expr\Variable && is_string($node->keyVar->name)) {
			$scope = $scope->assignVariable($node->keyVar->name, new \PHPStan\Type\MixedType(), \PHPStan\TrinaryLogic::createYes());
		}

		if ($node->valueVar instanceof \PhpParser\Node\Expr\Variable && is_string($node->valueVar->name)) {
			$scope = $scope->enterForeach(
				$node->expr,
				$node->valueVar->name,
				$node->keyVar !== null
				&& $node->keyVar instanceof \PhpParser\Node\Expr\Variable
				&& is_string($node->keyVar->name)
					? $node->keyVar->name
					: null
			);
			$comment = \PHPStan\Type\CommentHelper::getDocComment($node);
			if ($comment !== null) {
				$scope = $this->processVarAnnotation($scope, $node->valueVar->name, $comment, true);
			}
		}

		if ($node->valueVar instanceof \PhpParser\Node\Expr\List_ || $node->valueVar instanceof \PhpParser\Node\Expr\Array_) {
			$scope = $this->lookForArrayDestructuringArray($scope, $node->valueVar);
		}

		return $this->lookForAssigns($scope, $node->valueVar, \PHPStan\TrinaryLogic::createYes());
	}

	private function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope, \Closure $nodeCallback, bool $stopImmediately = false)
	{
		$nodeCallback($node, $scope);
		if ($stopImmediately) {
			return;
		}

		if (
			$node instanceof \PhpParser\Node\Stmt\ClassLike
		) {
			if ($node instanceof \PhpParser\Node\Stmt\Trait_) {
				return;
			}
			if (isset($node->namespacedName)) {
				$scope = $scope->enterClass($this->broker->getClass((string) $node->namespacedName));
			} elseif ($this->anonymousClassReflection !== null) {
				$scope = $scope->enterAnonymousClass($this->anonymousClassReflection);
			} else {
				throw new \PHPStan\ShouldNotHappenException();
			}
		} elseif ($node instanceof \PhpParser\Node\Stmt\TraitUse) {
			$this->processTraitUse($node, $scope, $nodeCallback);
		} elseif ($node instanceof \PhpParser\Node\Stmt\Function_) {
			$scope = $this->enterFunction($scope, $node);
		} elseif ($node instanceof \PhpParser\Node\Stmt\ClassMethod) {
			$scope = $this->enterClassMethod($scope, $node);
		} elseif ($node instanceof \PhpParser\Node\Stmt\Namespace_) {
			$scope = $scope->enterNamespace((string) $node->name);
		} elseif (
			$node instanceof \PhpParser\Node\Expr\StaticCall
			&& $node->class instanceof \PhpParser\Node\Name
			&& is_string($node->name)
			&& (string) $node->class === 'Closure'
			&& $node->name === 'bind'
		) {
			$thisType = null;
			if (isset($node->args[1])) {
				$argValue = $node->args[1]->value;
				if ($argValue instanceof \PhpParser\Node\Expr\ConstFetch && ((string) $argValue->name === 'null')) {
					$thisType = null;
				} else {
					$thisType = $scope->getType($argValue);
				}
			}
			$scopeClass = 'static';
			if (isset($node->args[2])) {
				$argValue = $node->args[2]->value;
				$argValueType = $scope->getType($argValue);
				if (count($argValueType->getReferencedClasses()) === 1) {
					$scopeClass = $argValueType->getReferencedClasses()[0];
				} elseif (
					$argValue instanceof \PhpParser\Node\Expr\ClassConstFetch
					&& strtolower($argValue->name) === 'class'
					&& $argValue->class instanceof \PhpParser\Node\Name
				) {
					$scopeClass = $scope->resolveName($argValue->class);
				} elseif ($argValue instanceof \PhpParser\Node\Scalar\String_) {
					$scopeClass = $argValue->value;
				}
			}
			$closureBindScope = $scope->enterClosureBind($thisType, $scopeClass);
		} elseif ($node instanceof \PhpParser\Node\Stmt\Foreach_) {
			$scope = $scope->exitFirstLevelStatements();
			$this->processNode($node->expr, $scope, $nodeCallback);
			$scope = $this->lookForAssigns($scope, $node->expr, \PHPStan\TrinaryLogic::createYes());
			$scope = $this->enterForeach($scope, $node);
			if ($node->keyVar !== null) {
				$this->processNode($node->keyVar, $scope, $nodeCallback);
			}

			$this->processNode($node->valueVar, $scope, $nodeCallback);

			$scope = $this->lookForAssignsInBranches($scope, [
				new \PHPStan\Analyser\StatementList($scope, $node->stmts),
				new \PHPStan\Analyser\StatementList($scope, []),
			], \PHPStan\Analyser\LookForAssignsSettings::insideLoop());
			$scope = $this->enterForeach($scope, $node);

			$this->processNodes($node->stmts, $scope->enterFirstLevelStatements(), $nodeCallback);

			return;
		} elseif ($node instanceof \PhpParser\Node\Stmt\For_) {
			$this->processNodes($node->init, $scope, $nodeCallback);

			foreach ($node->init as $initExpr) {
				$scope = $this->lookForAssigns($scope, $initExpr, \PHPStan\TrinaryLogic::createYes());
			}
			$scopeLoopMightHaveRun = $this->lookForAssignsInBranches($scope, [
				new \PHPStan\Analyser\StatementList($scope, $node->cond),
				new \PHPStan\Analyser\StatementList($scope, $node->stmts),
				new \PHPStan\Analyser\StatementList($scope, $node->loop),
				new \PHPStan\Analyser\StatementList($scope, []),
			], \PHPStan\Analyser\LookForAssignsSettings::insideLoop());

			$this->processNodes($node->cond, $scopeLoopMightHaveRun, $nodeCallback);

			foreach ($node->cond as $condExpr) {
				$scope = $scope->filterByTruthyValue($condExpr);
			}

			$scopeLoopDefinitelyRan = $this->lookForAssignsInBranches($scope, [
				new \PHPStan\Analyser\StatementList($scope, $node->stmts),
			], \PHPStan\Analyser\LookForAssignsSettings::insideLoop());

			$this->processNodes($node->loop, $scopeLoopDefinitelyRan, $nodeCallback);

			foreach ($node->cond as $condExpr) {
				$scopeLoopMightHaveRun = $scopeLoopMightHaveRun->filterByTruthyValue($condExpr);
			}
			$this->processNodes($node->stmts, $scopeLoopMightHaveRun, $nodeCallback);

			return;
		} elseif ($node instanceof \PhpParser\Node\Stmt\While_) {
			$bodyScope = $scope->filterByTruthyValue($node->cond);
			$condScope = $this->lookForAssignsInBranches($scope, [
				new \PHPStan\Analyser\StatementList($bodyScope, $node->stmts),
				new \PHPStan\Analyser\StatementList($scope, []),
			], \PHPStan\Analyser\LookForAssignsSettings::insideLoop());
			$this->processNode($node->cond, $condScope, $nodeCallback);

			$bodyScope = $this->lookForAssignsInBranches($bodyScope, [
				new \PHPStan\Analyser\StatementList($bodyScope, $node->stmts),
				new \PHPStan\Analyser\StatementList($bodyScope, []),
			], \PHPStan\Analyser\LookForAssignsSettings::insideLoop());
			$bodyScope = $this->lookForAssigns($bodyScope, $node->cond, \PHPStan\TrinaryLogic::createYes());
			$bodyScope = $bodyScope->filterByTruthyValue($node->cond);
			$this->processNodes($node->stmts, $bodyScope, $nodeCallback);
			return;
		} elseif ($node instanceof \PhpParser\Node\Stmt\Catch_) {
			$scope = $scope->enterCatch(
				$node->types,
				$node->var
			);
		} elseif ($node instanceof \PhpParser\Node\Expr\Array_) {
			$scope = $scope->exitFirstLevelStatements();
			foreach ($node->items as $item) {
				if ($item === null) {
					continue;
				}
				$this->processNode($item, $scope, $nodeCallback);
				if ($item->key !== null) {
					$scope = $this->lookForAssigns($scope, $item->key, \PHPStan\TrinaryLogic::createYes());
				}
				$scope = $this->lookForAssigns($scope, $item->value, \PHPStan\TrinaryLogic::createYes());
			}

			return;
		} elseif ($node instanceof \PhpParser\Node\Stmt\If_) {
			$this->processNode($node->cond, $scope->exitFirstLevelStatements(), $nodeCallback);
			$scope = $this->lookForAssigns(
				$scope,
				$node->cond,
				\PHPStan\TrinaryLogic::createYes()
			);
			$ifScope = $scope;
			$scope = $scope->filterByTruthyValue($node->cond);

			$specifyFetchedProperty = function (\PhpParser\Node $node, \PHPStan\Analyser\Scope $inScope) use (&$scope) {
				$this->specifyFetchedPropertyForInnerScope($node, $inScope, false, $scope);
			};
			$this->processNode($node->cond, $scope, $specifyFetchedProperty);
			$this->processNodes($node->stmts, $scope->enterFirstLevelStatements(), $nodeCallback);

			$elseifScope = $ifScope->filterByFalseyValue($node->cond);
			foreach ($node->elseifs as $elseif) {
				$this->processNode($elseif, $scope, $nodeCallback, true);
				$scope = $elseifScope;
				$this->processNode($elseif->cond, $scope->exitFirstLevelStatements(), $nodeCallback);
				$scope = $this->lookForAssigns(
					$scope,
					$elseif->cond,
					\PHPStan\TrinaryLogic::createYes()
				);
				$scope = $scope->filterByTruthyValue($elseif->cond);
				$this->processNode($elseif->cond, $scope, $specifyFetchedProperty);
				$this->processNodes($elseif->stmts, $scope->enterFirstLevelStatements(), $nodeCallback);
				$elseifScope = $this->lookForAssigns(
					$elseifScope,
					$elseif->cond,
					\PHPStan\TrinaryLogic::createYes()
				)->filterByFalseyValue($elseif->cond);
			}
			if ($node->else !== null) {
				$this->processNode($node->else, $elseifScope, $nodeCallback);
			}

			return;
		} elseif ($node instanceof \PhpParser\Node\Stmt\Switch_) {
			$scope = $scope->exitFirstLevelStatements();
			$this->processNode($node->cond, $scope, $nodeCallback);
			$scope = $this->lookForAssigns(
				$scope,
				$node->cond,
				\PHPStan\TrinaryLogic::createYes()
			);
			$switchScope = $scope;
			$switchConditionIsTrue = $node->cond instanceof \PhpParser\Node\Expr\ConstFetch && strtolower((string) $node->cond->name) === 'true';
			$switchConditionGetClassExpression = null;
			if (
				$node->cond instanceof \PhpParser\Node\Expr\FuncCall
				&& $node->cond->name instanceof \PhpParser\Node\Name
				&& strtolower((string) $node->cond->name) === 'get_class'
				&& isset($node->cond->args[0])
			) {
				$switchConditionGetClassExpression = $node->cond->args[0]->value;
			}
			foreach ($node->cases as $caseNode) {
				$this->processNode($caseNode, $scope, $nodeCallback, true);
				if ($caseNode->cond !== null) {
					$this->processNode($caseNode->cond, $switchScope, $nodeCallback);
					$switchScope = $this->lookForAssigns(
						$switchScope,
						$caseNode->cond,
						\PHPStan\TrinaryLogic::createYes()
					);
					$scope = $this->lookForAssigns(
						$scope,
						$caseNode->cond,
						\PHPStan\TrinaryLogic::createYes()
					);

					$caseScope = $switchScope;
					if ($switchConditionIsTrue) {
						$caseScope = $caseScope->filterByTruthyValue($caseNode->cond);
					} elseif (
						$switchConditionGetClassExpression !== null
						&& $caseNode->cond instanceof \PhpParser\Node\Expr\ClassConstFetch
						&& $caseNode->cond->class instanceof \PhpParser\Node\Name
						&& strtolower($caseNode->cond->name) === 'class'
					) {
						$caseScope = $caseScope->specifyExpressionType(
							$switchConditionGetClassExpression,
							new \PHPStan\Type\ObjectType($scope->resolveName($caseNode->cond->class))
						);
					}
				} else {
					$caseScope = $switchScope;
				}
				$this->processNodes(
					$caseNode->stmts,
					$caseScope->enterFirstLevelStatements(),
					$nodeCallback
				);
				if ($this->findEarlyTermination($caseNode->stmts, $switchScope) === null) {
					foreach ($caseNode->stmts as $statement) {
						$switchScope = $this->lookForAssigns($switchScope, $statement, \PHPStan\TrinaryLogic::createMaybe());
					}
				} else {
					$switchScope = $scope;
				}
			}
			return;
		} elseif ($node instanceof \PhpParser\Node\Stmt\TryCatch) {
			$statements = [];
			$this->processNodes($node->stmts, $scope->enterFirstLevelStatements(), $nodeCallback);

			$scopeForLookForAssignsInBranches = $scope;
			$tryAssignmentsCertainty = $this->polluteCatchScopeWithTryAssignments ? \PHPStan\TrinaryLogic::createYes() : \PHPStan\TrinaryLogic::createMaybe();
			foreach ($node->stmts as $statement) {
				$scope = $this->lookForAssigns($scope, $statement, $tryAssignmentsCertainty);
			}

			if ($node->finally !== null) {
				$statements[] = new \PHPStan\Analyser\StatementList($scopeForLookForAssignsInBranches, $node->stmts);
				$statements[] = new \PHPStan\Analyser\StatementList($scopeForLookForAssignsInBranches, []);
			}

			foreach ($node->catches as $catch) {
				$this->processNode($catch, $scope, $nodeCallback);
				if ($node->finally !== null) {
					$statements[] = new \PHPStan\Analyser\StatementList($scope->enterCatch(
						$catch->types,
						$catch->var
					), $catch->stmts);
				}
			}

			if ($node->finally !== null) {
				$finallyScope = $this->lookForAssignsInBranches($scopeForLookForAssignsInBranches, $statements, \PHPStan\Analyser\LookForAssignsSettings::insideFinally());

				$this->processNode($node->finally, $finallyScope, $nodeCallback);
			}

			return;
		} elseif ($node instanceof \PhpParser\Node\Expr\FuncCall) {
			$scope = $scope->enterFunctionCall($node);
		} elseif ($node instanceof \PhpParser\Node\Expr\StaticCall) {
			$scope = $scope->enterFunctionCall($node);
		} elseif ($node instanceof \PhpParser\Node\Expr\MethodCall) {
			if (
				$scope->getType($node->var)->describe() === \Closure::class
				&& $node->name === 'call'
				&& isset($node->args[0])
			) {
				$closureCallScope = $scope->enterClosureBind($scope->getType($node->args[0]->value), 'static');
			}
			$scope = $scope->enterFunctionCall($node);
		} elseif ($node instanceof \PhpParser\Node\Expr\New_ && $node->class instanceof \PhpParser\Node\Stmt\Class_) {
			do {
				$uniqidClass = 'AnonymousClass' . uniqid();
			} while (class_exists('\\' . $uniqidClass));

			$classNode = $node->class;
			$classNode->name = $uniqidClass;
			eval($this->printer->prettyPrint([$classNode]));
			unset($classNode);

			$classReflection = new \ReflectionClass('\\' . $uniqidClass);
			$this->anonymousClassReflection = $this->broker->getClassFromReflection(
				$classReflection,
				sprintf('class@anonymous%s:%s', $scope->getFile(), $node->getLine()),
				true
			);
		} elseif ($node instanceof \PhpParser\Node\Expr\BooleanNot) {
			$scope = $scope->enterNegation();
		} elseif ($node instanceof \PhpParser\Node\Stmt\Unset_ || $node instanceof \PhpParser\Node\Expr\Isset_) {
			foreach ($node->vars as $unsetVar) {
				while (
					$unsetVar instanceof \PhpParser\Node\Expr\ArrayDimFetch
					|| $unsetVar instanceof \PhpParser\Node\Expr\PropertyFetch
				) {
					$unsetVar = $unsetVar->var;
				}

				while (
					$unsetVar instanceof \PhpParser\Node\Expr\StaticPropertyFetch
					&& $unsetVar->class instanceof \PhpParser\Node\Expr
				) {
					$unsetVar = $unsetVar->class;
				}
				$scope = $scope->enterExpressionAssign($unsetVar);
			}
		} elseif ($node instanceof \PhpParser\Node\Stmt\Global_) {
			foreach ($node->vars as $var) {
				$scope = $scope->enterExpressionAssign($var);
			}
		}

		$originalScope = $scope;
		foreach ($node->getSubNodeNames() as $subNodeName) {
			$scope = $originalScope;
			$subNode = $node->{$subNodeName};

			if (is_array($subNode)) {
				$argClosureBindScope = null;
				if (isset($closureBindScope) && $subNodeName === 'args') {
					$argClosureBindScope = $closureBindScope;
				}
				if ($subNodeName === 'stmts') {
					$scope = $scope->enterFirstLevelStatements();
				} else {
					$scope = $scope->exitFirstLevelStatements();
				}

				if ($node instanceof \PhpParser\Node\Expr\Isset_ && $subNodeName === 'vars') {
					foreach ($node->vars as $issetVar) {
						$scope = $this->specifyProperty($scope, $issetVar);
					}
				}

				if ($node instanceof \PhpParser\Node\Expr\MethodCall && $subNodeName === 'args') {
					$scope = $this->lookForAssigns($scope, $node->var, \PHPStan\TrinaryLogic::createYes());
				}

				if (
					$node instanceof \PhpParser\Node\Expr\Closure
					&& $subNodeName === 'stmts'
				) {
					$scope = $scope->enterAnonymousFunction($node->params, $node->uses, $node->returnType);
				}

				if ($node instanceof \PhpParser\Node\Stmt\Do_ && $subNodeName === 'stmts') {
					$scope = $this->lookForAssignsInBranches($scope, [
						new \PHPStan\Analyser\StatementList($scope, $node->stmts),
						new \PHPStan\Analyser\StatementList($scope, [$node->cond], true),
						new \PHPStan\Analyser\StatementList($scope, []),
					], \PHPStan\Analyser\LookForAssignsSettings::insideLoop());
				}

				if ($node instanceof \PhpParser\Node\Expr\Isset_ && $subNodeName === 'vars') {
					foreach ($subNode as $issetVar) {
						$scope = $this->ensureNonNullability($scope, $issetVar);
					}
				}

				$this->processNodes($subNode, $scope, $nodeCallback, $argClosureBindScope);
			} elseif ($subNode instanceof \PhpParser\Node) {
				if ($node instanceof \PhpParser\Node\Expr\BinaryOp\Coalesce && $subNodeName === 'left') {
					$scope = $this->ensureNonNullability($scope, $subNode);
				}

				if (
					($node instanceof \PhpParser\Node\Expr\BinaryOp\BooleanAnd || $node instanceof \PhpParser\Node\Expr\BinaryOp\LogicalAnd)
					&& $subNodeName === 'right') {
					$scope = $scope->filterByTruthyValue($node->left);
				}
				if (
					($node instanceof \PhpParser\Node\Expr\BinaryOp\BooleanOr || $node instanceof \PhpParser\Node\Expr\BinaryOp\LogicalOr)
					&& $subNodeName === 'right') {
					$scope = $scope->filterByFalseyValue($node->left);
				}

				if (($node instanceof \PhpParser\Node\Expr\Assign || $node instanceof \PhpParser\Node\Expr\AssignRef) && $subNodeName === 'var') {
					$scope = $this->lookForEnterVariableAssign($scope, $node->var);
				}

				if ($node instanceof \PhpParser\Node\Expr\BinaryOp && $subNodeName === 'right') {
					$scope = $this->lookForAssigns($scope, $node->left, \PHPStan\TrinaryLogic::createYes());
				}

				if ($node instanceof \PhpParser\Node\Expr\Empty_ && $subNodeName === 'expr') {
					$scope = $this->specifyProperty($scope, $node->expr);
					$scope = $this->lookForEnterVariableAssign($scope, $node->expr);
				}

				if (
					$node instanceof \PhpParser\Node\Expr\ArrayItem
					&& $subNodeName === 'value'
					&& $node->key !== null
				) {
					$scope = $this->lookForAssigns($scope, $node->key, \PHPStan\TrinaryLogic::createYes());
				}

				if (
					$node instanceof \PhpParser\Node\Expr\Ternary
					&& $subNodeName !== 'cond'
				) {
					$scope = $this->lookForAssigns($scope, $node->cond, \PHPStan\TrinaryLogic::createYes());
					if ($subNodeName === 'if') {
						$scope = $scope->filterByTruthyValue($node->cond);
						$this->processNode($node->cond, $scope, function (\PhpParser\Node $node, \PHPStan\Analyser\Scope $inScope) use (&$scope) {
							$this->specifyFetchedPropertyForInnerScope($node, $inScope, false, $scope);
						});
					} elseif ($subNodeName === 'else') {
						$scope = $scope->filterByFalseyValue($node->cond);
						$this->processNode($node->cond, $scope, function (\PhpParser\Node $node, \PHPStan\Analyser\Scope $inScope) use (&$scope) {
							$this->specifyFetchedPropertyForInnerScope($node, $inScope, true, $scope);
						});
					}
				}

				if ($node instanceof \PhpParser\Node\Stmt\Do_ && $subNodeName === 'cond') {
					foreach ($node->stmts as $statement) {
						$scope = $this->lookForAssigns($scope, $statement, \PHPStan\TrinaryLogic::createYes());
					}
				}

				$nodeScope = $scope->exitFirstLevelStatements();
				if ($scope->isInFirstLevelStatement()) {
					if ($node instanceof \PhpParser\Node\Expr\Ternary && $subNodeName !== 'cond') {
						$nodeScope = $scope->enterFirstLevelStatements();
					} elseif (
						($node instanceof \PhpParser\Node\Expr\BinaryOp\BooleanAnd || $node instanceof \PhpParser\Node\Expr\BinaryOp\BooleanOr)
						&& $subNodeName === 'right'
					) {
						$nodeScope = $scope->enterFirstLevelStatements();
					}
				}

				if ($node instanceof \PhpParser\Node\Expr\MethodCall && $subNodeName === 'var' && isset($closureCallScope)) {
					$nodeScope = $closureCallScope->exitFirstLevelStatements();
				}

				$this->processNode($subNode, $nodeScope, $nodeCallback);
			}
		}
	}

	private function ensureNonNullability(\PHPStan\Analyser\Scope $scope, \PhpParser\Node $node): \PHPStan\Analyser\Scope
	{
		$scope = $this->assignVariable($scope, $node, \PHPStan\TrinaryLogic::createYes());
		$nodeToSpecify = $node;
		while (
			$nodeToSpecify instanceof \PhpParser\Node\Expr\PropertyFetch
			|| $nodeToSpecify instanceof \PhpParser\Node\Expr\MethodCall
		) {
			$nodeToSpecify = $nodeToSpecify->var;
			$scope = $scope->specifyExpressionType(
				$nodeToSpecify,
				\PHPStan\Type\TypeCombinator::removeNull($scope->getType($nodeToSpecify))
			);
		}

		return $scope;
	}

	private function lookForEnterVariableAssign(\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Expr $node): \PHPStan\Analyser\Scope
	{
		if ($node instanceof \PhpParser\Node\Expr\Variable) {
			$scope = $scope->enterExpressionAssign($node);
		} elseif ($node instanceof \PhpParser\Node\Expr\ArrayDimFetch) {
			while ($node instanceof \PhpParser\Node\Expr\ArrayDimFetch) {
				$node = $node->var;
			}

			if ($node instanceof \PhpParser\Node\Expr\Variable) {
				$scope = $scope->enterExpressionAssign($node);
			}
		} elseif ($node instanceof \PhpParser\Node\Expr\List_ || $node instanceof \PhpParser\Node\Expr\Array_) {
			foreach ($node->items as $listItem) {
				if ($listItem === null) {
					continue;
				}
				$listItemValue = $listItem;
				if ($listItemValue instanceof \PhpParser\Node\Expr\ArrayItem) {
					$listItemValue = $listItemValue->value;
				}
				$scope = $this->lookForEnterVariableAssign($scope, $listItemValue);
			}
		} else {
			$scope = $scope->enterExpressionAssign($node);
		}

		return $scope;
	}

	private function lookForAssigns(
		\PHPStan\Analyser\Scope $scope,
		\PhpParser\Node $node,
		\PHPStan\TrinaryLogic $certainty,
		\PHPStan\Analyser\LookForAssignsSettings $lookForAssignsSettings = null
	): \PHPStan\Analyser\Scope
	{
		if ($lookForAssignsSettings === null) {
			$lookForAssignsSettings = \PHPStan\Analyser\LookForAssignsSettings::default();
		}
		if ($node instanceof \PhpParser\Node\Stmt\StaticVar) {
			$scope = $scope->assignVariable(
				$node->name,
				$node->default !== null ? $scope->getType($node->default) : new \PHPStan\Type\MixedType(),
				$certainty
			);
		} elseif ($node instanceof \PhpParser\Node\Stmt\Static_) {
			foreach ($node->vars as $var) {
				$scope = $this->lookForAssigns($scope, $var, $certainty);
			}
		} elseif ($node instanceof \PhpParser\Node\Stmt\If_) {
			$scope = $this->lookForAssigns($scope, $node->cond, $certainty);
			$ifStatement = new \PHPStan\Analyser\StatementList(
				$scope->filterByTruthyValue($node->cond),
				array_merge([$node->cond], $node->stmts)
			);

			$elseIfScope = $scope->filterByFalseyValue($node->cond);
			$elseIfStatements = [];
			foreach ($node->elseifs as $elseIf) {
				$elseIfStatements[] = new \PHPStan\Analyser\StatementList($elseIfScope, array_merge([$elseIf->cond], $elseIf->stmts));
				$elseIfScope = $elseIfScope->filterByFalseyValue($elseIf->cond);
			}

			$statements = [
				$ifStatement,
				new \PHPStan\Analyser\StatementList($elseIfScope, $node->else !== null ? $node->else->stmts : []),
			];
			$statements = array_merge($statements, $elseIfStatements);

			$scope = $this->lookForAssignsInBranches($scope, $statements, $lookForAssignsSettings);
		} elseif ($node instanceof \PhpParser\Node\Stmt\TryCatch) {
			$statements = [
				new \PHPStan\Analyser\StatementList($scope, $node->stmts),
			];
			foreach ($node->catches as $catch) {
				$statements[] = new \PHPStan\Analyser\StatementList($scope->enterCatch(
					$catch->types,
					$catch->var
				), array_merge([new \PhpParser\Node\Stmt\Nop()], $catch->stmts));
			}

			$scope = $this->lookForAssignsInBranches($scope, $statements, $lookForAssignsSettings);
			if ($node->finally !== null) {
				foreach ($node->finally->stmts as $statement) {
					$scope = $this->lookForAssigns($scope, $statement, $certainty, $lookForAssignsSettings);
				}
			}
		} elseif ($node instanceof \PhpParser\Node\Expr\MethodCall || $node instanceof \PhpParser\Node\Expr\FuncCall || $node instanceof \PhpParser\Node\Expr\StaticCall) {
			if ($node instanceof \PhpParser\Node\Expr\MethodCall) {
				$scope = $this->lookForAssigns($scope, $node->var, $certainty);
			}
			foreach ($node->args as $argument) {
				$scope = $this->lookForAssigns($scope, $argument, $certainty);
			}

			$parametersAcceptor = $this->findParametersAcceptorInFunctionCall($node, $scope);

			if ($parametersAcceptor !== null) {
				$parameters = $parametersAcceptor->getParameters();
				foreach ($node->args as $i => $arg) {
					$assignByReference = false;
					if (isset($parameters[$i])) {
						$assignByReference = $parameters[$i]->isPassedByReference();
					} elseif (count($parameters) > 0 && $parametersAcceptor->isVariadic()) {
						$lastParameter = $parameters[count($parameters) - 1];
						$assignByReference = $lastParameter->isPassedByReference();
					}

					if (!$assignByReference) {
						continue;
					}

					$arg = $node->args[$i]->value;
					if ($arg instanceof \PhpParser\Node\Expr\Variable && is_string($arg->name)) {
						$scope = $scope->assignVariable($arg->name, new \PHPStan\Type\MixedType(), $certainty);
					}
				}
			}
			if (
				$node instanceof \PhpParser\Node\Expr\FuncCall
				&& $node->name instanceof \PhpParser\Node\Name
				&& in_array((string) $node->name, [
					'fopen',
					'file_get_contents',
				], true)
			) {
				$scope = $scope->assignVariable('http_response_header', new \PHPStan\Type\ArrayType(new \PHPStan\Type\IntegerType(), new \PHPStan\Type\StringType(), false), $certainty);
			}
		} elseif ($node instanceof \PhpParser\Node\Expr\BinaryOp) {
			$scope = $this->lookForAssigns($scope, $node->left, $certainty);
			$scope = $this->lookForAssigns($scope, $node->right, $certainty);
		} elseif ($node instanceof \PhpParser\Node\Arg) {
			$scope = $this->lookForAssigns($scope, $node->value, $certainty);
		} elseif ($node instanceof \PhpParser\Node\Expr\BooleanNot) {
			$scope = $this->lookForAssigns($scope, $node->expr, $certainty);
		} elseif ($node instanceof \PhpParser\Node\Expr\Ternary) {
			$scope = $this->lookForAssigns($scope, $node->cond, $certainty);
			$statements = [];
			if ($node->if !== null) {
				$statements[] = new \PHPStan\Analyser\StatementList(
					$scope->filterByTruthyValue($node->cond),
					[$node->if]
				);
			} else {
				$statements[] = new \PHPStan\Analyser\StatementList(
					$scope->filterByTruthyValue($node->cond),
					[$node->cond]
				);
			}

			$statements[] = new \PHPStan\Analyser\StatementList(
				$scope->filterByFalseyValue($node->cond),
				[$node->else]
			);
			$scope = $this->lookForAssignsInBranches($scope, $statements, $lookForAssignsSettings);
		} elseif ($node instanceof \PhpParser\Node\Expr\Array_) {
			foreach ($node->items as $item) {
				if ($item === null) {
					continue;
				}
				if ($item->key !== null) {
					$scope = $this->lookForAssigns($scope, $item->key, $certainty);
				}
				$scope = $this->lookForAssigns($scope, $item->value, $certainty);
			}
		} elseif ($node instanceof \PhpParser\Node\Expr\New_) {
			foreach ($node->args as $arg) {
				$scope = $this->lookForAssigns($scope, $arg, $certainty);
			}
		} elseif ($node instanceof \PhpParser\Node\Stmt\Do_) {
			$scope = $this->lookForAssignsInBranches($scope, [
				new \PHPStan\Analyser\StatementList($scope, $node->stmts),
			], \PHPStan\Analyser\LookForAssignsSettings::afterLoop());
			$scope = $this->lookForAssigns($scope, $node->cond, \PHPStan\TrinaryLogic::createYes());
		} elseif ($node instanceof \PhpParser\Node\Stmt\Switch_) {
			$statementLists = [];
			$tmpStatements = [];
			$hasDefault = false;
			foreach ($node->cases as $case) {
				if ($case->cond === null) {
					$hasDefault = true;
				}

				foreach ($case->stmts as $statement) {
					$tmpStatements[] = $statement;
					if ($this->findStatementEarlyTermination($statement, $scope) !== null) {
						$statementLists[] = new \PHPStan\Analyser\StatementList($scope, $tmpStatements);
						$tmpStatements = [];
						break;
					}
				}
			}

			if (count($tmpStatements) > 0) {
				$statementLists[] = new \PHPStan\Analyser\StatementList($scope, $tmpStatements);
			}

			if (!$hasDefault) {
				$statementLists[] = new \PHPStan\Analyser\StatementList($scope, []);
			}

			$scope = $this->lookForAssignsInBranches($scope, $statementLists, \PHPStan\Analyser\LookForAssignsSettings::afterLoop());
		} elseif ($node instanceof \PhpParser\Node\Expr\Cast) {
			$scope = $this->lookForAssigns($scope, $node->expr, $certainty);
		} elseif ($node instanceof \PhpParser\Node\Stmt\For_) {
			$forAssignmentsCertainty = $this->polluteScopeWithLoopInitialAssignments ? \PHPStan\TrinaryLogic::createYes() : \PHPStan\TrinaryLogic::createMaybe();
			foreach ($node->init as $initExpr) {
				$scope = $this->lookForAssigns($scope, $initExpr, $forAssignmentsCertainty);
			}

			foreach ($node->cond as $condExpr) {
				$scope = $this->lookForAssigns($scope, $condExpr, $forAssignmentsCertainty);
			}

			$statements = [
				new \PHPStan\Analyser\StatementList($scope, $node->stmts),
				new \PHPStan\Analyser\StatementList($scope, []), // in order not to add variables existing only inside the for loop
			];
			$scope = $this->lookForAssignsInBranches($scope, $statements, \PHPStan\Analyser\LookForAssignsSettings::afterLoop());
			foreach ($node->loop as $loopExpr) {
				$scope = $this->lookForAssigns($scope, $loopExpr, \PHPStan\TrinaryLogic::createMaybe());
			}
		} elseif ($node instanceof \PhpParser\Node\Stmt\While_) {
			$whileAssignmentsCertainty = $this->polluteScopeWithLoopInitialAssignments ? \PHPStan\TrinaryLogic::createYes() : \PHPStan\TrinaryLogic::createMaybe();
			$scope = $this->lookForAssigns($scope, $node->cond, $whileAssignmentsCertainty);

			$statements = [
				new \PHPStan\Analyser\StatementList($scope, $node->stmts),
				new \PHPStan\Analyser\StatementList($scope, []), // in order not to add variables existing only inside the for loop
			];
			$scope = $this->lookForAssignsInBranches($scope, $statements, \PHPStan\Analyser\LookForAssignsSettings::afterLoop());
		} elseif ($node instanceof \PhpParser\Node\Expr\ErrorSuppress) {
			$scope = $this->lookForAssigns($scope, $node->expr, $certainty);
		} elseif ($node instanceof \PhpParser\Node\Stmt\Unset_) {
			foreach ($node->vars as $var) {
				if ($var instanceof \PhpParser\Node\Expr\Variable && is_string($var->name)) {
					$scope = $scope->unsetVariable($var->name);
				}
			}
		} elseif ($node instanceof \PhpParser\Node\Stmt\Echo_) {
			foreach ($node->exprs as $echoedExpr) {
				$scope = $this->lookForAssigns($scope, $echoedExpr, $certainty);
			}
		} elseif ($node instanceof \PhpParser\Node\Expr\Print_) {
			$scope = $this->lookForAssigns($scope, $node->expr, $certainty);
		} elseif ($node instanceof \PhpParser\Node\Stmt\Foreach_) {
			$scope = $this->lookForAssigns($scope, $node->expr, $certainty);
			$initialScope = $scope;
			$scope = $this->enterForeach($scope, $node);
			$statements = [
				new \PHPStan\Analyser\StatementList($scope, array_merge(
					[new \PhpParser\Node\Stmt\Nop],
					$node->stmts
				)),
				new \PHPStan\Analyser\StatementList($initialScope, []), // in order not to add variables existing only inside the for loop
			];
			$scope = $this->lookForAssignsInBranches($initialScope, $statements, \PHPStan\Analyser\LookForAssignsSettings::afterLoop());
		} elseif ($node instanceof \PhpParser\Node\Expr\Isset_) {
			foreach ($node->vars as $var) {
				$scope = $this->lookForAssigns($scope, $var, $certainty);
			}
		} elseif ($node instanceof \PhpParser\Node\Expr\Empty_) {
			$scope = $this->lookForAssigns($scope, $node->expr, $certainty);
		} elseif ($node instanceof \PhpParser\Node\Expr\ArrayDimFetch && $node->dim !== null) {
			$scope = $this->lookForAssigns($scope, $node->dim, $certainty);
		} elseif ($node instanceof \PhpParser\Node\Expr\Closure) {
			foreach ($node->uses as $closureUse) {
				if (!$closureUse->byRef || $scope->hasVariableType($closureUse->var)->yes()) {
					continue;
				}

				$scope = $scope->assignVariable($closureUse->var, new \PHPStan\Type\MixedType(), $certainty);
			}
		} elseif ($node instanceof \PhpParser\Node\Expr\Instanceof_) {
			$scope = $this->lookForAssigns($scope, $node->expr, $certainty);
		} elseif ($node instanceof \PhpParser\Node\Expr\Include_) {
			$scope = $this->lookForAssigns($scope, $node->expr, $certainty);
		}

		$scope = $this->updateScopeForVariableAssign($scope, $node, $certainty);

		return $scope;
	}

	private function updateScopeForVariableAssign(\PHPStan\Analyser\Scope $scope, \PhpParser\Node $node, \PHPStan\TrinaryLogic $certainty): \PHPStan\Analyser\Scope
	{
		if ($node instanceof \PhpParser\Node\Expr\Assign || $node instanceof \PhpParser\Node\Expr\AssignRef || $node instanceof \PhpParser\Node\Expr\AssignOp || $node instanceof \PhpParser\Node\Stmt\Global_) {
			if ($node instanceof \PhpParser\Node\Expr\Assign || $node instanceof \PhpParser\Node\Expr\AssignRef || $node instanceof \PhpParser\Node\Expr\AssignOp) {
				$vars = [$node->var];
			} elseif ($node instanceof \PhpParser\Node\Stmt\Global_) {
				$vars = $node->vars;
			} else {
				throw new \PHPStan\ShouldNotHappenException();
			}

			foreach ($vars as $var) {
				$type = null;
				if ($node instanceof \PhpParser\Node\Expr\Assign || $node instanceof \PhpParser\Node\Expr\AssignRef) {
					$type = $scope->getType($node->expr);
				} elseif ($node instanceof \PhpParser\Node\Expr\AssignOp) {
					if (
						$node->var instanceof \PhpParser\Node\Expr\Variable
						&& is_string($node->var->name)
						&& !$scope->hasVariableType($node->var->name)->yes()
					) {
						continue;
					}
					$type = $scope->getType($node);
				} elseif (
					$node instanceof \PhpParser\Node\Stmt\Global_
					&& $var instanceof \PhpParser\Node\Expr\Variable
					&& is_string($var->name)
					&& $scope->hasVariableType($var->name)->no()
				) {
					$this->assignVariable($scope, $var, $certainty);
				}
				$scope = $this->assignVariable($scope, $var, $certainty, $type);
			}

			if ($node instanceof \PhpParser\Node\Expr\Assign || $node instanceof \PhpParser\Node\Expr\AssignRef) {
				if ($node->var instanceof \PhpParser\Node\Expr\Array_ || $node->var instanceof \PhpParser\Node\Expr\List_) {
					$scope = $this->lookForArrayDestructuringArray($scope, $node->var);
				}
			}

			if (!$node instanceof \PhpParser\Node\Stmt\Global_) {
				$scope = $this->lookForAssigns($scope, $node->expr, \PHPStan\TrinaryLogic::createYes());
			}

			if ($node instanceof \PhpParser\Node\Expr\Assign || $node instanceof \PhpParser\Node\Expr\AssignRef) {
				if ($node->var instanceof \PhpParser\Node\Expr\Variable && is_string($node->var->name)) {
					$comment = \PHPStan\Type\CommentHelper::getDocComment($node);
					if ($comment !== null) {
						$scope = $this->processVarAnnotation($scope, $node->var->name, $comment, false);
					}
				}
			}
		}

		return $scope;
	}

	private function processVarAnnotation(\PHPStan\Analyser\Scope $scope, string $variableName, string $comment, bool $strict): \PHPStan\Analyser\Scope
	{
		$resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc(
			$scope->getFile(),
			$scope->isInClass() ? $scope->getClassReflection()->getName() : null,
			$comment
		);
		$varTags = $resolvedPhpDoc->getVarTags();

		if (isset($varTags[$variableName])) {
			$variableType = $varTags[$variableName]->getType();
			return $scope->assignVariable($variableName, $variableType, \PHPStan\TrinaryLogic::createYes());

		} elseif (!$strict && count($varTags) === 1 && isset($varTags[0])) {
			$variableType = $varTags[0]->getType();
			return $scope->assignVariable($variableName, $variableType, \PHPStan\TrinaryLogic::createYes());

		} else {
			return $scope;
		}
	}

	private function assignVariable(
		\PHPStan\Analyser\Scope $scope,
		\PhpParser\Node $var,
		\PHPStan\TrinaryLogic $certainty,
		\PHPStan\Type\Type $subNodeType = null
	): \PHPStan\Analyser\Scope
	{
		if ($var instanceof \PhpParser\Node\Expr\Variable && is_string($var->name)) {
			$scope = $scope->assignVariable($var->name, $subNodeType !== null ? $subNodeType : new \PHPStan\Type\MixedType(), $certainty);
		} elseif ($var instanceof \PhpParser\Node\Expr\ArrayDimFetch) {
			$depth = 0;
			while ($var instanceof \PhpParser\Node\Expr\ArrayDimFetch) {
				$var = $var->var;
				$depth++;
			}

			if (isset($var->dim)) {
				$scope = $this->lookForAssigns($scope, $var->dim, \PHPStan\TrinaryLogic::createYes());
			}

			if ($var instanceof \PhpParser\Node\Expr\Variable && is_string($var->name)) {
				if ($scope->hasVariableType($var->name)->yes()) {
					$arrayDimFetchVariableType = $scope->getVariableType($var->name);
					if (
						!$arrayDimFetchVariableType instanceof \PHPStan\Type\ArrayType
						&& !$arrayDimFetchVariableType instanceof \PHPStan\Type\NullType
						&& !$arrayDimFetchVariableType instanceof \PHPStan\Type\MixedType
					) {
						return $scope;
					}
				}
				$arrayType = \PHPStan\Type\ArrayType::createDeepArrayType(
					new \PHPStan\Type\NestedArrayItemType($subNodeType !== null ? $subNodeType : new \PHPStan\Type\MixedType(), $depth),
					false
				);
				if ($scope->hasVariableType($var->name)->yes()) {
					if (
						!isset($arrayDimFetchVariableType)
						|| !$arrayDimFetchVariableType instanceof \PHPStan\Type\NullType
					) {
						$arrayType = \PHPStan\Type\TypeCombinator::union(
							$scope->getVariableType($var->name),
							$arrayType
						);
					}
				}

				$scope = $scope->assignVariable($var->name, $arrayType, $certainty);
			}
		} elseif ($var instanceof \PhpParser\Node\Expr\PropertyFetch && $subNodeType !== null) {
			$scope = $scope->specifyExpressionType($var, $subNodeType);
		} elseif ($var instanceof \PhpParser\Node\Expr\StaticPropertyFetch && $subNodeType !== null) {
			$scope = $scope->specifyExpressionType($var, $subNodeType);
		} else {
			$scope = $this->lookForAssigns($scope, $var, \PHPStan\TrinaryLogic::createYes());
		}

		return $scope;
	}

	/**
	 * @param \PHPStan\Analyser\Scope $initialScope
	 * @param \PHPStan\Analyser\StatementList[] $statementsLists
	 * @param \PHPStan\Analyser\LookForAssignsSettings $lookForAssignsSettings
	 * @return Scope
	 */
	private function lookForAssignsInBranches(
		\PHPStan\Analyser\Scope $initialScope,
		array $statementsLists,
		\PHPStan\Analyser\LookForAssignsSettings $lookForAssignsSettings
	): \PHPStan\Analyser\Scope
	{
		/** @var \PHPStan\Analyser\Scope|null $intersectedScope */
		$intersectedScope = null;
		foreach ($statementsLists as $i => $statementList) {
			$statements = $statementList->getStatements();
			$branchScope = $statementList->getScope();
			$branchScopeWithInitialScopeRemoved = $branchScope->removeVariables($initialScope, true);

			$earlyTerminationStatement = null;
			foreach ($statements as $statement) {
				$branchScope = $this->lookForAssigns($branchScope, $statement, \PHPStan\TrinaryLogic::createYes(), $lookForAssignsSettings);
				$branchScopeWithInitialScopeRemoved = $branchScope->removeVariables($initialScope, false);
				$earlyTerminationStatement = $this->findStatementEarlyTermination($statement, $branchScope);
				if ($earlyTerminationStatement !== null) {
					if ($lookForAssignsSettings->shouldSkipBranch($earlyTerminationStatement)) {
						continue 2;
					}
					break;
				}
			}

			if ($lookForAssignsSettings->shouldIntersectVariables($earlyTerminationStatement)) {
				if ($intersectedScope === null) {
					$intersectedScope = $initialScope->createIntersectedScope($branchScopeWithInitialScopeRemoved);
				} else {
					$intersectedScope = $intersectedScope->intersectVariables($branchScopeWithInitialScopeRemoved);
				}

				if ($statementList->shouldFilterByTruthyValue()) {
					/** @var \PhpParser\Node\Expr $statement */
					foreach ($statements as $statement) {
						$intersectedScope = $intersectedScope->filterByTruthyValue($statement);
					}
				}
			}
		}

		if ($intersectedScope !== null) {
			$scope = $initialScope->mergeWithIntersectedScope($intersectedScope);

			return $scope;
		}

		return $initialScope;
	}

	/**
	 * @param \PhpParser\Node[] $statements
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return \PhpParser\Node|null
	 */
	private function findEarlyTermination(array $statements, \PHPStan\Analyser\Scope $scope)
	{
		foreach ($statements as $statement) {
			$statement = $this->findStatementEarlyTermination($statement, $scope);
			if ($statement !== null) {
				return $statement;
			}
		}

		return null;
	}

	/**
	 * @param \PhpParser\Node $statement
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return \PhpParser\Node|null
	 */
	private function findStatementEarlyTermination(\PhpParser\Node $statement, \PHPStan\Analyser\Scope $scope)
	{
		if (
			$statement instanceof \PhpParser\Node\Stmt\Throw_
			|| $statement instanceof \PhpParser\Node\Stmt\Return_
			|| $statement instanceof \PhpParser\Node\Stmt\Continue_
			|| $statement instanceof \PhpParser\Node\Stmt\Break_
			|| $statement instanceof \PhpParser\Node\Expr\Exit_
		) {
			return $statement;
		} elseif ($statement instanceof \PhpParser\Node\Expr\MethodCall && count($this->earlyTerminatingMethodCalls) > 0) {
			if (!is_string($statement->name)) {
				return null;
			}

			$methodCalledOnType = $scope->getType($statement->var);
			foreach ($methodCalledOnType->getReferencedClasses() as $referencedClass) {
				if (!$this->broker->hasClass($referencedClass)) {
					continue;
				}

				$classReflection = $this->broker->getClass($referencedClass);
				foreach (array_merge([$referencedClass], $classReflection->getParentClassesNames()) as $className) {
					if (!isset($this->earlyTerminatingMethodCalls[$className])) {
						continue;
					}

					if (in_array($statement->name, $this->earlyTerminatingMethodCalls[$className], true)) {
						return $statement;
					}
				}
			}

			return null;
		} elseif ($statement instanceof \PhpParser\Node\Stmt\If_) {
			if ($statement->else === null) {
				return null;
			}

			if ($this->findEarlyTermination($statement->stmts, $scope) === null) {
				return null;
			}

			foreach ($statement->elseifs as $elseIfStatement) {
				if ($this->findEarlyTermination($elseIfStatement->stmts, $scope) === null) {
					return null;
				}
			}

			if ($this->findEarlyTermination($statement->else->stmts, $scope) === null) {
				return null;
			}

			return $statement;
		}

		return null;
	}

	/**
	 * @param \PhpParser\Node\Expr $functionCall
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return null|\PHPStan\Reflection\ParametersAcceptor
	 */
	private function findParametersAcceptorInFunctionCall(\PhpParser\Node\Expr $functionCall, \PHPStan\Analyser\Scope $scope)
	{
		if ($functionCall instanceof \PhpParser\Node\Expr\FuncCall && $functionCall->name instanceof \PhpParser\Node\Name) {
			if ($this->broker->hasFunction($functionCall->name, $scope)) {
				return $this->broker->getFunction($functionCall->name, $scope);
			}
		} elseif ($functionCall instanceof \PhpParser\Node\Expr\MethodCall && is_string($functionCall->name)) {
			$type = $scope->getType($functionCall->var);
			$methodName = $functionCall->name;
			if ($type->hasMethod($methodName)) {
				return $type->getMethod($methodName, $scope);
			}
		} elseif (
			$functionCall instanceof \PhpParser\Node\Expr\StaticCall
			&& $functionCall->class instanceof \PhpParser\Node\Name
			&& is_string($functionCall->name)) {
			$className = $scope->resolveName($functionCall->class);
			if ($this->broker->hasClass($className)) {
				$classReflection = $this->broker->getClass($className);
				if ($classReflection->hasMethod($functionCall->name)) {
					return $classReflection->getMethod($functionCall->name, $scope);
				}
			}
		}

		return null;
	}

	private function processTraitUse(\PhpParser\Node\Stmt\TraitUse $node, \PHPStan\Analyser\Scope $classScope, \Closure $nodeCallback)
	{
		foreach ($node->traits as $trait) {
			$traitName = (string) $trait;
			if (!$this->broker->hasClass($traitName)) {
				continue;
			}
			$traitReflection = $this->broker->getClass($traitName);
			$traitFileName = $traitReflection->getFileName();
			if ($traitFileName === false) {
				throw new \PHPStan\ShouldNotHappenException();
			}
			$fileName = $this->fileHelper->normalizePath($traitFileName);
			if (!isset($this->analysedFiles[$fileName])) {
				return;
			}
			$parserNodes = $this->parser->parseFile($fileName);
			$className = sprintf('class %s', $classScope->getClassReflection()->getDisplayName());
			if ($classScope->getClassReflection()->isAnonymous()) {
				$className = 'anonymous class';
			}
			$classScope = $classScope->changeAnalysedContextFile(
				sprintf(
					'%s (in context of %s)',
					$fileName,
					$className
				)
			);

			$this->processNodesForTraitUse($parserNodes, $traitName, $classScope, $nodeCallback);
		}
	}

	/**
	 * @param \PhpParser\Node[]|\PhpParser\Node $node
	 * @param string $traitName
	 * @param \PHPStan\Analyser\Scope $classScope
	 * @param \Closure $nodeCallback
	 */
	private function processNodesForTraitUse($node, string $traitName, \PHPStan\Analyser\Scope $classScope, \Closure $nodeCallback)
	{
		if ($node instanceof \PhpParser\Node) {
			if ($node instanceof \PhpParser\Node\Stmt\Trait_ && $traitName === (string) $node->namespacedName) {
				$this->processNodes($node->stmts, $classScope->enterFirstLevelStatements(), $nodeCallback);
				return;
			}
			if ($node instanceof \PhpParser\Node\Stmt\ClassLike) {
				return;
			}
			foreach ($node->getSubNodeNames() as $subNodeName) {
				$subNode = $node->{$subNodeName};
				$this->processNodesForTraitUse($subNode, $traitName, $classScope, $nodeCallback);
			}
		} elseif (is_array($node)) {
			foreach ($node as $subNode) {
				$this->processNodesForTraitUse($subNode, $traitName, $classScope, $nodeCallback);
			}
		}
	}

	private function enterClassMethod(\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Stmt\ClassMethod $classMethod): \PHPStan\Analyser\Scope
	{
		list($phpDocParameterTypes, $phpDocReturnType) = $this->getPhpDocs($scope, $classMethod);

		return $scope->enterClassMethod(
			$classMethod,
			$phpDocParameterTypes,
			$phpDocReturnType
		);
	}

	private function getPhpDocs(\PHPStan\Analyser\Scope $scope, \PhpParser\Node\FunctionLike $functionLike): array
	{
		$phpDocParameterTypes = [];
		$phpDocReturnType = null;
		if ($functionLike->getDocComment() !== null) {
			$docComment = $functionLike->getDocComment()->getText();
			$file = $scope->getFile();
			$class = $scope->isInClass() ? $scope->getClassReflection()->getName() : null;
			if ($functionLike instanceof \PhpParser\Node\Stmt\ClassMethod) {
				$phpDocBlock = \PHPStan\PhpDoc\PhpDocBlock::resolvePhpDocBlockForMethod(
					$this->broker,
					$docComment,
					$scope->getClassReflection()->getName(),
					$functionLike->name,
					$file
				);
				$docComment = $phpDocBlock->getDocComment();
				$file = $phpDocBlock->getFile();
				$class = $phpDocBlock->getClass();
			}

			$resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc(
				$file,
				$class,
				$docComment
			);
			$phpDocParameterTypes = array_map(function (\PHPStan\PhpDoc\Tag\ParamTag $tag): \PHPStan\Type\Type {
				return $tag->getType();
			}, $resolvedPhpDoc->getParamTags());
			$phpDocReturnType = $resolvedPhpDoc->getReturnTag() !== null ? $resolvedPhpDoc->getReturnTag()->getType() : null;
		}

		return [$phpDocParameterTypes, $phpDocReturnType];
	}

	private function enterFunction(\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Stmt\Function_ $function): \PHPStan\Analyser\Scope
	{
		list($phpDocParameterTypes, $phpDocReturnType) = $this->getPhpDocs($scope, $function);

		return $scope->enterFunction(
			$function,
			$phpDocParameterTypes,
			$phpDocReturnType
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Analyser;
use PHPStan\Broker\Broker;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\ClassMemberReflection;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParametersAcceptor;
use PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection;
use PHPStan\Reflection\Php\PhpMethodFromParserNodeReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
use PHPStan\Type\CallableType;
use PHPStan\Type\ErrorType;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\IterableIterableType;
use PHPStan\Type\MixedType;
use PHPStan\Type\NonexistentParentClassType;
use PHPStan\Type\NullType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\ObjectWithoutClassType;
use PHPStan\Type\StaticResolvableType;
use PHPStan\Type\StaticType;
use PHPStan\Type\StringType;
use PHPStan\Type\ThisType;
use PHPStan\Type\TrueOrFalseBooleanType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\VoidType;

class Scope
{

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	/**
	 * @var \PhpParser\PrettyPrinter\Standard
	 */
	private $printer;

	/**
	 * @var \PHPStan\Analyser\TypeSpecifier
	 */
	private $typeSpecifier;

	/**
	 * @var string
	 */
	private $file;

	/**
	 * @var \PHPStan\Type\Type[]
	 */
	private $resolvedTypes = [];

	/**
	 * @var string
	 */
	private $analysedContextFile;

	/**
	 * @var bool
	 */
	private $declareStrictTypes;

	/**
	 * @var \PHPStan\Reflection\ClassReflection|null
	 */
	private $classReflection;

	/**
	 * @var \PHPStan\Reflection\ParametersAcceptor|null
	 */
	private $function;

	/**
	 * @var string|null
	 */
	private $namespace;

	/**
	 * @var \PHPStan\Analyser\VariableTypeHolder[]
	 */
	private $variableTypes;

	/**
	 * @var \PHPStan\Type\Type[]
	 */
	private $moreSpecificTypes;

	/**
	 * @var string|null
	 */
	private $inClosureBindScopeClass;

	/**
	 * @var \PHPStan\Type\Type|null
	 */
	private $inAnonymousFunctionReturnType;

	/**
	 * @var \PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|null
	 */
	private $inFunctionCall;

	/**
	 * @var bool
	 */
	private $negated;

	/**
	 * @var bool
	 */
	private $inFirstLevelStatement;

	/**
	 * @var string[]
	 */
	private $currentlyAssignedExpressions = [];

	/**
	 * @param \PHPStan\Broker\Broker $broker
	 * @param \PhpParser\PrettyPrinter\Standard $printer
	 * @param \PHPStan\Analyser\TypeSpecifier $typeSpecifier
	 * @param string $file
	 * @param string|null $analysedContextFile
	 * @param bool $declareStrictTypes
	 * @param \PHPStan\Reflection\ClassReflection|null $classReflection
	 * @param \PHPStan\Reflection\ParametersAcceptor|null $function
	 * @param string|null $namespace
	 * @param \PHPStan\Analyser\VariableTypeHolder[] $variablesTypes
	 * @param \PHPStan\Type\Type[] $moreSpecificTypes
	 * @param string|null $inClosureBindScopeClass
	 * @param \PHPStan\Type\Type|null $inAnonymousFunctionReturnType
	 * @param \PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|null $inFunctionCall
	 * @param bool $negated
	 * @param bool $inFirstLevelStatement
	 * @param string[] $currentlyAssignedExpressions
	 */
	public function __construct(
		\PHPStan\Broker\Broker $broker,
		\PhpParser\PrettyPrinter\Standard $printer,
		\PHPStan\Analyser\TypeSpecifier $typeSpecifier,
		string $file,
		string $analysedContextFile = null,
		bool $declareStrictTypes = false,
		\PHPStan\Reflection\ClassReflection $classReflection = null,
		\PHPStan\Reflection\ParametersAcceptor $function = null,
		string $namespace = null,
		array $variablesTypes = [],
		array $moreSpecificTypes = [],
		string $inClosureBindScopeClass = null,
		\PHPStan\Type\Type $inAnonymousFunctionReturnType = null,
		\PhpParser\Node\Expr $inFunctionCall = null,
		bool $negated = false,
		bool $inFirstLevelStatement = true,
		array $currentlyAssignedExpressions = []
	)
	{
		if ($namespace === '') {
			$namespace = null;
		}

		$this->broker = $broker;
		$this->printer = $printer;
		$this->typeSpecifier = $typeSpecifier;
		$this->file = $file;
		$this->analysedContextFile = $analysedContextFile !== null ? $analysedContextFile : $file;
		$this->declareStrictTypes = $declareStrictTypes;
		$this->classReflection = $classReflection;
		$this->function = $function;
		$this->namespace = $namespace;
		$this->variableTypes = $variablesTypes;
		$this->moreSpecificTypes = $moreSpecificTypes;
		$this->inClosureBindScopeClass = $inClosureBindScopeClass;
		$this->inAnonymousFunctionReturnType = $inAnonymousFunctionReturnType;
		$this->inFunctionCall = $inFunctionCall;
		$this->negated = $negated;
		$this->inFirstLevelStatement = $inFirstLevelStatement;
		$this->currentlyAssignedExpressions = $currentlyAssignedExpressions;
	}

	public function getFile(): string
	{
		return $this->file;
	}

	public function getAnalysedContextFile(): string
	{
		return $this->analysedContextFile;
	}

	public function isDeclareStrictTypes(): bool
	{
		return $this->declareStrictTypes;
	}

	public function enterDeclareStrictTypes(): self
	{
		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			true
		);
	}

	public function isInClass(): bool
	{
		return $this->classReflection !== null;
	}

	public function getClassReflection(): \PHPStan\Reflection\ClassReflection
	{
		/** @var \PHPStan\Reflection\ClassReflection $classReflection */
		$classReflection = $this->classReflection;
		return $classReflection;
	}

	/**
	 * @return null|\PHPStan\Reflection\ParametersAcceptor
	 */
	public function getFunction()
	{
		return $this->function;
	}

	/**
	 * @return null|string
	 */
	public function getFunctionName()
	{
		return $this->function !== null ? $this->function->getName() : null;
	}

	/**
	 * @return null|string
	 */
	public function getNamespace()
	{
		return $this->namespace;
	}

	/**
	 * @return \PHPStan\Analyser\VariableTypeHolder[]
	 */
	private function getVariableTypes(): array
	{
		return $this->variableTypes;
	}

	public function hasVariableType(string $variableName): \PHPStan\TrinaryLogic
	{
		if (!isset($this->variableTypes[$variableName])) {
			return \PHPStan\TrinaryLogic::createNo();
		}

		return $this->variableTypes[$variableName]->getCertainty();
	}

	public function getVariableType(string $variableName): \PHPStan\Type\Type
	{
		if ($this->hasVariableType($variableName)->no()) {
			throw new \PHPStan\Analyser\UndefinedVariableException($this, $variableName);
		}

		return $this->variableTypes[$variableName]->getType();
	}

	public function isInAnonymousFunction(): bool
	{
		return $this->inAnonymousFunctionReturnType !== null;
	}

	/**
	 * @return \PHPStan\Type\Type|null
	 */
	public function getAnonymousFunctionReturnType()
	{
		return $this->inAnonymousFunctionReturnType;
	}

	/**
	 * @return \PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|null
	 */
	public function getInFunctionCall()
	{
		return $this->inFunctionCall;
	}

	public function getType(\PhpParser\Node\Expr $node): \PHPStan\Type\Type
	{
		$key = $this->printer->prettyPrintExpr($node);
		if (!array_key_exists($key, $this->resolvedTypes)) {
			$this->resolvedTypes[$key] = $this->resolveType($node);
		}
		return $this->resolvedTypes[$key];
	}

	private function resolveType(\PhpParser\Node\Expr $node): \PHPStan\Type\Type
	{
		if (
			$node instanceof \PhpParser\Node\Expr\BinaryOp\BooleanAnd
			|| $node instanceof \PhpParser\Node\Expr\BinaryOp\BooleanOr
			|| $node instanceof \PhpParser\Node\Expr\BinaryOp\LogicalAnd
			|| $node instanceof \PhpParser\Node\Expr\BinaryOp\LogicalOr
			|| $node instanceof \PhpParser\Node\Expr\BooleanNot
			|| $node instanceof \PhpParser\Node\Expr\BinaryOp\LogicalXor
			|| $node instanceof \PhpParser\Node\Expr\BinaryOp\Greater
			|| $node instanceof \PhpParser\Node\Expr\BinaryOp\GreaterOrEqual
			|| $node instanceof \PhpParser\Node\Expr\BinaryOp\Smaller
			|| $node instanceof \PhpParser\Node\Expr\BinaryOp\SmallerOrEqual
			|| $node instanceof \PhpParser\Node\Expr\BinaryOp\Identical
			|| $node instanceof \PhpParser\Node\Expr\BinaryOp\NotIdentical
			|| $node instanceof \PhpParser\Node\Expr\BinaryOp\Equal
			|| $node instanceof \PhpParser\Node\Expr\BinaryOp\NotEqual
			|| $node instanceof \PhpParser\Node\Expr\Instanceof_
			|| $node instanceof \PhpParser\Node\Expr\Isset_
			|| $node instanceof \PhpParser\Node\Expr\Empty_
		) {
			return new \PHPStan\Type\TrueOrFalseBooleanType();
		}

		if (
			$node instanceof \PhpParser\Node\Expr\UnaryMinus
			|| $node instanceof \PhpParser\Node\Expr\UnaryPlus
			|| $node instanceof \PhpParser\Node\Expr\ErrorSuppress
			|| $node instanceof \PhpParser\Node\Expr\Assign
		) {
			return $this->getType($node->expr);
		}

		if ($node instanceof \PhpParser\Node\Expr\BinaryOp\Mod) {
			return new \PHPStan\Type\IntegerType();
		}

		if ($node instanceof \PhpParser\Node\Expr\BinaryOp\Concat) {
			return new \PHPStan\Type\StringType();
		}

		if ($node instanceof \PhpParser\Node\Expr\BinaryOp\Spaceship) {
			return new \PHPStan\Type\IntegerType();
		}

		if ($node instanceof \PhpParser\Node\Expr\Ternary) {
			$conditionScope = $this->filterByTruthyValue($node->cond);
			$negatedConditionScope = $this->filterByFalseyValue($node->cond);
			$elseType = $negatedConditionScope->getType($node->else);
			if ($node->if === null) {
				return \PHPStan\Type\TypeCombinator::union($conditionScope->getType($node->cond), $elseType);
			}

			return \PHPStan\Type\TypeCombinator::union($conditionScope->getType($node->if), $elseType);
		}

		if ($node instanceof \PhpParser\Node\Expr\BinaryOp\Coalesce) {
			return \PHPStan\Type\TypeCombinator::union(
				\PHPStan\Type\TypeCombinator::removeNull($this->getType($node->left)),
				$this->getType($node->right)
			);
		}

		if ($node instanceof \PhpParser\Node\Expr\Clone_) {
			return $this->getType($node->expr);
		}

		if ($node instanceof \PhpParser\Node\Expr\AssignOp\Concat) {
			return new \PHPStan\Type\StringType();
		}

		if (
			$node instanceof \PhpParser\Node\Expr\AssignOp\ShiftLeft
			|| $node instanceof \PhpParser\Node\Expr\AssignOp\ShiftRight
			|| $node instanceof \PhpParser\Node\Expr\AssignOp\Mod
		) {
			return new \PHPStan\Type\IntegerType();
		}

		if (
			$node instanceof \PhpParser\Node\Expr\BinaryOp\Plus
			|| $node instanceof \PhpParser\Node\Expr\BinaryOp\Minus
			|| $node instanceof \PhpParser\Node\Expr\BinaryOp\Mul
			|| $node instanceof \PhpParser\Node\Expr\BinaryOp\Pow
			|| $node instanceof \PhpParser\Node\Expr\BinaryOp\Div
			|| $node instanceof \PhpParser\Node\Expr\AssignOp
		) {
			if ($node instanceof \PhpParser\Node\Expr\AssignOp) {
				$left = $node->var;
				$right = $node->expr;
			} elseif ($node instanceof \PhpParser\Node\Expr\BinaryOp) {
				$left = $node->left;
				$right = $node->right;
			} else {
				throw new \PHPStan\ShouldNotHappenException();
			}

			$leftType = $this->getType($left);
			$rightType = $this->getType($right);

			if ($leftType instanceof \PHPStan\Type\BooleanType) {
				$leftType = new \PHPStan\Type\IntegerType();
			}

			if ($rightType instanceof \PHPStan\Type\BooleanType) {
				$rightType = new \PHPStan\Type\IntegerType();
			}

			if ($node instanceof \PhpParser\Node\Expr\AssignOp\Div || $node instanceof \PhpParser\Node\Expr\BinaryOp\Div) {
				if (!$leftType instanceof \PHPStan\Type\MixedType && !$rightType instanceof \PHPStan\Type\MixedType) {
					return new \PHPStan\Type\FloatType();
				}
			}

			if (
				($leftType instanceof \PHPStan\Type\FloatType && !$rightType instanceof \PHPStan\Type\MixedType)
				|| ($rightType instanceof \PHPStan\Type\FloatType && !$leftType instanceof \PHPStan\Type\MixedType)
			) {
				return new \PHPStan\Type\FloatType();
			}

			if ($leftType instanceof \PHPStan\Type\IntegerType && $rightType instanceof \PHPStan\Type\IntegerType) {
				return new \PHPStan\Type\IntegerType();
			}

			if (
				($node instanceof \PhpParser\Node\Expr\AssignOp\Plus || $node instanceof \PhpParser\Node\Expr\BinaryOp\Plus)
				&& $leftType instanceof \PHPStan\Type\ArrayType
				&& $rightType instanceof \PHPStan\Type\ArrayType
			) {
				return new \PHPStan\Type\ArrayType(
					\PHPStan\Type\TypeCombinator::union($leftType->getIterableKeyType(), $rightType->getIterableKeyType()),
					\PHPStan\Type\TypeCombinator::union($leftType->getItemType(), $rightType->getItemType()),
					$leftType->isItemTypeInferredFromLiteralArray() || $rightType->isItemTypeInferredFromLiteralArray()
				);
			}
		}

		if ($node instanceof \PhpParser\Node\Scalar\LNumber) {
			return new \PHPStan\Type\IntegerType();
		} elseif ($node instanceof \PhpParser\Node\Expr\ConstFetch) {
			$constName = strtolower((string) $node->name);
			if ($constName === 'true') {
				return new \PHPStan\Type\TrueBooleanType();
			} elseif ($constName === 'false') {
				return new \PHPStan\Type\FalseBooleanType();
			} elseif ($constName === 'null') {
				return new \PHPStan\Type\NullType();
			}

			if ($this->broker->hasConstant($node->name, $this)) {
				$typeFromValue = $this->getTypeFromValue(
					constant($this->broker->resolveConstantName($node->name, $this))
				);
				if ($typeFromValue !== null) {
					return $typeFromValue;
				}
			}
		} elseif ($node instanceof \PhpParser\Node\Scalar\String_ || $node instanceof \PhpParser\Node\Scalar\Encapsed) {
			return new \PHPStan\Type\StringType();
		} elseif ($node instanceof \PhpParser\Node\Scalar\DNumber) {
			return new \PHPStan\Type\FloatType();
		} elseif ($node instanceof \PhpParser\Node\Expr\Closure) {
			return new \PHPStan\Type\ObjectType('Closure');
		} elseif ($node instanceof \PhpParser\Node\Expr\New_) {
			if ($node->class instanceof \PhpParser\Node\Name) {
				if (
					count($node->class->parts) === 1
				) {
					if ($node->class->parts[0] === 'static') {
						return new \PHPStan\Type\StaticType($this->getClassReflection()->getName());
					} elseif ($node->class->parts[0] === 'self') {
						return new \PHPStan\Type\ObjectType($this->getClassReflection()->getName());
					}
				}

				return new \PHPStan\Type\ObjectType((string) $node->class);
			}
		} elseif ($node instanceof \PhpParser\Node\Expr\Array_) {
			$itemTypes = array_map(
				function (\PhpParser\Node\Expr\ArrayItem $item): \PHPStan\Type\Type {
					return $this->getType($item->value);
				},
				$node->items
			);

			$callable = \PHPStan\TrinaryLogic::createNo();
			if (count($itemTypes) === 2) {
				if (
					($itemTypes[0]->accepts(new \PHPStan\Type\StringType()) || count($itemTypes[0]->getReferencedClasses()) > 0)
					&& $itemTypes[1]->accepts(new \PHPStan\Type\StringType())
				) {
					$callable = \PHPStan\TrinaryLogic::createYes();
				}
			}

			$arrayWithKeys = [];
			$keyExpressionTypes = [];
			foreach ($node->items as $arrayItem) {
				$itemKey = $arrayItem->key;
				if ($itemKey === null) {
					$arrayWithKeys[] = 'foo';
					continue;
				}

				if (
					$itemKey instanceof \PhpParser\Node\Scalar\String_
					|| $itemKey instanceof \PhpParser\Node\Scalar\LNumber
					|| $itemKey instanceof \PhpParser\Node\Scalar\DNumber
					|| $itemKey instanceof \PhpParser\Node\Expr\ConstFetch
				) {
					if ($itemKey instanceof \PhpParser\Node\Expr\ConstFetch) {
						$constName = strtolower((string) $itemKey->name);
						if ($constName === 'true') {
							$value = true;
						} elseif ($constName === 'false') {
							$value = false;
						} elseif ($constName === 'null') {
							$value = null;
						} elseif ($this->broker->hasConstant($itemKey->name, $this)) {
							$value = constant($this->broker->resolveConstantName($itemKey->name, $this));
						} else {
							$keyExpressionTypes[] = new \PHPStan\Type\MixedType();
							continue;
						}

						$arrayWithKeys[$value] = 'foo';
					} else {
						$arrayWithKeys[$itemKey->value] = 'foo';
					}
				} else {
					$keyExpressionTypes[] = $this->getType($itemKey);
				}
			}

			$scalarKeysTypes = array_map(function ($value): \PHPStan\Type\Type {
				return $this->getTypeFromValue($value);
			}, array_keys($arrayWithKeys));

			return new \PHPStan\Type\ArrayType(
				$this->getCombinedType(array_merge($scalarKeysTypes, $keyExpressionTypes)),
				$this->getCombinedType($itemTypes),
				true,
				$callable
			);
		} elseif ($node instanceof \PhpParser\Node\Expr\Cast\Int_) {
				return new \PHPStan\Type\IntegerType();
		} elseif ($node instanceof \PhpParser\Node\Expr\Cast\Bool_) {
			return new \PHPStan\Type\TrueOrFalseBooleanType();
		} elseif ($node instanceof \PhpParser\Node\Expr\Cast\Double) {
			return new \PHPStan\Type\FloatType();
		} elseif ($node instanceof \PhpParser\Node\Expr\Cast\String_) {
			return new \PHPStan\Type\StringType();
		} elseif ($node instanceof \PhpParser\Node\Expr\Cast\Array_) {
			return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType());
		} elseif ($node instanceof \PhpParser\Node\Scalar\MagicConst\Line) {
			return new \PHPStan\Type\IntegerType();
		} elseif ($node instanceof \PhpParser\Node\Scalar\MagicConst) {
			return new \PHPStan\Type\StringType();
		} elseif ($node instanceof \PhpParser\Node\Expr\Cast\Object_) {
			return new \PHPStan\Type\ObjectType('stdClass');
		} elseif ($node instanceof \PhpParser\Node\Expr\Cast\Unset_) {
			return new \PHPStan\Type\NullType();
		} elseif ($node instanceof \PhpParser\Node\Expr\ClassConstFetch && is_string($node->name)) {
			if ($node->class instanceof \PhpParser\Node\Name) {
				$constantClass = (string) $node->class;
				$constantClassType = new \PHPStan\Type\ObjectType($constantClass);
				if (in_array(strtolower($constantClass), [
					'self',
					'parent',
				], true)) {
					$resolvedName = $this->resolveName($node->class);
					$constantClassType = new \PHPStan\Type\ObjectType($resolvedName);
				}
			} else {
				$constantClassType = $this->getType($node->class);
			}

			$constantName = $node->name;
			if (strtolower($constantName) === 'class') {
				return new \PHPStan\Type\StringType();
			}
			if ($constantClassType->hasConstant($constantName)) {
				$constant = $constantClassType->getConstant($constantName);
				$typeFromValue = $this->getTypeFromValue($constant->getValue());
				if ($typeFromValue !== null) {
					return $typeFromValue;
				}
			}
		}

		$exprString = $this->printer->prettyPrintExpr($node);
		if (isset($this->moreSpecificTypes[$exprString])) {
			return $this->moreSpecificTypes[$exprString];
		}

		if ($node instanceof \PhpParser\Node\Expr\Variable && is_string($node->name)) {
			if ($this->hasVariableType($node->name)->no()) {
				return new \PHPStan\Type\ErrorType();
			}

			return $this->getVariableType($node->name);
		}

		if ($node instanceof \PhpParser\Node\Expr\ArrayDimFetch && $node->dim !== null) {
			$arrayType = $this->getType($node->var);
			if ($arrayType instanceof \PHPStan\Type\ArrayType) {
				return $arrayType->getItemType();
			}
		}

		if ($node instanceof \PhpParser\Node\Expr\MethodCall && is_string($node->name)) {
			$methodCalledOnType = $this->getType($node->var);
			$referencedClasses = $methodCalledOnType->getReferencedClasses();
			if (
				count($referencedClasses) === 1
				&& $this->broker->hasClass($referencedClasses[0])
			) {
				$methodClassReflection = $this->broker->getClass($referencedClasses[0]);
				if (!$methodClassReflection->hasMethod($node->name)) {
					return new \PHPStan\Type\ErrorType();
				}

				$methodReflection = $methodClassReflection->getMethod($node->name, $this);
				foreach ($this->broker->getDynamicMethodReturnTypeExtensionsForClass($methodClassReflection->getName()) as $dynamicMethodReturnTypeExtension) {
					if (!$dynamicMethodReturnTypeExtension->isMethodSupported($methodReflection)) {
						continue;
					}

					return $dynamicMethodReturnTypeExtension->getTypeFromMethodCall($methodReflection, $node, $this);
				}
			}

			if (!$methodCalledOnType->hasMethod($node->name)) {
				return new \PHPStan\Type\ErrorType();
			}
			$methodReflection = $methodCalledOnType->getMethod($node->name, $this);

			$calledOnThis = $node->var instanceof \PhpParser\Node\Expr\Variable && is_string($node->var->name) && $node->var->name === 'this';
			$methodReturnType = $methodReflection->getReturnType();
			if ($methodReturnType instanceof \PHPStan\Type\StaticResolvableType) {
				if ($calledOnThis) {
					if ($this->isInClass()) {
						return $methodReturnType->changeBaseClass($this->getClassReflection()->getName());
					}
				} elseif (count($referencedClasses) === 1) {
					return $methodReturnType->resolveStatic($referencedClasses[0]);
				}
			}

			return $methodReflection->getReturnType();
		}

		if ($node instanceof \PhpParser\Node\Expr\StaticCall && is_string($node->name)) {
			if ($node->class instanceof \PhpParser\Node\Name) {
				$calleeType = new \PHPStan\Type\ObjectType($this->resolveName($node->class));
			} else {
				$calleeType = $this->getType($node->class);
			}

			if (!$calleeType->hasMethod($node->name)) {
				return new \PHPStan\Type\ErrorType();
			}
			$staticMethodReflection = $calleeType->getMethod($node->name, $this);
			$referencedClasses = $calleeType->getReferencedClasses();
			if (
				count($calleeType->getReferencedClasses()) === 1
				&& $this->broker->hasClass($referencedClasses[0])
			) {
				$staticMethodClassReflection = $this->broker->getClass($referencedClasses[0]);
				foreach ($this->broker->getDynamicStaticMethodReturnTypeExtensionsForClass($staticMethodClassReflection->getName()) as $dynamicStaticMethodReturnTypeExtension) {
					if (!$dynamicStaticMethodReturnTypeExtension->isStaticMethodSupported($staticMethodReflection)) {
						continue;
					}

					return $dynamicStaticMethodReturnTypeExtension->getTypeFromStaticMethodCall($staticMethodReflection, $node, $this);
				}
			}
			if ($staticMethodReflection->getReturnType() instanceof \PHPStan\Type\StaticResolvableType) {
				if ($node->class instanceof \PhpParser\Node\Name) {
					$nodeClassString = strtolower((string) $node->class);
					if (in_array($nodeClassString, [
						'self',
						'static',
						'parent',
					], true) && $this->isInClass()) {
						return $staticMethodReflection->getReturnType()->changeBaseClass($this->getClassReflection()->getName());
					}
				}
				if (count($referencedClasses) === 1) {
					return $staticMethodReflection->getReturnType()->resolveStatic($referencedClasses[0]);
				}
			}
			return $staticMethodReflection->getReturnType();
		}

		if ($node instanceof \PhpParser\Node\Expr\PropertyFetch && is_string($node->name)) {
			$propertyFetchedOnType = $this->getType($node->var);
			if (!$propertyFetchedOnType->hasProperty($node->name)) {
				return new \PHPStan\Type\ErrorType();
			}

			return $propertyFetchedOnType->getProperty($node->name, $this)->getType();
		}

		if ($node instanceof \PhpParser\Node\Expr\StaticPropertyFetch && is_string($node->name) && $node->class instanceof \PhpParser\Node\Name) {
			$staticPropertyHolderClass = $this->resolveName($node->class);
			if ($this->broker->hasClass($staticPropertyHolderClass)) {
				$staticPropertyClassReflection = $this->broker->getClass(
					$staticPropertyHolderClass
				);
				if (!$staticPropertyClassReflection->hasProperty($node->name)) {
					return new \PHPStan\Type\ErrorType();
				}

				return $staticPropertyClassReflection->getProperty($node->name, $this)->getType();
			}
		}

		if ($node instanceof \PhpParser\Node\Expr\FuncCall && $node->name instanceof \PhpParser\Node\Name) {
			if (!$this->broker->hasFunction($node->name, $this)) {
				return new \PHPStan\Type\ErrorType();
			}

			$functionReflection = $this->broker->getFunction($node->name, $this);

			foreach ($this->broker->getDynamicFunctionReturnTypeExtensions() as $dynamicFunctionReturnTypeExtension) {
				if (!$dynamicFunctionReturnTypeExtension->isFunctionSupported($functionReflection)) {
					continue;
				}

				return $dynamicFunctionReturnTypeExtension->getTypeFromFunctionCall($functionReflection, $node, $this);
			}

			return $functionReflection->getReturnType();
		}

		return new \PHPStan\Type\MixedType();
	}

	public function resolveName(\PhpParser\Node\Name $name): string
	{
		$originalClass = (string) $name;
		if ($this->isInClass()) {
			if (in_array(strtolower($originalClass), [
				'self',
				'static',
			], true)) {
				return $this->getClassReflection()->getName();
			} elseif ($originalClass === 'parent') {
				$currentClassReflection = $this->getClassReflection();
				if ($currentClassReflection->getParentClass() !== false) {
					return $currentClassReflection->getParentClass()->getName();
				}
			}
		}

		return $originalClass;
	}

	/**
	 * @param mixed $value
	 * @return Type|null
	 */
	private function getTypeFromValue($value)
	{
		if (is_int($value)) {
			return new \PHPStan\Type\IntegerType();
		} elseif (is_float($value)) {
			return new \PHPStan\Type\FloatType();
		} elseif (is_bool($value)) {
			return new \PHPStan\Type\TrueOrFalseBooleanType();
		} elseif ($value === null) {
			return new \PHPStan\Type\NullType();
		} elseif (is_string($value)) {
			return new \PHPStan\Type\StringType();
		} elseif (is_array($value)) {
			return new \PHPStan\Type\ArrayType(
				$this->getCombinedType(
					array_map(function ($value): \PHPStan\Type\Type {
						return $this->getTypeFromValue($value);
					}, array_keys($value))
				),
				$this->getCombinedType(
					array_map(function ($value): \PHPStan\Type\Type {
						return $this->getTypeFromValue($value);
					}, array_values($value))
				),
				false
			);
		}

		return null;
	}

	/**
	 * @param \PHPStan\Type\Type[] $types
	 * @return \PHPStan\Type\Type
	 */
	private function getCombinedType(array $types): \PHPStan\Type\Type
	{
		if (count($types) === 0) {
			return new \PHPStan\Type\MixedType();
		}

		return \PHPStan\Type\TypeCombinator::union(...$types);
	}

	public function isSpecified(\PhpParser\Node\Expr $node): bool
	{
		$exprString = $this->printer->prettyPrintExpr($node);

		return isset($this->moreSpecificTypes[$exprString]);
	}

	public function enterClass(\PHPStan\Reflection\ClassReflection $classReflection): self
	{
		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			$this->isDeclareStrictTypes(),
			$classReflection,
			null,
			$this->getNamespace(),
			[
				'this' => \PHPStan\Analyser\VariableTypeHolder::createYes(new \PHPStan\Type\ThisType($classReflection->getName())),
			]
		);
	}

	public function changeAnalysedContextFile(string $fileName): self
	{
		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$fileName,
			$this->isDeclareStrictTypes(),
			$this->isInClass() ? $this->getClassReflection() : null,
			$this->getFunction(),
			$this->getNamespace(),
			$this->getVariableTypes(),
			$this->moreSpecificTypes,
			$this->inClosureBindScopeClass,
			$this->getAnonymousFunctionReturnType(),
			$this->getInFunctionCall(),
			$this->isNegated()
		);
	}

	public function enterClassMethod(
		\PhpParser\Node\Stmt\ClassMethod $classMethod,
		array $phpDocParameterTypes,
		\PHPStan\Type\Type $phpDocReturnType = null
	): self
	{
		return $this->enterFunctionLike(
			new \PHPStan\Reflection\Php\PhpMethodFromParserNodeReflection(
				$this->getClassReflection(),
				$classMethod,
				$this->getRealParameterTypes($classMethod),
				$phpDocParameterTypes,
				$classMethod->returnType !== null,
				$this->getFunctionType($classMethod->returnType, $classMethod->returnType === null, false),
				$phpDocReturnType
			)
		);
	}

	private function getRealParameterTypes(\PhpParser\Node\FunctionLike $functionLike): array
	{
		$realParameterTypes = [];
		foreach ($functionLike->getParams() as $parameter) {
			$realParameterTypes[$parameter->name] = $this->getFunctionType(
				$parameter->type,
				$this->isParameterValueNullable($parameter),
				$parameter->variadic
			);
		}

		return $realParameterTypes;
	}

	public function enterFunction(
		\PhpParser\Node\Stmt\Function_ $function,
		array $phpDocParameterTypes,
		\PHPStan\Type\Type $phpDocReturnType = null
	): self
	{
		return $this->enterFunctionLike(
			new \PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection(
				$function,
				$this->getRealParameterTypes($function),
				$phpDocParameterTypes,
				$function->returnType !== null,
				$this->getFunctionType($function->returnType, $function->returnType === null, false),
				$phpDocReturnType
			)
		);
	}

	private function enterFunctionLike(\PHPStan\Reflection\ParametersAcceptor $functionReflection): self
	{
		$variableTypes = $this->getVariableTypes();
		foreach ($functionReflection->getParameters() as $parameter) {
			$variableTypes[$parameter->getName()] = \PHPStan\Analyser\VariableTypeHolder::createYes($parameter->getType());
		}

		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			$this->isDeclareStrictTypes(),
			$this->isInClass() ? $this->getClassReflection() : null,
			$functionReflection,
			$this->getNamespace(),
			$variableTypes,
			[],
			null,
			null
		);
	}

	public function enterNamespace(string $namespaceName): self
	{
		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			$this->isDeclareStrictTypes(),
			null,
			null,
			$namespaceName
		);
	}

	public function enterClosureBind(\PHPStan\Type\Type $thisType = null, string $scopeClass): self
	{
		$variableTypes = $this->getVariableTypes();

		if ($thisType !== null) {
			$variableTypes['this'] = \PHPStan\Analyser\VariableTypeHolder::createYes($thisType);
		} else {
			unset($variableTypes['this']);
		}

		if ($scopeClass === 'static' && $this->isInClass()) {
			$scopeClass = $this->getClassReflection()->getName();
		}

		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			$this->isDeclareStrictTypes(),
			$this->isInClass() ? $this->getClassReflection() : null,
			$this->getFunction(),
			$this->getNamespace(),
			$variableTypes,
			$this->moreSpecificTypes,
			$scopeClass,
			$this->getAnonymousFunctionReturnType(),
			$this->getInFunctionCall(),
			$this->isNegated()
		);
	}

	public function isInClosureBind(): bool
	{
		return $this->inClosureBindScopeClass !== null;
	}

	public function enterAnonymousClass(\PHPStan\Reflection\ClassReflection $anonymousClass): self
	{
		return $this->enterClass($anonymousClass);
	}

	/**
	 * @param \PhpParser\Node\Param[] $parameters
	 * @param \PhpParser\Node\Expr\ClosureUse[] $uses
	 * @param \PhpParser\Node\Name|string|\PhpParser\Node\NullableType|null $returnTypehint
	 * @return self
	 */
	public function enterAnonymousFunction(
		array $parameters,
		array $uses,
		$returnTypehint = null
	): self
	{
		$variableTypes = [];
		foreach ($parameters as $parameter) {
			$isNullable = $this->isParameterValueNullable($parameter);

			$variableTypes[$parameter->name] = \PHPStan\Analyser\VariableTypeHolder::createYes(
				$this->getFunctionType($parameter->type, $isNullable, $parameter->variadic)
			);
		}

		foreach ($uses as $use) {
			if (!$this->hasVariableType($use->var)->yes()) {
				if ($use->byRef) {
					$variableTypes[$use->var] = \PHPStan\Analyser\VariableTypeHolder::createYes(new \PHPStan\Type\MixedType());
				}
				continue;
			}
			$variableTypes[$use->var] = \PHPStan\Analyser\VariableTypeHolder::createYes($this->getVariableType($use->var));
		}

		if ($this->hasVariableType('this')->yes()) {
			$variableTypes['this'] = \PHPStan\Analyser\VariableTypeHolder::createYes($this->getVariableType('this'));
		}

		$returnType = $this->getFunctionType($returnTypehint, $returnTypehint === null, false);

		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			$this->isDeclareStrictTypes(),
			$this->isInClass() ? $this->getClassReflection() : null,
			$this->getFunction(),
			$this->getNamespace(),
			$variableTypes,
			[],
			$this->inClosureBindScopeClass,
			$returnType,
			$this->getInFunctionCall()
		);
	}

	public function isParameterValueNullable(\PhpParser\Node\Param $parameter): bool
	{
		if ($parameter->default instanceof \PhpParser\Node\Expr\ConstFetch) {
			return strtolower((string) $parameter->default->name) === 'null';
		}

		return false;
	}

	/**
	 * @param \PhpParser\Node\Name|string|\PhpParser\Node\NullableType|null $type
	 * @param bool $isNullable
	 * @param bool $isVariadic
	 * @return Type
	 */
	public function getFunctionType($type = null, bool $isNullable, bool $isVariadic): \PHPStan\Type\Type
	{
		if ($isNullable) {
			return \PHPStan\Type\TypeCombinator::addNull(
				$this->getFunctionType($type, false, $isVariadic)
			);
		}
		if ($isVariadic) {
			return new \PHPStan\Type\ArrayType(new \PHPStan\Type\IntegerType(), $this->getFunctionType(
				$type,
				false,
				false
			), false);
		}
		if ($type === null) {
			return new \PHPStan\Type\MixedType();
		} elseif ($type === 'string') {
			return new \PHPStan\Type\StringType();
		} elseif ($type === 'int') {
			return new \PHPStan\Type\IntegerType();
		} elseif ($type === 'bool') {
			return new \PHPStan\Type\TrueOrFalseBooleanType();
		} elseif ($type === 'float') {
			return new \PHPStan\Type\FloatType();
		} elseif ($type === 'callable') {
			return new \PHPStan\Type\CallableType();
		} elseif ($type === 'array') {
			return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType());
		} elseif ($type instanceof \PhpParser\Node\Name) {
			$className = (string) $type;
			if ($className === 'self') {
				$className = $this->getClassReflection()->getName();
			} elseif (
				$className === 'parent'
			) {
				if ($this->isInClass() && $this->getClassReflection()->getParentClass() !== false) {
					return new \PHPStan\Type\ObjectType($this->getClassReflection()->getParentClass()->getName());
				}

				return new \PHPStan\Type\NonexistentParentClassType();
			}
			return new \PHPStan\Type\ObjectType($className);
		} elseif ($type === 'iterable') {
			return new \PHPStan\Type\IterableIterableType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType());
		} elseif ($type === 'void') {
			return new \PHPStan\Type\VoidType();
		} elseif ($type === 'object') {
			return new \PHPStan\Type\ObjectWithoutClassType();
		} elseif ($type instanceof \PhpParser\Node\NullableType) {
			return $this->getFunctionType($type->type, true, $isVariadic);
		}

		return new \PHPStan\Type\MixedType();
	}

	public function enterForeach(\PhpParser\Node\Expr $iteratee, string $valueName, string $keyName = null): self
	{
		$iterateeType = $this->getType($iteratee);
		$scope = $this->assignVariable($valueName, $iterateeType->getIterableValueType(), \PHPStan\TrinaryLogic::createYes());

		if ($keyName !== null) {
			$scope = $scope->assignVariable($keyName, $iterateeType->getIterableKeyType(), \PHPStan\TrinaryLogic::createYes());
		}

		return $scope;
	}

	/**
	 * @param \PhpParser\Node\Name[] $classes
	 * @param string $variableName
	 * @return Scope
	 */
	public function enterCatch(array $classes, string $variableName): self
	{
		$type = \PHPStan\Type\TypeCombinator::union(...array_map(function (string $class): \PHPStan\Type\ObjectType {
			return new \PHPStan\Type\ObjectType($class);
		}, $classes));

		return $this->assignVariable(
			$variableName,
			\PHPStan\Type\TypeCombinator::intersect($type, new \PHPStan\Type\ObjectType(\Throwable::class)),
			\PHPStan\TrinaryLogic::createYes()
		);
	}

	/**
	 * @param \PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $functionCall
	 * @return self
	 */
	public function enterFunctionCall($functionCall): self
	{
		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			$this->isDeclareStrictTypes(),
			$this->isInClass() ? $this->getClassReflection() : null,
			$this->getFunction(),
			$this->getNamespace(),
			$this->getVariableTypes(),
			$this->moreSpecificTypes,
			$this->inClosureBindScopeClass,
			$this->getAnonymousFunctionReturnType(),
			$functionCall,
			$this->isNegated(),
			$this->inFirstLevelStatement
		);
	}

	public function enterExpressionAssign(\PhpParser\Node\Expr $expr): self
	{
		$currentlyAssignedExpressions = $this->currentlyAssignedExpressions;
		$currentlyAssignedExpressions[] = $this->printer->prettyPrintExpr($expr);

		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			$this->isDeclareStrictTypes(),
			$this->isInClass() ? $this->getClassReflection() : null,
			$this->getFunction(),
			$this->getNamespace(),
			$this->getVariableTypes(),
			$this->moreSpecificTypes,
			$this->inClosureBindScopeClass,
			$this->getAnonymousFunctionReturnType(),
			$this->getInFunctionCall(),
			$this->isNegated(),
			$this->isInFirstLevelStatement(),
			$currentlyAssignedExpressions
		);
	}

	public function isInExpressionAssign(\PhpParser\Node\Expr $expr): bool
	{
		$exprString = $this->printer->prettyPrintExpr($expr);
		return in_array($exprString, $this->currentlyAssignedExpressions, true);
	}

	public function assignVariable(
		string $variableName,
		\PHPStan\Type\Type $type,
		\PHPStan\TrinaryLogic $certainty
	): self
	{
		if ($certainty->no()) {
			throw new \PHPStan\ShouldNotHappenException();
		}

		$existingCertainty = $this->hasVariableType($variableName);
		if (!$existingCertainty->no()) {
			$certainty = $certainty->or($existingCertainty);
		}

		$variableTypes = $this->getVariableTypes();
		$variableTypes[$variableName] = new \PHPStan\Analyser\VariableTypeHolder($type, $certainty);

		$exprString = $this->printer->prettyPrintExpr(new \PhpParser\Node\Expr\Variable($variableName));
		$moreSpecificTypes = $this->moreSpecificTypes;
		if (array_key_exists($exprString, $moreSpecificTypes)) {
			unset($moreSpecificTypes[$exprString]);
		}

		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			$this->isDeclareStrictTypes(),
			$this->isInClass() ? $this->getClassReflection() : null,
			$this->getFunction(),
			$this->getNamespace(),
			$variableTypes,
			$moreSpecificTypes,
			$this->inClosureBindScopeClass,
			$this->getAnonymousFunctionReturnType(),
			$this->getInFunctionCall(),
			$this->isNegated(),
			$this->inFirstLevelStatement
		);
	}

	public function unsetVariable(string $variableName): self
	{
		if ($this->hasVariableType($variableName)->no()) {
			return $this;
		}
		$variableTypes = $this->getVariableTypes();
		unset($variableTypes[$variableName]);

		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			$this->isDeclareStrictTypes(),
			$this->isInClass() ? $this->getClassReflection() : null,
			$this->getFunction(),
			$this->getNamespace(),
			$variableTypes,
			$this->moreSpecificTypes,
			$this->inClosureBindScopeClass,
			$this->getAnonymousFunctionReturnType(),
			$this->getInFunctionCall(),
			$this->isNegated(),
			$this->inFirstLevelStatement
		);
	}

	public function intersectVariables(\PHPStan\Analyser\Scope $otherScope): self
	{
		$ourVariableTypeHolders = $this->getVariableTypes();
		$theirVariableTypeHolders = $otherScope->getVariableTypes();
		$intersectedVariableTypeHolders = [];
		foreach ($theirVariableTypeHolders as $name => $variableTypeHolder) {
			if (isset($ourVariableTypeHolders[$name])) {
				$intersectedVariableTypeHolders[$name] = $ourVariableTypeHolders[$name]->and($variableTypeHolder);
			} else {
				$intersectedVariableTypeHolders[$name] = \PHPStan\Analyser\VariableTypeHolder::createMaybe($variableTypeHolder->getType());
			}
		}

		foreach ($ourVariableTypeHolders as $name => $variableTypeHolder) {
			$variableNode = new \PhpParser\Node\Expr\Variable($name);
			if ($otherScope->isSpecified($variableNode)) {
				$intersectedVariableTypeHolders[$name] = \PHPStan\Analyser\VariableTypeHolder::createYes(
					\PHPStan\Type\TypeCombinator::union(
						$otherScope->getType($variableNode),
						$variableTypeHolder->getType()
					)
				);
				continue;
			}
			if (isset($theirVariableTypeHolders[$name])) {
				continue;
			}

			$intersectedVariableTypeHolders[$name] = \PHPStan\Analyser\VariableTypeHolder::createMaybe($variableTypeHolder->getType());
		}

		$theirSpecifiedTypes = $otherScope->moreSpecificTypes;
		$intersectedSpecifiedTypes = [];
		foreach ($this->moreSpecificTypes as $exprString => $specificType) {
			if (!isset($theirSpecifiedTypes[$exprString])) {
				continue;
			}

			$intersectedSpecifiedTypes[$exprString] = \PHPStan\Type\TypeCombinator::union(
				$specificType,
				$theirSpecifiedTypes[$exprString]
			);
		}

		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			$this->isDeclareStrictTypes(),
			$this->isInClass() ? $this->getClassReflection() : null,
			$this->getFunction(),
			$this->getNamespace(),
			$intersectedVariableTypeHolders,
			$intersectedSpecifiedTypes,
			$this->inClosureBindScopeClass,
			$this->getAnonymousFunctionReturnType(),
			$this->getInFunctionCall(),
			$this->isNegated(),
			$this->inFirstLevelStatement
		);
	}

	public function createIntersectedScope(self $otherScope): self
	{
		$variableTypes = [];
		foreach ($otherScope->getVariableTypes() as $name => $variableTypeHolder) {
			$variableTypes[$name] = $variableTypeHolder;
		}

		$specifiedTypes = [];
		foreach ($otherScope->moreSpecificTypes as $exprString => $specificType) {
			$specifiedTypes[$exprString] = $specificType;
		}

		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			$this->isDeclareStrictTypes(),
			$this->isInClass() ? $this->getClassReflection() : null,
			$this->getFunction(),
			$this->getNamespace(),
			$variableTypes,
			$specifiedTypes,
			$this->inClosureBindScopeClass,
			$this->getAnonymousFunctionReturnType(),
			$this->getInFunctionCall(),
			$this->isNegated(),
			$this->inFirstLevelStatement
		);
	}

	public function mergeWithIntersectedScope(self $intersectedScope): self
	{
		$variableTypeHolders = $this->variableTypes;
		$specifiedTypes = $this->moreSpecificTypes;
		foreach ($intersectedScope->getVariableTypes() as $name => $theirVariableTypeHolder) {
			if (isset($variableTypeHolders[$name])) {
				$type = $theirVariableTypeHolder->getType();
				if ($theirVariableTypeHolder->getCertainty()->maybe()) {
					$type = \PHPStan\Type\TypeCombinator::union($type, $variableTypeHolders[$name]->getType());
				}
				$theirVariableTypeHolder = new \PHPStan\Analyser\VariableTypeHolder(
					$type,
					$theirVariableTypeHolder->getCertainty()->or($variableTypeHolders[$name]->getCertainty())
				);
			}

			$variableTypeHolders[$name] = $theirVariableTypeHolder->addMaybe();

			$exprString = $this->printer->prettyPrintExpr(new \PhpParser\Node\Expr\Variable($name));
			unset($specifiedTypes[$exprString]);
		}

		foreach ($intersectedScope->moreSpecificTypes as $exprString => $specificType) {
			if (preg_match('#^\$([a-zA-Z_][a-zA-Z0-9_]*)$#', $exprString, $matches) === 1) {
				$variableName = $matches[1];
				$variableTypeHolders[$variableName] = \PHPStan\Analyser\VariableTypeHolder::createYes($specificType);
				continue;
			}
			$specifiedTypes[$exprString] = $specificType;
		}

		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			$this->isDeclareStrictTypes(),
			$this->isInClass() ? $this->getClassReflection() : null,
			$this->getFunction(),
			$this->getNamespace(),
			$variableTypeHolders,
			$specifiedTypes,
			$this->inClosureBindScopeClass,
			$this->getAnonymousFunctionReturnType(),
			$this->getInFunctionCall(),
			$this->isNegated(),
			$this->inFirstLevelStatement
		);
	}

	public function removeVariables(self $otherScope, bool $all): self
	{
		$ourVariableTypeHolders = $this->getVariableTypes();
		foreach ($otherScope->getVariableTypes() as $name => $theirVariableTypeHolder) {
			if ($all) {
				if (
					isset($ourVariableTypeHolders[$name])
					&& $ourVariableTypeHolders[$name]->getCertainty()->equals($theirVariableTypeHolder->getCertainty())
				) {
					unset($ourVariableTypeHolders[$name]);
				}
			} else {
				if (
					isset($ourVariableTypeHolders[$name])
					&& $theirVariableTypeHolder->getType()->describe() === $ourVariableTypeHolders[$name]->getType()->describe()
					&& $ourVariableTypeHolders[$name]->getCertainty()->equals($theirVariableTypeHolder->getCertainty())
				) {
					unset($ourVariableTypeHolders[$name]);
				}
			}
		}

		$moreSpecificTypes = $this->moreSpecificTypes;
		foreach ($otherScope->moreSpecificTypes as $exprString => $specifiedType) {
			if (isset($moreSpecificTypes[$exprString]) && $specifiedType->describe() === $moreSpecificTypes[$exprString]->describe()) {
				unset($moreSpecificTypes[$exprString]);
			}
		}

		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			$this->isDeclareStrictTypes(),
			$this->isInClass() ? $this->getClassReflection() : null,
			$this->getFunction(),
			$this->getNamespace(),
			$ourVariableTypeHolders,
			$moreSpecificTypes,
			$this->inClosureBindScopeClass,
			$this->getAnonymousFunctionReturnType(),
			$this->getInFunctionCall(),
			$this->isNegated(),
			$this->inFirstLevelStatement
		);
	}

	public function specifyExpressionType(\PhpParser\Node\Expr $expr, \PHPStan\Type\Type $type): self
	{
		$exprString = $this->printer->prettyPrintExpr($expr);

		$scope = $this->addMoreSpecificTypes([
			$exprString => $type,
		]);

		if ($expr instanceof \PhpParser\Node\Expr\Variable && is_string($expr->name)) {
			$variableName = $expr->name;

			$variableTypes = $scope->getVariableTypes();
			$variableTypes[$variableName] = \PHPStan\Analyser\VariableTypeHolder::createYes($type);

			return new self(
				$scope->broker,
				$scope->printer,
				$scope->typeSpecifier,
				$scope->getFile(),
				$scope->getAnalysedContextFile(),
				$scope->isDeclareStrictTypes(),
				$scope->isInClass() ? $scope->getClassReflection() : null,
				$scope->getFunction(),
				$scope->getNamespace(),
				$variableTypes,
				$scope->moreSpecificTypes,
				$scope->inClosureBindScopeClass,
				$scope->getAnonymousFunctionReturnType(),
				$scope->getInFunctionCall(),
				$scope->isNegated(),
				$scope->inFirstLevelStatement
			);
		}

		return $scope;
	}

	public function unspecifyExpressionType(\PhpParser\Node\Expr $expr): self
	{
		$exprString = $this->printer->prettyPrintExpr($expr);
		$moreSpecificTypes = $this->moreSpecificTypes;
		if (isset($moreSpecificTypes[$exprString]) && !$moreSpecificTypes[$exprString] instanceof \PHPStan\Type\MixedType) {
			unset($moreSpecificTypes[$exprString]);
			return new self(
				$this->broker,
				$this->printer,
				$this->typeSpecifier,
				$this->getFile(),
				$this->getAnalysedContextFile(),
				$this->isDeclareStrictTypes(),
				$this->isInClass() ? $this->getClassReflection() : null,
				$this->getFunction(),
				$this->getNamespace(),
				$this->getVariableTypes(),
				$moreSpecificTypes,
				$this->inClosureBindScopeClass,
				$this->getAnonymousFunctionReturnType(),
				$this->getInFunctionCall(),
				$this->isNegated(),
				$this->inFirstLevelStatement
			);
		}

		return $this;
	}

	public function removeTypeFromExpression(\PhpParser\Node\Expr $expr, \PHPStan\Type\Type $type): self
	{
		return $this->specifyExpressionType(
			$expr,
			\PHPStan\Type\TypeCombinator::remove($this->getType($expr), $type)
		);
	}

	public function filterByTruthyValue(\PhpParser\Node\Expr $expr): self
	{
		$specifiedTypes = $this->typeSpecifier->specifyTypesInCondition($this, $expr, \PHPStan\Analyser\TypeSpecifier::CONTEXT_TRUTHY);
		return $this->filterBySpecifiedTypes($specifiedTypes);
	}

	public function filterByFalseyValue(\PhpParser\Node\Expr $expr): self
	{
		$specifiedTypes = $this->typeSpecifier->specifyTypesInCondition($this, $expr, \PHPStan\Analyser\TypeSpecifier::CONTEXT_FALSEY);
		return $this->filterBySpecifiedTypes($specifiedTypes);
	}

	private function filterBySpecifiedTypes(\PHPStan\Analyser\SpecifiedTypes $specifiedTypes): self
	{
		$scope = $this;
		foreach ($specifiedTypes->getSureTypes() as list($expr, $type)) {
			$type = \PHPStan\Type\TypeCombinator::intersect($type, $this->getType($expr));
			$scope = $scope->specifyExpressionType($expr, $type);
		}
		foreach ($specifiedTypes->getSureNotTypes() as list($expr, $type)) {
			$scope = $scope->removeTypeFromExpression($expr, $type);
		}
		return $scope;
	}

	public function specifyFetchedPropertyFromIsset(\PhpParser\Node\Expr\PropertyFetch $expr): self
	{
		$exprString = $this->printer->prettyPrintExpr($expr);

		return $this->addMoreSpecificTypes([
			$exprString => new \PHPStan\Type\MixedType(),
		]);
	}

	public function specifyFetchedStaticPropertyFromIsset(\PhpParser\Node\Expr\StaticPropertyFetch $expr): self
	{
		$exprString = $this->printer->prettyPrintExpr($expr);

		return $this->addMoreSpecificTypes([
			$exprString => new \PHPStan\Type\MixedType(),
		]);
	}

	public function enterNegation(): self
	{
		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			$this->isDeclareStrictTypes(),
			$this->isInClass() ? $this->getClassReflection() : null,
			$this->getFunction(),
			$this->getNamespace(),
			$this->getVariableTypes(),
			$this->moreSpecificTypes,
			$this->inClosureBindScopeClass,
			$this->getAnonymousFunctionReturnType(),
			$this->getInFunctionCall(),
			!$this->isNegated(),
			$this->inFirstLevelStatement
		);
	}

	public function enterFirstLevelStatements(): self
	{
		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			$this->isDeclareStrictTypes(),
			$this->isInClass() ? $this->getClassReflection() : null,
			$this->getFunction(),
			$this->getNamespace(),
			$this->getVariableTypes(),
			$this->moreSpecificTypes,
			$this->inClosureBindScopeClass,
			$this->getAnonymousFunctionReturnType(),
			$this->getInFunctionCall(),
			$this->isNegated(),
			true,
			$this->currentlyAssignedExpressions
		);
	}

	public function exitFirstLevelStatements(): self
	{
		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			$this->isDeclareStrictTypes(),
			$this->isInClass() ? $this->getClassReflection() : null,
			$this->getFunction(),
			$this->getNamespace(),
			$this->getVariableTypes(),
			$this->moreSpecificTypes,
			$this->inClosureBindScopeClass,
			$this->getAnonymousFunctionReturnType(),
			$this->getInFunctionCall(),
			$this->isNegated(),
			false,
			$this->currentlyAssignedExpressions
		);
	}

	public function isInFirstLevelStatement(): bool
	{
		return $this->inFirstLevelStatement;
	}

	public function isNegated(): bool
	{
		return $this->negated;
	}

	private function addMoreSpecificTypes(array $types): self
	{
		$moreSpecificTypes = $this->moreSpecificTypes;
		foreach ($types as $exprString => $type) {
			$moreSpecificTypes[$exprString] = $type;
		}

		return new self(
			$this->broker,
			$this->printer,
			$this->typeSpecifier,
			$this->getFile(),
			$this->getAnalysedContextFile(),
			$this->isDeclareStrictTypes(),
			$this->isInClass() ? $this->getClassReflection() : null,
			$this->getFunction(),
			$this->getNamespace(),
			$this->getVariableTypes(),
			$moreSpecificTypes,
			$this->inClosureBindScopeClass,
			$this->getAnonymousFunctionReturnType(),
			$this->getInFunctionCall(),
			$this->isNegated(),
			$this->inFirstLevelStatement
		);
	}

	public function canAccessProperty(\PHPStan\Reflection\PropertyReflection $propertyReflection): bool
	{
		return $this->canAccessClassMember($propertyReflection);
	}

	public function canCallMethod(\PHPStan\Reflection\MethodReflection $methodReflection): bool
	{
		if ($this->canAccessClassMember($methodReflection)) {
			return true;
		}

		return $this->canAccessClassMember($methodReflection->getPrototype());
	}

	public function canAccessConstant(\PHPStan\Reflection\ClassConstantReflection $constantReflection): bool
	{
		return $this->canAccessClassMember($constantReflection);
	}

	private function canAccessClassMember(\PHPStan\Reflection\ClassMemberReflection $classMemberReflection): bool
	{
		if ($classMemberReflection->isPublic()) {
			return true;
		}

		if ($this->inClosureBindScopeClass !== null && $this->broker->hasClass($this->inClosureBindScopeClass)) {
			$currentClassReflection = $this->broker->getClass($this->inClosureBindScopeClass);
		} elseif ($this->isInClass()) {
			$currentClassReflection = $this->getClassReflection();
		} else {
			return false;
		}

		$classReflectionName = $classMemberReflection->getDeclaringClass()->getName();
		if ($classMemberReflection->isPrivate()) {
			return $currentClassReflection->getName() === $classReflectionName;
		}

		// protected

		if (
			$currentClassReflection->getName() === $classReflectionName
			|| $currentClassReflection->isSubclassOf($classReflectionName)
		) {
			return true;
		}

		return $classMemberReflection->getDeclaringClass()->isSubclassOf($currentClassReflection->getName());
	}

	/**
	 * @return string[]
	 */
	public function debug(): array
	{
		$descriptions = [];
		foreach ($this->getVariableTypes() as $name => $variableTypeHolder) {
			$key = sprintf('$%s (%s)', $name, $variableTypeHolder->getCertainty()->describe());
			$descriptions[$key] = $variableTypeHolder->getType()->describe();
		}
		foreach ($this->moreSpecificTypes as $exprString => $type) {
			$key = $exprString;
			if (isset($descriptions[$key])) {
				$key .= '-specified';
			}
			$descriptions[$key] = $type->describe();
		}

		return $descriptions;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Analyser;

use PHPStan\Type\TypeCombinator;

class SpecifiedTypes
{

	/**
	 * @var mixed[]
	 */
	private $sureTypes;

	/**
	 * @var mixed[]
	 */
	private $sureNotTypes;

	/**
	 * @param mixed[] $sureTypes
	 * @param mixed[] $sureNotTypes
	 */
	public function __construct(array $sureTypes = [], array $sureNotTypes = [])
	{
		$this->sureTypes = $sureTypes;
		$this->sureNotTypes = $sureNotTypes;
	}

	/**
	 * @return mixed[]
	 */
	public function getSureTypes(): array
	{
		return $this->sureTypes;
	}

	/**
	 * @return mixed[]
	 */
	public function getSureNotTypes(): array
	{
		return $this->sureNotTypes;
	}

	public function intersectWith(\PHPStan\Analyser\SpecifiedTypes $other): self
	{
		$sureTypeUnion = [];
		$sureNotTypeUnion = [];

		foreach ($this->sureTypes as $exprString => list($exprNode, $type)) {
			if (isset($other->sureTypes[$exprString])) {
				$sureTypeUnion[$exprString] = [
					$exprNode,
					\PHPStan\Type\TypeCombinator::union($type, $other->sureTypes[$exprString][1]),
				];
			}
		}

		foreach ($this->sureNotTypes as $exprString => list($exprNode, $type)) {
			if (isset($other->sureNotTypes[$exprString])) {
				$sureNotTypeUnion[$exprString] = [
					$exprNode,
					\PHPStan\Type\TypeCombinator::intersect($type, $other->sureNotTypes[$exprString][1]),
				];
			}
		}

		return new self($sureTypeUnion, $sureNotTypeUnion);
	}


	public function unionWith(\PHPStan\Analyser\SpecifiedTypes $other): self
	{
		$sureTypeUnion = $this->sureTypes + $other->sureTypes;
		$sureNotTypeUnion = $this->sureNotTypes + $other->sureNotTypes;

		foreach ($this->sureTypes as $exprString => list($exprNode, $type)) {
			if (isset($other->sureTypes[$exprString])) {
				$sureTypeUnion[$exprString] = [
					$exprNode,
					\PHPStan\Type\TypeCombinator::intersect($type, $other->sureTypes[$exprString][1]),
				];
			}
		}

		foreach ($this->sureNotTypes as $exprString => list($exprNode, $type)) {
			if (isset($other->sureNotTypes[$exprString])) {
				$sureNotTypeUnion[$exprString] = [
					$exprNode,
					\PHPStan\Type\TypeCombinator::union($type, $other->sureNotTypes[$exprString][1]),
				];
			}
		}

		return new self($sureTypeUnion, $sureNotTypeUnion);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Analyser;

class StatementList
{

	/** @var \PHPStan\Analyser\Scope */
	private $scope;

	/** @var \PhpParser\Node[] */
	private $statements;

	/** @var bool */
	private $filterByTruthyValue;

	public function __construct(
		\PHPStan\Analyser\Scope $scope,
		array $statements,
		bool $filterByTruthyValue = false
	)
	{
		$this->scope = $scope;
		$this->statements = $statements;
		$this->filterByTruthyValue = $filterByTruthyValue;
	}

	public function getScope(): \PHPStan\Analyser\Scope
	{
		return $this->scope;
	}

	/**
	 * @return \PhpParser\Node[]
	 */
	public function getStatements(): array
	{
		return $this->statements;
	}

	public function shouldFilterByTruthyValue(): bool
	{
		return $this->filterByTruthyValue;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Analyser;
use PHPStan\TrinaryLogic;
use PHPStan\Type\ArrayType;
use PHPStan\Type\CallableType;
use PHPStan\Type\FalseBooleanType;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\IterableIterableType;
use PHPStan\Type\MixedType;
use PHPStan\Type\NullType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\ObjectWithoutClassType;
use PHPStan\Type\ResourceType;
use PHPStan\Type\StaticType;
use PHPStan\Type\StringType;
use PHPStan\Type\TrueBooleanType;
use PHPStan\Type\TrueOrFalseBooleanType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\UnionType;

class TypeSpecifier
{

	const CONTEXT_TRUE = 0b0001;
	const CONTEXT_TRUTHY_BUT_NOT_TRUE = 0b0010;
	const CONTEXT_TRUTHY = self::CONTEXT_TRUE | self::CONTEXT_TRUTHY_BUT_NOT_TRUE;
	const CONTEXT_FALSE = 0b0100;
	const CONTEXT_FALSEY_BUT_NOT_FALSE = 0b1000;
	const CONTEXT_FALSEY = self::CONTEXT_FALSE | self::CONTEXT_FALSEY_BUT_NOT_FALSE;

	/**
	 * @var \PhpParser\PrettyPrinter\Standard
	 */
	private $printer;

	public function __construct(\PhpParser\PrettyPrinter\Standard $printer)
	{
		$this->printer = $printer;
	}

	public function specifyTypesInCondition(\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Expr $expr, int $context = self::CONTEXT_TRUTHY): \PHPStan\Analyser\SpecifiedTypes
	{
		if ($expr instanceof \PhpParser\Node\Expr\Instanceof_) {
			if ($expr->class instanceof \PhpParser\Node\Name) {
				$className = (string) $expr->class;
				if ($className === 'self' && $scope->isInClass()) {
					$type = new \PHPStan\Type\ObjectType($scope->getClassReflection()->getName());
				} elseif ($className === 'static' && $scope->isInClass()) {
					$type = new \PHPStan\Type\StaticType($scope->getClassReflection()->getName());
				} else {
					$type = new \PHPStan\Type\ObjectType($className);
				}
				return $this->create($expr->expr, $type, $context);
			} elseif ($context & self::CONTEXT_TRUE) {
				return $this->create($expr->expr, new \PHPStan\Type\ObjectWithoutClassType(), $context);
			}
		} elseif ($expr instanceof \PhpParser\Node\Expr\BinaryOp\Identical) {
			$expressions = $this->findTypeExpressionsFromBinaryOperation($expr);
			if ($expressions !== null) {
				$constantName = strtolower((string) $expressions[1]->name);
				if ($constantName === 'false') {
					$types = $this->create($expressions[0], new \PHPStan\Type\FalseBooleanType(), $context);
					return $types->unionWith($this->specifyTypesInCondition(
						$scope,
						$expressions[0],
						($context & self::CONTEXT_TRUE) ? self::CONTEXT_FALSE : ~self::CONTEXT_FALSE
					));
				} elseif ($constantName === 'true') {
					$types = $this->create($expressions[0], new \PHPStan\Type\TrueBooleanType(), $context);
					return $types->unionWith($this->specifyTypesInCondition(
						$scope,
						$expressions[0],
						($context & self::CONTEXT_TRUE) ? self::CONTEXT_TRUE : ~self::CONTEXT_TRUE
					));
				} elseif ($constantName === 'null') {
					return $this->create($expressions[0], new \PHPStan\Type\NullType(), $context);
				}
			} elseif ($context & self::CONTEXT_TRUE) {
				$type = \PHPStan\Type\TypeCombinator::intersect($scope->getType($expr->right), $scope->getType($expr->left));
				$leftTypes = $this->create($expr->left, $type, $context);
				$rightTypes = $this->create($expr->right, $type, $context);
				return $leftTypes->unionWith($rightTypes);
			}
		} elseif ($expr instanceof \PhpParser\Node\Expr\BinaryOp\NotIdentical) {
			return $this->specifyTypesInCondition(
				$scope,
				new \PhpParser\Node\Expr\BooleanNot(new \PhpParser\Node\Expr\BinaryOp\Identical($expr->left, $expr->right)),
				$context
			);
		} elseif ($expr instanceof \PhpParser\Node\Expr\BinaryOp\Equal) {
			$expressions = $this->findTypeExpressionsFromBinaryOperation($expr);
			if ($expressions !== null) {
				$constantName = strtolower((string) $expressions[1]->name);
				if ($constantName === 'false') {
					return $this->specifyTypesInCondition(
						$scope,
						$expressions[0],
						($context & self::CONTEXT_TRUE) ? self::CONTEXT_FALSEY : ~self::CONTEXT_FALSEY
					);
				} elseif ($constantName === 'true') {
					return $this->specifyTypesInCondition(
						$scope,
						$expressions[0],
						($context & self::CONTEXT_TRUE) ? self::CONTEXT_TRUTHY : ~self::CONTEXT_TRUTHY
					);
				}
			}
		} elseif ($expr instanceof \PhpParser\Node\Expr\BinaryOp\NotEqual) {
			return $this->specifyTypesInCondition(
				$scope,
				new \PhpParser\Node\Expr\BooleanNot(new \PhpParser\Node\Expr\BinaryOp\Equal($expr->left, $expr->right)),
				$context
			);
		} elseif (
			$expr instanceof \PhpParser\Node\Expr\FuncCall
			&& $expr->name instanceof \PhpParser\Node\Name
			&& isset($expr->args[0])
		) {
			$functionName = strtolower((string) $expr->name);
			$innerExpr = $expr->args[0]->value;
			switch ($functionName) {
				case 'is_int':
				case 'is_integer':
				case 'is_long':
					return $this->create($innerExpr, new \PHPStan\Type\IntegerType(), $context);
				case 'is_float':
				case 'is_double':
				case 'is_real':
					return $this->create($innerExpr, new \PHPStan\Type\FloatType(), $context);
				case 'is_null':
					return $this->create($innerExpr, new \PHPStan\Type\NullType(), $context);
				case 'is_array':
					return $this->create($innerExpr, new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType(), false, \PHPStan\TrinaryLogic::createMaybe()), $context);
				case 'is_bool':
					return $this->create($innerExpr, new \PHPStan\Type\TrueOrFalseBooleanType(), $context);
				case 'is_callable':
					return $this->create($innerExpr, new \PHPStan\Type\CallableType(), $context);
				case 'is_resource':
					return $this->create($innerExpr, new \PHPStan\Type\ResourceType(), $context);
				case 'is_iterable':
					return $this->create($innerExpr, new \PHPStan\Type\IterableIterableType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType()), $context);
				case 'is_string':
					return $this->create($innerExpr, new \PHPStan\Type\StringType(), $context);
				case 'is_object':
					return $this->create($innerExpr, new \PHPStan\Type\ObjectWithoutClassType(), $context);
				case 'is_numeric':
					return $this->create($innerExpr, new \PHPStan\Type\UnionType([
						new \PHPStan\Type\StringType(),
						new \PHPStan\Type\IntegerType(),
						new \PHPStan\Type\FloatType(),
					]), $context);
				case 'is_a':
					if (isset($expr->args[1])) {
						$classNameArgExpr = $expr->args[1]->value;
						if ($classNameArgExpr instanceof \PhpParser\Node\Scalar\String_) {
							$objectType = new \PHPStan\Type\ObjectType($classNameArgExpr->value);
							$types = $this->create($innerExpr, $objectType, $context);
						} elseif (
							$classNameArgExpr instanceof \PhpParser\Node\Expr\ClassConstFetch
							&& $classNameArgExpr->class instanceof \PhpParser\Node\Name
							&& is_string($classNameArgExpr->name)
							&& strtolower($classNameArgExpr->name) === 'class'
						) {
							$className = $scope->resolveName($classNameArgExpr->class);
							if (strtolower($classNameArgExpr->class->toString()) === 'static') {
								$objectType = new \PHPStan\Type\StaticType($className);
							} else {
								$objectType = new \PHPStan\Type\ObjectType($className);
							}
							$types = $this->create($innerExpr, $objectType, $context);
						} elseif ($context & self::CONTEXT_TRUE) {
							$objectType = new \PHPStan\Type\ObjectWithoutClassType();
							$types = $this->create($innerExpr, $objectType, $context);
						} else {
							$types = new \PHPStan\Analyser\SpecifiedTypes();
						}

						if (isset($expr->args[2]) && ($context & self::CONTEXT_TRUE)) {
							if (!$scope->getType($expr->args[2]->value)->isSuperTypeOf(new \PHPStan\Type\TrueBooleanType())->no()) {
								$types = $types->intersectWith($this->create($innerExpr, new \PHPStan\Type\StringType(), $context));
							}
						}

						return $types;
					}
			}
		} elseif ($expr instanceof \PhpParser\Node\Expr\BinaryOp\BooleanAnd || $expr instanceof \PhpParser\Node\Expr\BinaryOp\LogicalAnd) {
			$leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context);
			$rightTypes = $this->specifyTypesInCondition($scope, $expr->right, $context);
			return ($context & self::CONTEXT_TRUE) ? $leftTypes->unionWith($rightTypes) : $leftTypes->intersectWith($rightTypes);
		} elseif ($expr instanceof \PhpParser\Node\Expr\BinaryOp\BooleanOr || $expr instanceof \PhpParser\Node\Expr\BinaryOp\LogicalOr) {
			$leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context);
			$rightTypes = $this->specifyTypesInCondition($scope, $expr->right, $context);
			return ($context & self::CONTEXT_TRUE) ? $leftTypes->intersectWith($rightTypes) : $leftTypes->unionWith($rightTypes);
		} elseif ($expr instanceof \PhpParser\Node\Expr\BooleanNot) {
			return $this->specifyTypesInCondition($scope, $expr->expr, ~$context);
		} elseif ($expr instanceof \PhpParser\Node\Expr\Assign) {
			return $this->specifyTypesInCondition($scope, $expr->var, $context);
		} elseif (
			$expr instanceof \PhpParser\Node\Expr\Isset_
			&& count($expr->vars) > 0
			&& $context & self::CONTEXT_TRUTHY
		) {
			$vars = [];
			foreach ($expr->vars as $var) {
				$vars[] = $var;

				while (
					$var instanceof \PhpParser\Node\Expr\ArrayDimFetch
					|| $var instanceof \PhpParser\Node\Expr\PropertyFetch
				) {
					$var = $var->var;
					$vars[] = $var;
				}

				while (
					$var instanceof \PhpParser\Node\Expr\StaticPropertyFetch
					&& $var->class instanceof \PhpParser\Node\Expr
				) {
					$var = $var->class;
					$vars[] = $var;
				}
			}

			$types = null;
			foreach ($vars as $var) {
				$type = $this->create($var, new \PHPStan\Type\NullType(), self::CONTEXT_FALSE);
				if ($types === null) {
					$types = $type;
				} else {
					$types = $types->unionWith($type);
				}
			}
			return $types;
		} elseif (($context & self::CONTEXT_TRUTHY) === 0) {
			$type = new \PHPStan\Type\ObjectWithoutClassType();
			return $this->create($expr, $type, self::CONTEXT_FALSE);
		} elseif (($context & self::CONTEXT_FALSEY) === 0) {
			$type = new \PHPStan\Type\UnionType([new \PHPStan\Type\NullType(), new \PHPStan\Type\FalseBooleanType()]);
			return $this->create($expr, $type, self::CONTEXT_FALSE);
		}

		return new \PHPStan\Analyser\SpecifiedTypes();
	}

	/**
	 * @param \PhpParser\Node\Expr\BinaryOp $binaryOperation
	 * @return array|null
	 */
	private function findTypeExpressionsFromBinaryOperation(\PhpParser\Node\Expr\BinaryOp $binaryOperation)
	{
		if ($binaryOperation->left instanceof \PhpParser\Node\Expr\ConstFetch) {
			return [$binaryOperation->right, $binaryOperation->left];
		} elseif ($binaryOperation->right instanceof \PhpParser\Node\Expr\ConstFetch) {
			return [$binaryOperation->left, $binaryOperation->right];
		}

		return null;
	}

	private function create(\PhpParser\Node\Expr $expr, \PHPStan\Type\Type $type, int $context): \PHPStan\Analyser\SpecifiedTypes
	{
		$sureTypes = [];
		$sureNotTypes = [];

		if ($expr instanceof \PhpParser\Node\Expr\Variable
			|| $expr instanceof \PhpParser\Node\Expr\FuncCall
			|| $expr instanceof \PhpParser\Node\Expr\MethodCall
			|| $expr instanceof \PhpParser\Node\Expr\StaticCall
			|| $expr instanceof \PhpParser\Node\Expr\PropertyFetch
			|| $expr instanceof \PhpParser\Node\Expr\StaticPropertyFetch
			|| $expr instanceof \PhpParser\Node\Expr\ArrayDimFetch
		) {
			$exprString = $this->printer->prettyPrintExpr($expr);
			if ($context & self::CONTEXT_FALSE) {
				$sureNotTypes[$exprString] = [$expr, $type];
			} elseif ($context & self::CONTEXT_TRUE) {
				$sureTypes[$exprString] = [$expr, $type];
			}
		}

		return new \PHPStan\Analyser\SpecifiedTypes($sureTypes, $sureNotTypes);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Analyser;

class UndefinedVariableException extends \PHPStan\AnalysedCodeException
{

	/** @var \PHPStan\Analyser\Scope */
	private $scope;

	/** @var string */
	private $variableName;

	public function __construct(\PHPStan\Analyser\Scope $scope, string $variableName)
	{
		parent::__construct(sprintf('Undefined variable: $%s', $variableName));
		$this->scope = $scope;
		$this->variableName = $variableName;
	}

	public function getScope(): \PHPStan\Analyser\Scope
	{
		return $this->scope;
	}

	public function getVariableName(): string
	{
		return $this->variableName;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Analyser;

use PHPStan\TrinaryLogic;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;

class VariableTypeHolder
{

	/**
	 * @var \PHPStan\Type\Type
	 */
	private $type;

	/**
	 * @var \PHPStan\TrinaryLogic
	 */
	private $certainty;

	public function __construct(\PHPStan\Type\Type $type, \PHPStan\TrinaryLogic $certainty)
	{
		if ($certainty->no()) {
			throw new \PHPStan\ShouldNotHappenException();
		}
		$this->type = $type;
		$this->certainty = $certainty;
	}

	public static function createYes(\PHPStan\Type\Type $type): self
	{
		return new self($type, \PHPStan\TrinaryLogic::createYes());
	}

	public static function createMaybe(\PHPStan\Type\Type $type): self
	{
		return new self($type, \PHPStan\TrinaryLogic::createMaybe());
	}

	public function and(self $other): self
	{
		return new self(
			\PHPStan\Type\TypeCombinator::union($this->getType(), $other->getType()),
			$this->getCertainty()->and($other->getCertainty())
		);
	}

	public function addMaybe(): self
	{
		return new self(
			$this->getType(),
			$this->getCertainty()->addMaybe()
		);
	}

	public function getType(): \PHPStan\Type\Type
	{
		return $this->type;
	}

	public function getCertainty(): \PHPStan\TrinaryLogic
	{
		return $this->certainty;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Broker;

use PHPStan\Analyser\Scope;
use PHPStan\PhpDoc\Tag\ParamTag;
use PHPStan\Reflection\BrokerAwareExtension;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\FunctionReflectionFactory;
use PHPStan\Type\FileTypeMapper;
use PHPStan\Type\Type;

class Broker
{

	/** @var \PHPStan\Reflection\PropertiesClassReflectionExtension[] */
	private $propertiesClassReflectionExtensions;

	/** @var \PHPStan\Reflection\MethodsClassReflectionExtension[] */
	private $methodsClassReflectionExtensions;

	/** @var \PHPStan\Type\DynamicMethodReturnTypeExtension[] */
	private $dynamicMethodReturnTypeExtensions = [];

	/** @var \PHPStan\Type\DynamicStaticMethodReturnTypeExtension[] */
	private $dynamicStaticMethodReturnTypeExtensions = [];

	/** @var \PHPStan\Type\DynamicMethodReturnTypeExtension[] */
	private $dynamicMethodReturnTypeExtensionsByClass;

	/** @var \PHPStan\Type\DynamicStaticMethodReturnTypeExtension[] */
	private $dynamicStaticMethodReturnTypeExtensionsByClass;

	/** @var \PHPStan\Type\DynamicFunctionReturnTypeExtension[] */
	private $dynamicFunctionReturnTypeExtensions = [];

	/** @var \PHPStan\Reflection\ClassReflection[] */
	private $classReflections = [];

	/** @var \PHPStan\Reflection\FunctionReflectionFactory */
	private $functionReflectionFactory;

	/** @var \PHPStan\Type\FileTypeMapper */
	private $fileTypeMapper;

	/** @var \PHPStan\Reflection\FunctionReflection[] */
	private $functionReflections = [];

	/** @var null|self */
	private static $instance;

	/** @var bool[] */
	private $hasClassCache;

	/**
	 * @param \PHPStan\Reflection\PropertiesClassReflectionExtension[] $propertiesClassReflectionExtensions
	 * @param \PHPStan\Reflection\MethodsClassReflectionExtension[] $methodsClassReflectionExtensions
	 * @param \PHPStan\Type\DynamicMethodReturnTypeExtension[] $dynamicMethodReturnTypeExtensions
	 * @param \PHPStan\Type\DynamicStaticMethodReturnTypeExtension[] $dynamicStaticMethodReturnTypeExtensions
	 * @param \PHPStan\Type\DynamicFunctionReturnTypeExtension[] $dynamicFunctionReturnTypeExtensions
	 * @param \PHPStan\Reflection\FunctionReflectionFactory $functionReflectionFactory
	 * @param \PHPStan\Type\FileTypeMapper $fileTypeMapper
	 */
	public function __construct(
		array $propertiesClassReflectionExtensions,
		array $methodsClassReflectionExtensions,
		array $dynamicMethodReturnTypeExtensions,
		array $dynamicStaticMethodReturnTypeExtensions,
		array $dynamicFunctionReturnTypeExtensions,
		\PHPStan\Reflection\FunctionReflectionFactory $functionReflectionFactory,
		\PHPStan\Type\FileTypeMapper $fileTypeMapper
	)
	{
		$this->propertiesClassReflectionExtensions = $propertiesClassReflectionExtensions;
		$this->methodsClassReflectionExtensions = $methodsClassReflectionExtensions;
		foreach (array_merge($propertiesClassReflectionExtensions, $methodsClassReflectionExtensions, $dynamicMethodReturnTypeExtensions, $dynamicStaticMethodReturnTypeExtensions, $dynamicFunctionReturnTypeExtensions) as $extension) {
			if ($extension instanceof \PHPStan\Reflection\BrokerAwareExtension) {
				$extension->setBroker($this);
			}
		}

		$this->dynamicMethodReturnTypeExtensions = $dynamicMethodReturnTypeExtensions;
		$this->dynamicStaticMethodReturnTypeExtensions = $dynamicStaticMethodReturnTypeExtensions;

		foreach ($dynamicFunctionReturnTypeExtensions as $functionReturnTypeExtension) {
			$this->dynamicFunctionReturnTypeExtensions[] = $functionReturnTypeExtension;
		}

		$this->functionReflectionFactory = $functionReflectionFactory;
		$this->fileTypeMapper = $fileTypeMapper;

		self::$instance = $this;
	}

	public static function getInstance(): self
	{
		if (self::$instance === null) {
			throw new \PHPStan\ShouldNotHappenException();
		}
		return self::$instance;
	}

	/**
	 * @param string $className
	 * @return \PHPStan\Type\DynamicMethodReturnTypeExtension[]
	 */
	public function getDynamicMethodReturnTypeExtensionsForClass(string $className): array
	{
		if ($this->dynamicMethodReturnTypeExtensionsByClass === null) {
			$byClass = [];
			foreach ($this->dynamicMethodReturnTypeExtensions as $extension) {
				$byClass[$extension->getClass()][] = $extension;
			}

			$this->dynamicMethodReturnTypeExtensionsByClass = $byClass;
		}
		return $this->getDynamicExtensionsForType($this->dynamicMethodReturnTypeExtensionsByClass, $className);
	}

	/**
	 * @param string $className
	 * @return \PHPStan\Type\DynamicStaticMethodReturnTypeExtension[]
	 */
	public function getDynamicStaticMethodReturnTypeExtensionsForClass(string $className): array
	{
		if ($this->dynamicStaticMethodReturnTypeExtensionsByClass === null) {
			$byClass = [];
			foreach ($this->dynamicStaticMethodReturnTypeExtensions as $extension) {
				$byClass[$extension->getClass()][] = $extension;
			}

			$this->dynamicStaticMethodReturnTypeExtensionsByClass = $byClass;
		}
		return $this->getDynamicExtensionsForType($this->dynamicStaticMethodReturnTypeExtensionsByClass, $className);
	}

	/**
	 * @return \PHPStan\Type\DynamicFunctionReturnTypeExtension[]
	 */
	public function getDynamicFunctionReturnTypeExtensions(): array
	{
		return $this->dynamicFunctionReturnTypeExtensions;
	}

	/**
	 * @param \PHPStan\Type\DynamicMethodReturnTypeExtension[]|\PHPStan\Type\DynamicStaticMethodReturnTypeExtension[] $extensions
	 * @param string $className
	 * @return mixed[]
	 */
	private function getDynamicExtensionsForType(array $extensions, string $className): array
	{
		$extensionsForClass = [];
		$class = $this->getClass($className);
		foreach (array_merge([$className], $class->getParentClassesNames(), $class->getNativeReflection()->getInterfaceNames()) as $extensionClassName) {
			if (!isset($extensions[$extensionClassName])) {
				continue;
			}

			$extensionsForClass = array_merge($extensionsForClass, $extensions[$extensionClassName]);
		}

		return $extensionsForClass;
	}

	public function getClass(string $className): \PHPStan\Reflection\ClassReflection
	{
		if (!$this->hasClass($className)) {
			throw new \PHPStan\Broker\ClassNotFoundException($className);
		}

		if (!isset($this->classReflections[$className])) {
			$reflectionClass = new \ReflectionClass($className);
			$classReflection = $this->getClassFromReflection(
				$reflectionClass,
				$reflectionClass->getName(),
				$reflectionClass->isAnonymous()
			);
			$this->classReflections[$className] = $classReflection;
			if ($className !== $reflectionClass->getName()) {
				// class alias optimization
				$this->classReflections[$reflectionClass->getName()] = $classReflection;
			}
		}

		return $this->classReflections[$className];
	}

	public function getClassFromReflection(\ReflectionClass $reflectionClass, string $displayName, bool $anonymous): \PHPStan\Reflection\ClassReflection
	{
		$className = $reflectionClass->getName();
		if (!isset($this->classReflections[$className])) {
			$classReflection = new \PHPStan\Reflection\ClassReflection(
				$this,
				$this->propertiesClassReflectionExtensions,
				$this->methodsClassReflectionExtensions,
				$displayName,
				$reflectionClass,
				$anonymous
			);
			$this->classReflections[$className] = $classReflection;
		}

		return $this->classReflections[$className];
	}

	public function hasClass(string $className): bool
	{
		if (isset($this->hasClassCache[$className])) {
			return $this->hasClassCache[$className];
		}

		spl_autoload_register($autoloader = function (string $autoloadedClassName) use ($className) {
			if ($autoloadedClassName !== $className && !$this->isExistsCheckCall()) {
				throw new \PHPStan\Broker\ClassAutoloadingException($autoloadedClassName);
			}
		});

		try {
			return $this->hasClassCache[$className] = class_exists($className) || interface_exists($className) || trait_exists($className);
		} catch (\PHPStan\Broker\ClassAutoloadingException $e) {
			throw $e;
		} catch (\Throwable $t) {
			throw new \PHPStan\Broker\ClassAutoloadingException(
				$className,
				$t
			);
		} finally {
			spl_autoload_unregister($autoloader);
		}
	}

	public function getFunction(\PhpParser\Node\Name $nameNode, \PHPStan\Analyser\Scope $scope = null): \PHPStan\Reflection\FunctionReflection
	{
		$functionName = $this->resolveFunctionName($nameNode, $scope);
		if ($functionName === null) {
			throw new \PHPStan\Broker\FunctionNotFoundException((string) $nameNode);
		}

		$lowerCasedFunctionName = strtolower($functionName);
		if (!isset($this->functionReflections[$lowerCasedFunctionName])) {
			$reflectionFunction = new \ReflectionFunction($lowerCasedFunctionName);
			$phpDocParameterTags = [];
			$phpDocReturnTag = null;
			if ($reflectionFunction->getFileName() !== false && $reflectionFunction->getDocComment() !== false) {
				$fileName = $reflectionFunction->getFileName();
				$docComment = $reflectionFunction->getDocComment();
				$resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($fileName, null, $docComment);
				$phpDocParameterTags = $resolvedPhpDoc->getParamTags();
				$phpDocReturnTag = $resolvedPhpDoc->getReturnTag();
			}
			$this->functionReflections[$lowerCasedFunctionName] = $this->functionReflectionFactory->create(
				$reflectionFunction,
				array_map(function (\PHPStan\PhpDoc\Tag\ParamTag $paramTag): \PHPStan\Type\Type {
					return $paramTag->getType();
				}, $phpDocParameterTags),
				$phpDocReturnTag !== null ? $phpDocReturnTag->getType() : null
			);
		}

		return $this->functionReflections[$lowerCasedFunctionName];
	}

	public function hasFunction(\PhpParser\Node\Name $nameNode, \PHPStan\Analyser\Scope $scope = null): bool
	{
		return $this->resolveFunctionName($nameNode, $scope) !== null;
	}

	/**
	 * @param \PhpParser\Node\Name $nameNode
	 * @param \PHPStan\Analyser\Scope|null $scope
	 * @return string|null
	 */
	public function resolveFunctionName(\PhpParser\Node\Name $nameNode, \PHPStan\Analyser\Scope $scope = null)
	{
		return $this->resolveName($nameNode, function (string $name): bool {
			return function_exists($name);
		}, $scope);
	}

	public function hasConstant(\PhpParser\Node\Name $nameNode, \PHPStan\Analyser\Scope $scope = null): bool
	{
		return $this->resolveConstantName($nameNode, $scope) !== null;
	}

	/**
	 * @param \PhpParser\Node\Name $nameNode
	 * @param \PHPStan\Analyser\Scope|null $scope
	 * @return string|null
	 */
	public function resolveConstantName(\PhpParser\Node\Name $nameNode, \PHPStan\Analyser\Scope $scope = null)
	{
		return $this->resolveName($nameNode, function (string $name): bool {
			return defined($name);
		}, $scope);
	}

	/**
	 * @param \PhpParser\Node\Name $nameNode
	 * @param \Closure $existsCallback
	 * @param \PHPStan\Analyser\Scope|null $scope
	 * @return string|null
	 */
	private function resolveName(
		\PhpParser\Node\Name $nameNode,
		\Closure $existsCallback,
		\PHPStan\Analyser\Scope $scope = null
	)
	{
		$name = (string) $nameNode;
		if ($scope !== null && $scope->getNamespace() !== null && !$nameNode->isFullyQualified()) {
			$namespacedName = sprintf('%s\\%s', $scope->getNamespace(), $name);
			if ($existsCallback($namespacedName)) {
				return $namespacedName;
			}
		}

		if ($existsCallback($name)) {
			return $name;
		}

		return null;
	}

	private function isExistsCheckCall(): bool
	{
		$debugBacktrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
		$existsCallTypes = [
			'class_exists' => true,
			'interface_exists' => true,
			'trait_exists' => true,
		];

		foreach ($debugBacktrace as $traceStep) {
			if (
				isset($traceStep['function'])
				&& isset($existsCallTypes[$traceStep['function']])
				// We must ignore the self::hasClass calls
				&& (!isset($traceStep['file']) || $traceStep['file'] !== __FILE__)
			) {
				return true;
			}
		}

		return false;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Broker;

use PHPStan\Reflection\Annotations\AnnotationsMethodsClassReflectionExtension;
use PHPStan\Reflection\Annotations\AnnotationsPropertiesClassReflectionExtension;
use PHPStan\Reflection\FunctionReflectionFactory;
use PHPStan\Reflection\Php\PhpClassReflectionExtension;
use PHPStan\Reflection\PhpDefect\PhpDefectClassReflectionExtension;
use PHPStan\Type\FileTypeMapper;

class BrokerFactory
{

	const PROPERTIES_CLASS_REFLECTION_EXTENSION_TAG = 'phpstan.broker.propertiesClassReflectionExtension';
	const METHODS_CLASS_REFLECTION_EXTENSION_TAG = 'phpstan.broker.methodsClassReflectionExtension';
	const DYNAMIC_METHOD_RETURN_TYPE_EXTENSION_TAG = 'phpstan.broker.dynamicMethodReturnTypeExtension';
	const DYNAMIC_STATIC_METHOD_RETURN_TYPE_EXTENSION_TAG = 'phpstan.broker.dynamicStaticMethodReturnTypeExtension';
	const DYNAMIC_FUNCTION_RETURN_TYPE_EXTENSION_TAG = 'phpstan.broker.dynamicFunctionReturnTypeExtension';

	/** @var \Nette\DI\Container */
	private $container;

	public function __construct(\PHPStanVendor\Nette\DI\Container $container)
	{
		$this->container = $container;
	}

	public function create(): \PHPStan\Broker\Broker
	{
		$tagToService = function (array $tags) {
			return array_map(function (string $serviceName) {
				return $this->container->getService($serviceName);
			}, array_keys($tags));
		};

		$phpClassReflectionExtension = $this->container->getByType(\PHPStan\Reflection\Php\PhpClassReflectionExtension::class);
		$annotationsMethodsClassReflectionExtension = $this->container->getByType(\PHPStan\Reflection\Annotations\AnnotationsMethodsClassReflectionExtension::class);
		$annotationsPropertiesClassReflectionExtension = $this->container->getByType(\PHPStan\Reflection\Annotations\AnnotationsPropertiesClassReflectionExtension::class);
		$phpDefectClassReflectionExtension = $this->container->getByType(\PHPStan\Reflection\PhpDefect\PhpDefectClassReflectionExtension::class);

		return new \PHPStan\Broker\Broker(
			array_merge([$phpClassReflectionExtension, $phpDefectClassReflectionExtension], $tagToService($this->container->findByTag(self::PROPERTIES_CLASS_REFLECTION_EXTENSION_TAG)), [$annotationsPropertiesClassReflectionExtension]),
			array_merge([$phpClassReflectionExtension], $tagToService($this->container->findByTag(self::METHODS_CLASS_REFLECTION_EXTENSION_TAG)), [$annotationsMethodsClassReflectionExtension]),
			$tagToService($this->container->findByTag(self::DYNAMIC_METHOD_RETURN_TYPE_EXTENSION_TAG)),
			$tagToService($this->container->findByTag(self::DYNAMIC_STATIC_METHOD_RETURN_TYPE_EXTENSION_TAG)),
			$tagToService($this->container->findByTag(self::DYNAMIC_FUNCTION_RETURN_TYPE_EXTENSION_TAG)),
			$this->container->getByType(\PHPStan\Reflection\FunctionReflectionFactory::class),
			$this->container->getByType(\PHPStan\Type\FileTypeMapper::class)
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Broker;

class ClassAutoloadingException extends \PHPStan\AnalysedCodeException
{

	/** @var string */
	private $className;

	public function __construct(
		string $functionName,
		\Throwable $previous = null
	)
	{
		if ($previous !== null) {
			parent::__construct(sprintf(
				'%s (%s) thrown while autoloading class %s.',
				get_class($previous),
				$previous->getMessage(),
				$functionName
			), 0, $previous);
		} else {
			parent::__construct(sprintf(
				'Class %s not found and could not be autoloaded.',
				$functionName
			), 0);
		}

		$this->className = $functionName;
	}

	public function getClassName(): string
	{
		return $this->className;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Broker;

class ClassNotFoundException extends \PHPStan\AnalysedCodeException
{

	/** @var string */
	private $className;

	public function __construct(string $functionName)
	{
		parent::__construct(sprintf('Class %s was not found while trying to analyse it - autoloading is probably not configured properly.', $functionName));
		$this->className = $functionName;
	}

	public function getClassName(): string
	{
		return $this->className;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Broker;

class FunctionNotFoundException extends \PHPStan\AnalysedCodeException
{

	/** @var string */
	private $functionName;

	public function __construct(string $functionName)
	{
		parent::__construct(sprintf('Function %s not found while trying to analyse it - autoloading is probably not configured properly.', $functionName));
		$this->functionName = $functionName;
	}

	public function getFunctionName(): string
	{
		return $this->functionName;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Cache;

class Cache
{

	/** @var \PHPStan\Cache\CacheStorage */
	private $storage;

	public function __construct(\PHPStan\Cache\CacheStorage $storage)
	{
		$this->storage = $storage;
	}

	/**
	 * @param string $key
	 * @return mixed|null
	 */
	public function load(string $key)
	{
		return $this->storage->load($key);
	}

	/**
	 * @param string $key
	 * @param mixed $data
	 * @return bool
	 */
	public function save(string $key, $data): bool
	{
		return $this->storage->save($key, $data);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Cache;

interface CacheStorage
{

	/**
	 * @param string $key
	 * @return mixed|null
	 */
	public function load(string $key);

	/**
	 * @param string $key
	 * @param mixed $data
	 * @return bool
	 */
	public function save(string $key, $data): bool;

}
<?php declare(strict_types = 1);

namespace PHPStan\Cache;

class FileCacheStorage implements \PHPStan\Cache\CacheStorage
{

	/** @var string */
	private $directory;

	public function __construct(string $directory)
	{
		$this->directory = $directory;

		if (@mkdir($this->directory) && !is_dir($this->directory)) {
			throw new \InvalidArgumentException(sprintf('Directory "%s" doesn\'t exist.', $this->directory));
		}
	}

	/**
	 * @param string $key
	 * @return mixed|null
	 */
	public function load(string $key)
	{
		return (function (string $key) {
			$filePath = $this->getFilePath($key);
			return is_file($filePath) ? require $this->getFilePath($key) : null;
		})($key);
	}

	/**
	 * @param string $key
	 * @param mixed $data
	 * @return bool
	 */
	public function save(string $key, $data): bool
	{
		$writtenBytes = @file_put_contents(
			$this->getFilePath($key),
			sprintf("<?php declare(strict_types = 1);\n\nreturn %s;", var_export($data, true))
		);
		return $writtenBytes !== false;
	}

	private function getFilePath(string $key): string
	{
		return sprintf('%s/%s.php', $this->directory, preg_replace('~[^-\\w]~', '_', $key));
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Cache;

class MemoryCacheStorage implements \PHPStan\Cache\CacheStorage
{

	/** @var mixed[] */
	private $storage = [];

	/**
	 * @param string $key
	 * @return mixed|null
	 */
	public function load(string $key)
	{
		return array_key_exists($key, $this->storage) ? $this->storage[$key] : null;
	}

	/**
	 * @param string $key
	 * @param mixed $data
	 * @return bool
	 */
	public function save(string $key, $data): bool
	{
		$this->storage[$key] = $data;
		return true;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Command;

use PHPStan\Analyser\Analyser;
use PHPStan\Analyser\Error;
use PHPStan\Command\ErrorFormatter\ErrorFormatter;
use PHPStan\File\FileExcluder;
use PHPStan\File\FileHelper;

class AnalyseApplication
{

	/**
	 * @var \PHPStan\Analyser\Analyser
	 */
	private $analyser;

	/**
	 * @var string
	 */
	private $memoryLimitFile;

	/**
	 * @var string[]
	 */
	private $fileExtensions;

	/** @var \PHPStan\File\FileHelper */
	private $fileHelper;

	/** @var \PHPStan\File\FileExcluder */
	private $fileExcluder;

	public function __construct(
		\PHPStan\Analyser\Analyser $analyser,
		string $memoryLimitFile,
		\PHPStan\File\FileHelper $fileHelper,
		array $fileExtensions,
		\PHPStan\File\FileExcluder $fileExcluder
	)
	{
		$this->analyser = $analyser;
		$this->memoryLimitFile = $memoryLimitFile;
		$this->fileExtensions = $fileExtensions;
		$this->fileHelper = $fileHelper;
		$this->fileExcluder = $fileExcluder;
	}

	/**
	 * @param string[] $paths
	 * @param \Symfony\Component\Console\Style\OutputStyle $style
	 * @param \PHPStan\Command\ErrorFormatter\ErrorFormatter $errorFormatter
	 * @param bool $defaultLevelUsed
	 * @param bool $debug
	 * @return int Error code.
	 */
	public function analyse(
		array $paths,
		\PHPStanVendor\Symfony\Component\Console\Style\OutputStyle $style,
		\PHPStan\Command\ErrorFormatter\ErrorFormatter $errorFormatter,
		bool $defaultLevelUsed,
		bool $debug
	): int
	{
		$errors = [];
		$files = [];

		$this->updateMemoryLimitFile();

		$paths = array_map(function (string $path): string {
			return $this->fileHelper->absolutizePath($path);
		}, $paths);

		$onlyFiles = true;
		foreach ($paths as $path) {
			if (!file_exists($path)) {
				$errors[] = new \PHPStan\Analyser\Error(sprintf('<error>Path %s does not exist</error>', $path), $path, null, false);
			} elseif (is_file($path)) {
				$files[] = $this->fileHelper->normalizePath($path);
			} else {
				$finder = new \PHPStanVendor\Symfony\Component\Finder\Finder();
				$finder->followLinks();
				foreach ($finder->files()->name('*.{' . implode(',', $this->fileExtensions) . '}')->in($path) as $fileInfo) {
					$files[] = $this->fileHelper->normalizePath($fileInfo->getPathname());
					$onlyFiles = false;
				}
			}
		}

		$files = array_filter($files, function (string $file): bool {
			return !$this->fileExcluder->isExcludedFromAnalysing($file);
		});

		$this->updateMemoryLimitFile();

		if (!$debug) {
			$progressStarted = false;
			$fileOrder = 0;
			$preFileCallback = null;
			$postFileCallback = function () use ($style, &$progressStarted, $files, &$fileOrder) {
				if (!$progressStarted) {
					$style->progressStart(count($files));
					$progressStarted = true;
				}
				$style->progressAdvance();
				if ($fileOrder % 100 === 0) {
					$this->updateMemoryLimitFile();
				}
				$fileOrder++;
			};
		} else {
			$preFileCallback = function (string $file) use ($style) {
				$style->writeln($file);
			};
			$postFileCallback = null;
		}

		$errors = array_merge($errors, $this->analyser->analyse(
			$files,
			$onlyFiles,
			$preFileCallback,
			$postFileCallback,
			$debug
		));

		if (isset($progressStarted) && $progressStarted) {
			$style->progressFinish();
		}

		$fileSpecificErrors = [];
		$notFileSpecificErrors = [];
		foreach ($errors as $error) {
			if (is_string($error)) {
				$notFileSpecificErrors[] = $error;
			} elseif ($error instanceof \PHPStan\Analyser\Error) {
				$fileSpecificErrors[] = $error;
			} else {
				throw new \PHPStan\ShouldNotHappenException();
			}
		}

		return $errorFormatter->formatErrors(
			new \PHPStan\Command\AnalysisResult(
				$fileSpecificErrors,
				$notFileSpecificErrors,
				$defaultLevelUsed,
				$this->fileHelper->normalizePath(dirname($paths[0]))
			),
			$style
		);
	}

	private function updateMemoryLimitFile()
	{
		$bytes = memory_get_peak_usage(true);
		$megabytes = ceil($bytes / 1024 / 1024);
		file_put_contents($this->memoryLimitFile, sprintf('%d MB', $megabytes));

		if (function_exists('pcntl_signal_dispatch')) {
			pcntl_signal_dispatch();
		}
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Command;
use PHPStan\Command\ErrorFormatter\ErrorFormatter;
use PHPStan\DependencyInjection\ContainerFactory;
use PHPStan\File\FileHelper;
use PHPStan\Type\TypeCombinator;

class AnalyseCommand extends \PHPStanVendor\Symfony\Component\Console\Command\Command
{

	const NAME = 'analyse';

	const OPTION_LEVEL = 'level';

	const DEFAULT_LEVEL = 0;

	protected function configure()
	{
		$this->setName(self::NAME)
			->setDescription('Analyses source code')
			->setDefinition([
				new \PHPStanVendor\Symfony\Component\Console\Input\InputArgument('paths', \PHPStanVendor\Symfony\Component\Console\Input\InputArgument::REQUIRED | \PHPStanVendor\Symfony\Component\Console\Input\InputArgument::IS_ARRAY, 'Paths with source code to run analysis on'),
				new \PHPStanVendor\Symfony\Component\Console\Input\InputOption('configuration', 'c', \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_REQUIRED, 'Path to project configuration file'),
				new \PHPStanVendor\Symfony\Component\Console\Input\InputOption(self::OPTION_LEVEL, 'l', \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_REQUIRED, 'Level of rule options - the higher the stricter'),
				new \PHPStanVendor\Symfony\Component\Console\Input\InputOption(\PHPStan\Command\ErrorsConsoleStyle::OPTION_NO_PROGRESS, null, \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'Do not show progress bar, only results'),
				new \PHPStanVendor\Symfony\Component\Console\Input\InputOption('debug', null, \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'Show debug information - which file is analysed, do not catch internal errors'),
				new \PHPStanVendor\Symfony\Component\Console\Input\InputOption('autoload-file', 'a', \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_REQUIRED, 'Project\'s additional autoload file path'),
				new \PHPStanVendor\Symfony\Component\Console\Input\InputOption('errorFormat', null, \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_REQUIRED, 'Format in which to print the result of the analysis', 'table'),
				new \PHPStanVendor\Symfony\Component\Console\Input\InputOption('memory-limit', null, \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_REQUIRED, 'Memory limit for analysis'),
			]);
	}


	public function getAliases(): array
	{
		return ['analyze'];
	}

	protected function execute(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output): int
	{
		$consoleStyle = new \PHPStan\Command\ErrorsConsoleStyle($input, $output);

		$memoryLimit = $input->getOption('memory-limit');
		if ($memoryLimit !== null) {
			if (!preg_match('#^-?\d+[kMG]?$#i', $memoryLimit)) {
				$consoleStyle->error(sprintf('Invalid memory limit format "%s".', $memoryLimit));
				return 1;
			}
			if (ini_set('memory_limit', $memoryLimit) === false) {
				$consoleStyle->error(sprintf('Memory limit "%s" cannot be set.', $memoryLimit));
				return 1;
			}
		}

		$currentWorkingDirectory = getcwd();
		$fileHelper = new \PHPStan\File\FileHelper($currentWorkingDirectory);

		$autoloadFile = $input->getOption('autoload-file');
		if ($autoloadFile !== null && is_file($autoloadFile)) {
			$autoloadFile = $fileHelper->normalizePath($autoloadFile);
			if (is_file($autoloadFile)) {
				require_once $autoloadFile;
			}
		}

		$projectConfigFile = $input->getOption('configuration');
		$levelOption = $input->getOption(self::OPTION_LEVEL);
		$defaultLevelUsed = false;
		if ($projectConfigFile === null && $levelOption === null) {
			$levelOption = self::DEFAULT_LEVEL;
			$defaultLevelUsed = true;
		}

		$containerFactory = new \PHPStan\DependencyInjection\ContainerFactory($currentWorkingDirectory);

		$additionalConfigFiles = [];
		if ($levelOption !== null) {
			$levelConfigFile = sprintf('%s/config.level%s.neon', $containerFactory->getConfigDirectory(), $levelOption);
			if (!is_file($levelConfigFile)) {
				$output->writeln(sprintf('Level config file %s was not found.', $levelConfigFile));
				return 1;
			}

			$additionalConfigFiles[] = $levelConfigFile;
		}

		if ($projectConfigFile !== null) {
			if (!is_file($projectConfigFile)) {
				$output->writeln(sprintf('Project config file at path %s does not exist.', $projectConfigFile));
				return 1;
			}

			$additionalConfigFiles[] = $projectConfigFile;

			$loader = new \PHPStanVendor\Nette\DI\Config\Loader();
			$projectConfig = $loader->load($projectConfigFile, null);
			if (isset($projectConfig['parameters']['tmpDir'])) {
				$tmpDir = \PHPStanVendor\Nette\DI\Helpers::expand($projectConfig['parameters']['tmpDir'], [
					'rootDir' => $containerFactory->getRootDirectory(),
					'currentWorkingDirectory' => $containerFactory->getCurrentWorkingDirectory(),
				]);
			}
		}

		if (!isset($tmpDir)) {
			$tmpDir = sys_get_temp_dir() . '/phpstan';
			if (!@mkdir($tmpDir, 0777, true) && !is_dir($tmpDir)) {
				$consoleStyle->error(sprintf('Cannot create a temp directory %s', $tmpDir));
				return 1;
			}
		}

		$container = $containerFactory->create($tmpDir, $additionalConfigFiles);
		$memoryLimitFile = $container->parameters['memoryLimitFile'];
		if (file_exists($memoryLimitFile)) {
			$consoleStyle->note(sprintf(
				"PHPStan crashed in the previous run probably because of excessive memory consumption.\nIt consumed around %s of memory.\n\nTo avoid this issue, allow to use more memory with the --memory-limit option.",
				file_get_contents($memoryLimitFile)
			));
			unlink($memoryLimitFile);
		}
		if (PHP_VERSION_ID >= 70100 && !property_exists(\PhpParser\Node\Stmt\Catch_::class, 'types')) {
			$consoleStyle->note(
				'You\'re running PHP >= 7.1, but you still have PHP-Parser version 2.x. This will lead to parse errors in case you use PHP 7.1 syntax like nullable parameters, iterable and void typehints, union exception types, or class constant visibility. Update to PHP-Parser 3.x to dismiss this message.'
			);
		}
		$errorFormat = $input->getOption('errorFormat');
		$errorFormatterServiceName = sprintf('errorFormatter.%s', $errorFormat);
		if (!$container->hasService($errorFormatterServiceName)) {
			$consoleStyle->error(sprintf(
				'Error formatter "%s" not found. Available error formatters are: %s',
				$errorFormat,
				implode(', ', array_map(function (string $name) {
					return substr($name, strlen('errorFormatter.'));
				}, $container->findByType(\PHPStan\Command\ErrorFormatter\ErrorFormatter::class)))
			));
			return 1;
		}
		/** @var ErrorFormatter $errorFormatter */
		$errorFormatter = $container->getService($errorFormatterServiceName);
		$this->setUpSignalHandler($consoleStyle, $memoryLimitFile);
		if (!isset($container->parameters['customRulesetUsed'])) {
			$output->writeln('');
			$output->writeln('<comment>No rules detected</comment>');
			$output->writeln('');
			$output->writeln('You have the following choices:');
			$output->writeln('');
			$output->writeln('* while running the analyse option, use the <info>--level</info> option to adjust your rule level - the higher the stricter');
			$output->writeln('');
			$output->writeln(sprintf('* create your own <info>custom ruleset</info> by selecting which rules you want to check by copying the service definitions from the built-in config level files in <options=bold>%s</>.', $fileHelper->normalizePath(__DIR__ . '/../../conf')));
			$output->writeln('  * in this case, don\'t forget to define parameter <options=bold>customRulesetUsed</> in your config file.');
			$output->writeln('');
			return 1;
		} elseif ($container->parameters['customRulesetUsed']) {
			$defaultLevelUsed = false;
		}

		foreach ($container->parameters['autoload_files'] as $autoloadFile) {
			require_once $fileHelper->normalizePath($autoloadFile);
		}

		if (count($container->parameters['autoload_directories']) > 0) {
			$robotLoader = new \PHPStanVendor\Nette\Loaders\RobotLoader();
			$robotLoader->acceptFiles = array_map(function (string $extension): string {
				return sprintf('*.%s', $extension);
			}, $container->parameters['fileExtensions']);

			$robotLoader->setTempDirectory($tmpDir);
			foreach ($container->parameters['autoload_directories'] as $directory) {
				$robotLoader->addDirectory($fileHelper->normalizePath($directory));
			}

			$robotLoader->register();
		}

		\PHPStan\Type\TypeCombinator::setUnionTypesEnabled($container->parameters['checkUnionTypes']);

		/** @var \PHPStan\Command\AnalyseApplication $application */
		$application = $container->getByType(\PHPStan\Command\AnalyseApplication::class);
		return $this->handleReturn(
			$application->analyse(
				$input->getArgument('paths'),
				$consoleStyle,
				$errorFormatter,
				$defaultLevelUsed,
				$input->getOption('debug')
			),
			$memoryLimitFile
		);
	}

	private function handleReturn(int $code, string $memoryLimitFile): int
	{
		unlink($memoryLimitFile);
		return $code;
	}

	private function setUpSignalHandler(\PHPStanVendor\Symfony\Component\Console\Style\StyleInterface $consoleStyle, string $memoryLimitFile)
	{
		if (function_exists('pcntl_signal')) {
			pcntl_signal(SIGINT, function () use ($consoleStyle, $memoryLimitFile) {
				if (file_exists($memoryLimitFile)) {
					unlink($memoryLimitFile);
				}
				$consoleStyle->newLine();
				exit(1);
			});
		}
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Command;

class AnalysisResult
{

	/**
	 * @var \PHPStan\Analyser\Error[]
	 */
	private $fileSpecificErrors;

	/**
	 * @var string[]
	 */
	private $notFileSpecificErrors;

	/**
	 * @var bool
	 */
	private $defaultLevelUsed;

	/**
	 * @var string
	 */
	private $currentDirectory;

	/**
	 * @param \PHPStan\Analyser\Error[] $fileSpecificErrors
	 * @param string[] $notFileSpecificErrors
	 * @param bool $defaultLevelUsed
	 * @param string $currentDirectory
	 */
	public function __construct(
		array $fileSpecificErrors,
		array $notFileSpecificErrors,
		bool $defaultLevelUsed,
		string $currentDirectory
	)
	{
		$this->fileSpecificErrors = $fileSpecificErrors;
		$this->notFileSpecificErrors = $notFileSpecificErrors;
		$this->defaultLevelUsed = $defaultLevelUsed;
		$this->currentDirectory = $currentDirectory;
	}

	public function hasErrors(): bool
	{
		return $this->getTotalErrorsCount() > 0;
	}

	public function getTotalErrorsCount(): int
	{
		return count($this->fileSpecificErrors) + count($this->notFileSpecificErrors);
	}

	/**
	 * @return \PHPStan\Analyser\Error[]
	 */
	public function getFileSpecificErrors(): array
	{
		return $this->fileSpecificErrors;
	}

	/**
	 * @return string[]
	 */
	public function getNotFileSpecificErrors(): array
	{
		return $this->notFileSpecificErrors;
	}

	public function isDefaultLevelUsed(): bool
	{
		return $this->defaultLevelUsed;
	}

	public function getCurrentDirectory(): string
	{
		return $this->currentDirectory;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Command\ErrorFormatter;

use PHPStan\Command\AnalysisResult;

class CheckstyleErrorFormatter implements \PHPStan\Command\ErrorFormatter\ErrorFormatter
{

	/**
	 * Formats the errors and outputs them to the console.
	 *
	 * @param \PHPStan\Command\AnalysisResult $analysisResult
	 * @param \Symfony\Component\Console\Style\OutputStyle $style
	 * @return int Error code.
	 */
	public function formatErrors(
		\PHPStan\Command\AnalysisResult $analysisResult,
		\PHPStanVendor\Symfony\Component\Console\Style\OutputStyle $style
	): int
	{
		$returnCode = 1;
		if (!$analysisResult->hasErrors()) {
			$returnCode = 0;
		}

		$out = '';

		/** @var \PHPStan\Analyser\Error $fileSpecificError */
		foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) {
			$out .= '<file name="' . $this->escape($fileSpecificError->getFile()) . '">' . "\n";
			$out .= ' ';
			$out .= '<error';
			$out .= ' line="' . $this->escape((string) $fileSpecificError->getLine()) . '"';
			$out .= ' column="1"';
			$out .= ' severity="error"';
			$out .= ' message="' . $this->escape($fileSpecificError->getMessage()) . '"';
			$out .= '/>' . "\n";
			$out .= '</file>' . "\n";
		}

		$style->write('<?xml version="1.0" encoding="UTF-8"?>' . "\n");
		$style->write('<checkstyle>' . "\n");
		if ($out !== '') {
			$style->write($out);
		}
		$style->write('</checkstyle>' . "\n");

		return $returnCode;
	}

	/**
	 * Escapes values for using in XML
	 *
	 * @param string $string
	 * @return string
	 */
	protected function escape(string $string): string
	{
		return htmlspecialchars($string, ENT_XML1 | ENT_COMPAT, 'UTF-8');
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Command\ErrorFormatter;

use PHPStan\Command\AnalysisResult;

interface ErrorFormatter
{

	/**
	 * Formats the errors and outputs them to the console.
	 *
	 * @param \PHPStan\Command\AnalysisResult $analysisResult
	 * @param \Symfony\Component\Console\Style\OutputStyle $style
	 * @return int Error code.
	 */
	public function formatErrors(
		\PHPStan\Command\AnalysisResult $analysisResult,
		\PHPStanVendor\Symfony\Component\Console\Style\OutputStyle $style
	): int;

}
<?php declare(strict_types = 1);

namespace PHPStan\Command\ErrorFormatter;

use PHPStan\Command\AnalysisResult;

class RawErrorFormatter implements \PHPStan\Command\ErrorFormatter\ErrorFormatter
{

	public function formatErrors(
		\PHPStan\Command\AnalysisResult $analysisResult,
		\PHPStanVendor\Symfony\Component\Console\Style\OutputStyle $style
	): int
	{
		if (!$analysisResult->hasErrors()) {
			return 0;
		}

		foreach ($analysisResult->getNotFileSpecificErrors() as $notFileSpecificError) {
			$style->writeln(sprintf('?:?:%s', $notFileSpecificError));
		}

		foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) {
			$style->writeln(
				sprintf(
					'%s:%d:%s',
					$fileSpecificError->getFile(),
					$fileSpecificError->getLine() !== null ? $fileSpecificError->getLine() : '?',
					$fileSpecificError->getMessage()
				)
			);
		}

		return 1;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Command\ErrorFormatter;

use PHPStan\Command\AnalyseCommand;
use PHPStan\Command\AnalysisResult;

class TableErrorFormatter implements \PHPStan\Command\ErrorFormatter\ErrorFormatter
{

	public function formatErrors(
		\PHPStan\Command\AnalysisResult $analysisResult,
		\PHPStanVendor\Symfony\Component\Console\Style\OutputStyle $style
	): int
	{
		if (!$analysisResult->hasErrors()) {
			$style->success('No errors');
			if ($analysisResult->isDefaultLevelUsed()) {
				$style->note(sprintf(
					'PHPStan is performing only the most basic checks. You can pass a higher rule level through the --%s option (the default and current level is %d) to analyse code more thoroughly.',
					\PHPStan\Command\AnalyseCommand::OPTION_LEVEL,
					\PHPStan\Command\AnalyseCommand::DEFAULT_LEVEL
				));
			}
			return 0;
		}

		$currentDirectory = $analysisResult->getCurrentDirectory();
		$cropFilename = function (string $filename) use ($currentDirectory): string {
			if ($currentDirectory !== '' && strpos($filename, $currentDirectory) === 0) {
				return substr($filename, strlen($currentDirectory) + 1);
			}

			return $filename;
		};

		/** @var \PHPStan\Analyser\Error[][] $fileErrors */
		$fileErrors = [];
		foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) {
			if (!isset($fileErrors[$fileSpecificError->getFile()])) {
				$fileErrors[$fileSpecificError->getFile()] = [];
			}

			$fileErrors[$fileSpecificError->getFile()][] = $fileSpecificError;
		}

		foreach ($fileErrors as $file => $errors) {
			$rows = [];
			foreach ($errors as $error) {
				$rows[] = [
					(string) $error->getLine(),
					$error->getMessage(),
				];
			}

			$style->table(['Line', $cropFilename($file)], $rows);
		}

		if (count($analysisResult->getNotFileSpecificErrors()) > 0) {
			$style->table(['Error'], array_map(function (string $error): array {
				return [$error];
			}, $analysisResult->getNotFileSpecificErrors()));
		}

		$style->error(sprintf($analysisResult->getTotalErrorsCount() === 1 ? 'Found %d error' : 'Found %d errors', $analysisResult->getTotalErrorsCount()));
		return 1;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Command;

class ErrorsConsoleStyle extends \PHPStanVendor\Symfony\Component\Console\Style\SymfonyStyle
{

	const OPTION_NO_PROGRESS = 'no-progress';

	/** @var bool */
	private $showProgress;

	/** @var \Symfony\Component\Console\Output\OutputInterface */
	private $output;

	/** @var \Symfony\Component\Console\Helper\ProgressBar */
	private $progressBar;

	public function __construct(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output)
	{
		parent::__construct($input, $output);
		$this->showProgress = $input->hasOption(self::OPTION_NO_PROGRESS) && !((bool) $input->getOption(self::OPTION_NO_PROGRESS));
		$this->output = $output;
	}

	public function table(array $headers, array $rows)
	{
		$terminalWidth = (new \PHPStanVendor\Symfony\Component\Console\Terminal())->getWidth();
		$maxHeaderWidth = strlen($headers[0]);
		foreach ($rows as $row) {
			$length = strlen($row[0]);
			if ($maxHeaderWidth === 0 || $length > $maxHeaderWidth) {
				$maxHeaderWidth = $length;
			}
		}

		$wrap = function ($rows) use ($terminalWidth, $maxHeaderWidth) {
			return array_map(function ($row) use ($terminalWidth, $maxHeaderWidth) {
				return array_map(function ($s) use ($terminalWidth, $maxHeaderWidth) {
					if ($terminalWidth > $maxHeaderWidth + 5) {
						return wordwrap(
							$s,
							$terminalWidth - $maxHeaderWidth - 5,
							"\n",
							true
						);
					}

					return $s;
				}, $row);
			}, $rows);
		};

		parent::table($headers, $wrap($rows));
	}

	/**
	 * @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint
	 * @param int $max
	 */
	public function createProgressBar($max = 0): \PHPStanVendor\Symfony\Component\Console\Helper\ProgressBar
	{
		$this->progressBar = parent::createProgressBar($max);
		return $this->progressBar;
	}

	/**
	 * @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint
	 * @param int $max
	 */
	public function progressStart($max = 0)
	{
		if (!$this->showProgress) {
			return;
		}
		parent::progressStart($max);
	}

	/**
	 * @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint
	 * @param int $step
	 */
	public function progressAdvance($step = 1)
	{
		if (!$this->showProgress) {
			return;
		}
		if ($this->output->isDecorated() && $step > 0) {
			$stepTime = (time() - $this->progressBar->getStartTime()) / $step;
			if ($stepTime > 0 && $stepTime < 1) {
				$this->progressBar->setRedrawFrequency(1 / $stepTime);
			} else {
				$this->progressBar->setRedrawFrequency(1);
			}
		}

		$this->progressBar->setProgress($this->progressBar->getProgress() + $step);
	}

	public function progressFinish()
	{
		if (!$this->showProgress) {
			return;
		}
		parent::progressFinish();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\DependencyInjection;
use PHPStan\File\FileHelper;

class ContainerFactory
{

	/**
	 * @var string
	 */
	private $currentWorkingDirectory;

	/**
	 * @var string
	 */
	private $rootDirectory;

	/**
	 * @var string
	 */
	private $configDirectory;

	public function __construct(string $currentWorkingDirectory)
	{
		$this->currentWorkingDirectory = $currentWorkingDirectory;
		$fileHelper = new \PHPStan\File\FileHelper($currentWorkingDirectory);
		$this->rootDirectory = $fileHelper->normalizePath(__DIR__ . '/../..');
		$this->configDirectory = $this->rootDirectory . '/conf';
	}

	public function create(
		string $tempDirectory,
		array $additionalConfigFiles
	): \PHPStanVendor\Nette\DI\Container
	{
		$configurator = new \PHPStanVendor\Nette\Configurator();
		$configurator->defaultExtensions = [
			'php' => \PHPStanVendor\Nette\DI\Extensions\PhpExtension::class,
			'extensions' => \PHPStanVendor\Nette\DI\Extensions\ExtensionsExtension::class,
		];
		$configurator->setDebugMode(true);
		$configurator->setTempDirectory($tempDirectory);
		$configurator->addParameters([
			'rootDir' => $this->rootDirectory,
			'currentWorkingDirectory' => $this->currentWorkingDirectory,
			'cliArgumentsVariablesRegistered' => ini_get('register_argc_argv') === '1',
			'tmpDir' => $tempDirectory,
		]);
		$configurator->addConfig($this->configDirectory . '/config.neon');
		foreach ($additionalConfigFiles as $additionalConfigFile) {
			$configurator->addConfig($additionalConfigFile);
		}

		return $configurator->createContainer();
	}

	public function getCurrentWorkingDirectory(): string
	{
		return $this->currentWorkingDirectory;
	}

	public function getRootDirectory(): string
	{
		return $this->rootDirectory;
	}

	public function getConfigDirectory(): string
	{
		return $this->configDirectory;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\File;

class FileExcluder
{

	/**
	 * Directories to exclude from analysing
	 *
	 * @var string[]
	 */
	private $analyseExcludes;

	public function __construct(
		\PHPStan\File\FileHelper $fileHelper,
		array $analyseExcludes
	)
	{
		$this->analyseExcludes = array_map(function (string $exclude) use ($fileHelper): string {
			$normalized = $fileHelper->normalizePath($exclude);

			if ($this->isFnmatchPattern($normalized)) {
				return $normalized;
			}

			return $fileHelper->absolutizePath($normalized);
		}, $analyseExcludes);
	}

	public function isExcludedFromAnalysing(string $file): bool
	{
		foreach ($this->analyseExcludes as $exclude) {
			if (strpos($file, $exclude) === 0) {
				return true;
			}

			$isWindows = DIRECTORY_SEPARATOR === '\\';
			if ($isWindows) {
				$fnmatchFlags = FNM_NOESCAPE | FNM_CASEFOLD;
			} else {
				$fnmatchFlags = 0;
			}

			if ($this->isFnmatchPattern($exclude) && fnmatch($exclude, $file, $fnmatchFlags)) {
				return true;
			}
		}

		return false;
	}

	private function isFnmatchPattern(string $path): bool
	{
		return preg_match('~[*?[\]]~', $path) > 0;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\File;

class FileHelper
{

	/** @var string */
	private $workingDirectory;

	public function __construct(string $workingDirectory)
	{
		$this->workingDirectory = $this->normalizePath($workingDirectory);
	}

	public function getWorkingDirectory(): string
	{
		return $this->workingDirectory;
	}

	public function absolutizePath(string $path): string
	{
		if (DIRECTORY_SEPARATOR === '/') {
			if (substr($path, 0, 1) === '/') {
				return $path;
			}
		} else {
			if (substr($path, 1, 1) === ':') {
				return $path;
			}
		}

		return rtrim($this->getWorkingDirectory(), '/\\') . DIRECTORY_SEPARATOR . ltrim($path, '/\\');
	}

	public function normalizePath(string $originalPath): string
	{
		if (preg_match('~^([a-z]+)\\:\\/\\/(.+)~', $originalPath, $m)) {
			list(, $scheme, $path) = $m;
		} else {
			$scheme = null;
			$path = $originalPath;
		}

		$path = str_replace('\\', '/', $path);
		$path = preg_replace('~/{2,}~', '/', $path);

		$pathRoot = strpos($path, '/') === 0 ? DIRECTORY_SEPARATOR : '';
		$pathParts = explode('/', trim($path, '/'));

		$normalizedPathParts = [];
		foreach ($pathParts as $pathPart) {
			if ($pathPart === '.') {
				continue;
			}
			if ($pathPart === '..') {
				$removedPart = array_pop($normalizedPathParts);
				if ($scheme === 'phar' && substr($removedPart, -5) === '.phar') {
					$scheme = null;
				}

			} else {
				$normalizedPathParts[] = $pathPart;
			}
		}

		return ($scheme !== null ? $scheme . '://' : '') . $pathRoot . implode(DIRECTORY_SEPARATOR, $normalizedPathParts);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Parser;

class CachedParser implements \PHPStan\Parser\Parser
{

	/** @var \PHPStan\Parser\Parser */
	private $originalParser;

	/** @var mixed[] */
	private $cachedNodesByFile = [];

	/** @var mixed[] */
	private $cachedNodesByString = [];

	public function __construct(\PHPStan\Parser\Parser $originalParser)
	{
		$this->originalParser = $originalParser;
	}

	/**
	 * @param string $file path to a file to parse
	 * @return \PhpParser\Node[]
	 */
	public function parseFile(string $file): array
	{
		if (!isset($this->cachedNodesByFile[$file])) {
			$this->cachedNodesByFile[$file] = $this->originalParser->parseFile($file);
		}

		return $this->cachedNodesByFile[$file];
	}

	/**
	 * @param string $sourceCode
	 * @return \PhpParser\Node[]
	 */
	public function parseString(string $sourceCode): array
	{
		if (!isset($this->cachedNodesByString[$sourceCode])) {
			$this->cachedNodesByString[$sourceCode] = $this->originalParser->parseString($sourceCode);
		}

		return $this->cachedNodesByString[$sourceCode];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Parser;

class DirectParser implements \PHPStan\Parser\Parser
{

	/**
	 * @var \PhpParser\Parser
	 */
	private $parser;

	/**
	 * @var \PhpParser\NodeTraverser
	 */
	private $traverser;

	public function __construct(\PhpParser\Parser $parser, \PhpParser\NodeTraverser $traverser)
	{
		$this->parser = $parser;
		$this->traverser = $traverser;
	}

	/**
	 * @param string $file path to a file to parse
	 * @return \PhpParser\Node[]
	 */
	public function parseFile(string $file): array
	{
		return $this->parseString(file_get_contents($file));
	}

	/**
	 * @param string $sourceCode
	 * @return \PhpParser\Node[]
	 */
	public function parseString(string $sourceCode): array
	{
		$nodes = $this->parser->parse($sourceCode);
		if ($nodes === null) {
			throw new \PHPStan\ShouldNotHappenException();
		}
		return $this->traverser->traverse($nodes);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Parser;

class FunctionCallStatementFinder
{

	/**
	 * @param string[] $functionNames
	 * @param mixed $statements
	 * @return \PhpParser\Node|null
	 */
	public function findFunctionCallInStatements(array $functionNames, $statements)
	{
		foreach ($statements as $statement) {
			if (is_array($statement)) {
				$result = $this->findFunctionCallInStatements($functionNames, $statement);
				if ($result !== null) {
					return $result;
				}
			}

			if (!($statement instanceof \PhpParser\Node)) {
				continue;
			}

			if ($statement instanceof \PhpParser\Node\Expr\FuncCall && $statement->name instanceof \PhpParser\Node\Name) {
				if (in_array((string) $statement->name, $functionNames, true)) {
					return $statement;
				}
			}

			$result = $this->findFunctionCallInStatements($functionNames, $statement);
			if ($result !== null) {
				return $result;
			}
		}

		return null;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Parser;

interface Parser
{

	/**
	 * @param string $file path to a file to parse
	 * @return \PhpParser\Node[]
	 */
	public function parseFile(string $file): array;

	/**
	 * @param string $sourceCode
	 * @return \PhpParser\Node[]
	 */
	public function parseString(string $sourceCode): array;

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDoc;

use PHPStan\Broker\Broker;
use PHPStan\Reflection\ClassReflection;

class PhpDocBlock
{

	/** @var string */
	private $docComment;

	/** @var string */
	private $file;

	/** @var string */
	private $class;

	private function __construct(
		string $docComment,
		string $file,
		string $class
	)
	{
		$this->docComment = $docComment;
		$this->file = $file;
		$this->class = $class;
	}

	public function getDocComment(): string
	{
		return $this->docComment;
	}

	public function getFile(): string
	{
		return $this->file;
	}

	public function getClass(): string
	{
		return $this->class;
	}

	public static function resolvePhpDocBlockForProperty(
		\PHPStan\Broker\Broker $broker,
		string $docComment,
		string $class,
		string $propertyName,
		string $file
	): self
	{
		return self::resolvePhpDocBlock(
			$broker,
			$docComment,
			$class,
			$propertyName,
			$file,
			'hasNativeProperty',
			'getNativeProperty',
			__FUNCTION__
		);
	}

	public static function resolvePhpDocBlockForMethod(
		\PHPStan\Broker\Broker $broker,
		string $docComment,
		string $class,
		string $methodName,
		string $file
	): self
	{
		return self::resolvePhpDocBlock(
			$broker,
			$docComment,
			$class,
			$methodName,
			$file,
			'hasNativeMethod',
			'getNativeMethod',
			__FUNCTION__
		);
	}

	private static function resolvePhpDocBlock(
		\PHPStan\Broker\Broker $broker,
		string $docComment,
		string $class,
		string $name,
		string $file,
		string $hasMethodName,
		string $getMethodName,
		string $resolveMethodName
	): self
	{
		if (
			preg_match('#\{@inheritdoc\}#i', $docComment) > 0
			&& $broker->hasClass($class)
		) {
			$classReflection = $broker->getClass($class);
			if ($classReflection->getParentClass() !== false) {
				$parentClassReflection = $classReflection->getParentClass();
				$phpDocBlockFromClass = self::resolvePhpDocBlockFromClass(
					$broker,
					$parentClassReflection,
					$name,
					$hasMethodName,
					$getMethodName,
					$resolveMethodName
				);
				if ($phpDocBlockFromClass !== null) {
					return $phpDocBlockFromClass;
				}
			}

			foreach ($classReflection->getInterfaces() as $interface) {
				$phpDocBlockFromClass = self::resolvePhpDocBlockFromClass(
					$broker,
					$interface,
					$name,
					$hasMethodName,
					$getMethodName,
					$resolveMethodName
				);
				if ($phpDocBlockFromClass !== null) {
					return $phpDocBlockFromClass;
				}
			}
		}

		return new self($docComment, $file, $class);
	}

	/**
	 * @param \PHPStan\Broker\Broker $broker
	 * @param \PHPStan\Reflection\ClassReflection $classReflection
	 * @param string $name
	 * @param string $hasMethodName
	 * @param string $getMethodName
	 * @param string $resolveMethodName
	 * @return self|null
	 */
	private static function resolvePhpDocBlockFromClass(
		\PHPStan\Broker\Broker $broker,
		\PHPStan\Reflection\ClassReflection $classReflection,
		string $name,
		string $hasMethodName,
		string $getMethodName,
		string $resolveMethodName
	)
	{
		if ($classReflection->getFileName() !== false && $classReflection->$hasMethodName($name)) {
			/** @var \PHPStan\Reflection\Php\PhpMethodReflection|\PHPStan\Reflection\Php\PhpPropertyReflection $parentReflection */
			$parentReflection = $classReflection->$getMethodName($name);
			if ($parentReflection->getDocComment() !== false) {
				return self::$resolveMethodName(
					$broker,
					$parentReflection->getDocComment(),
					$classReflection->getName(),
					$name,
					$classReflection->getFileName()
				);
			}
		}

		return null;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDoc;

use PHPStan\Analyser\NameScope;
use PHPStan\PhpDoc\Tag\MethodTag;
use PHPStan\PhpDoc\Tag\MethodTagParameter;
use PHPStan\PhpDoc\Tag\ParamTag;
use PHPStan\PhpDoc\Tag\PropertyTag;
use PHPStan\PhpDoc\Tag\ReturnTag;
use PHPStan\PhpDoc\Tag\VarTag;
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprNullNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use PHPStan\Type\ArrayType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\MixedType;
use PHPStan\Type\TypeCombinator;

class PhpDocNodeResolver
{

	/** @var TypeNodeResolver */
	private $typeNodeResolver;

	public function __construct(\PHPStan\PhpDoc\TypeNodeResolver $typeNodeResolver)
	{
		$this->typeNodeResolver = $typeNodeResolver;
	}

	public function resolve(\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode $phpDocNode, \PHPStan\Analyser\NameScope $nameScope): \PHPStan\PhpDoc\ResolvedPhpDocBlock
	{
		return new \PHPStan\PhpDoc\ResolvedPhpDocBlock(
			$this->resolveVarTags($phpDocNode, $nameScope),
			$this->resolveMethodTags($phpDocNode, $nameScope),
			$this->resolvePropertyTags($phpDocNode, $nameScope),
			$this->resolveParamTags($phpDocNode, $nameScope),
			$this->resolveReturnTag($phpDocNode, $nameScope)
		);
	}

	/**
	 * @param PhpDocNode $phpDocNode
	 * @param NameScope $nameScope
	 * @return \PHPStan\PhpDoc\Tag\VarTag[]
	 */
	private function resolveVarTags(\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode $phpDocNode, \PHPStan\Analyser\NameScope $nameScope): array
	{
		$resolved = [];
		foreach ($phpDocNode->getVarTagValues() as $tagValue) {
			if ($tagValue->variableName !== '') {
				$variableName = substr($tagValue->variableName, 1);
				$type = !isset($resolved[$variableName])
					? $this->typeNodeResolver->resolve($tagValue->type, $nameScope)
					: new \PHPStan\Type\MixedType();
				$resolved[$variableName] = new \PHPStan\PhpDoc\Tag\VarTag($type);

			} else {
				$resolved[] = new \PHPStan\PhpDoc\Tag\VarTag($this->typeNodeResolver->resolve($tagValue->type, $nameScope));
			}
		}

		return $resolved;
	}

	/**
	 * @param PhpDocNode $phpDocNode
	 * @param NameScope $nameScope
	 * @return \PHPStan\PhpDoc\Tag\PropertyTag[]
	 */
	private function resolvePropertyTags(\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode $phpDocNode, \PHPStan\Analyser\NameScope $nameScope): array
	{
		$resolved = [];

		foreach ($phpDocNode->getPropertyTagValues() as $tagValue) {
			$propertyName = substr($tagValue->propertyName, 1);
			$propertyType = !isset($resolved[$propertyName])
				? $this->typeNodeResolver->resolve($tagValue->type, $nameScope)
				: new \PHPStan\Type\MixedType();

			$resolved[$propertyName] = new \PHPStan\PhpDoc\Tag\PropertyTag(
				$propertyType,
				true,
				true
			);
		}

		foreach ($phpDocNode->getPropertyReadTagValues() as $tagValue) {
			$propertyName = substr($tagValue->propertyName, 1);
			$propertyType = !isset($resolved[$propertyName])
				? $this->typeNodeResolver->resolve($tagValue->type, $nameScope)
				: new \PHPStan\Type\MixedType();

			$resolved[$propertyName] = new \PHPStan\PhpDoc\Tag\PropertyTag(
				$propertyType,
				true,
				false
			);
		}

		foreach ($phpDocNode->getPropertyWriteTagValues() as $tagValue) {
			$propertyName = substr($tagValue->propertyName, 1);
			$propertyType = !isset($resolved[$propertyName])
				? $this->typeNodeResolver->resolve($tagValue->type, $nameScope)
				: new \PHPStan\Type\MixedType();

			$resolved[$propertyName] = new \PHPStan\PhpDoc\Tag\PropertyTag(
				$propertyType,
				false,
				true
			);
		}

		return $resolved;
	}

	/**
	 * @param PhpDocNode $phpDocNode
	 * @param NameScope $nameScope
	 * @return \PHPStan\PhpDoc\Tag\MethodTag[]
	 */
	private function resolveMethodTags(\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode $phpDocNode, \PHPStan\Analyser\NameScope $nameScope): array
	{
		$resolved = [];

		foreach ($phpDocNode->getMethodTagValues() as $tagValue) {
			$parameters = [];
			foreach ($tagValue->parameters as $parameterNode) {
				$parameterName = substr($parameterNode->parameterName, 1);
				$type = $parameterNode->type !== null ? $this->typeNodeResolver->resolve($parameterNode->type, $nameScope) : new \PHPStan\Type\MixedType();
				if ($parameterNode->defaultValue instanceof \PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprNullNode) {
					$type = \PHPStan\Type\TypeCombinator::addNull($type);
				}
				$parameters[$parameterName] = new \PHPStan\PhpDoc\Tag\MethodTagParameter(
					$type,
					$parameterNode->isReference,
					$parameterNode->defaultValue !== null,
					$parameterNode->isVariadic
				);
			}

			$resolved[$tagValue->methodName] = new \PHPStan\PhpDoc\Tag\MethodTag(
				$tagValue->returnType !== null ? $this->typeNodeResolver->resolve($tagValue->returnType, $nameScope) : new \PHPStan\Type\MixedType(),
				$tagValue->isStatic,
				$parameters
			);
		}

		return $resolved;
	}

	/**
	 * @param  PhpDocNode $phpDocNode
	 * @param  NameScope $nameScope
	 * @return \PHPStan\PhpDoc\Tag\ParamTag[]
	 */
	private function resolveParamTags(\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode $phpDocNode, \PHPStan\Analyser\NameScope $nameScope): array
	{
		$resolved = [];
		foreach ($phpDocNode->getParamTagValues() as $tagValue) {
			$parameterName = substr($tagValue->parameterName, 1);
			$parameterType = !isset($resolved[$parameterName])
				? $this->typeNodeResolver->resolve($tagValue->type, $nameScope)
				: new \PHPStan\Type\MixedType();

			if ($tagValue->isVariadic) {
				if (!$parameterType instanceof \PHPStan\Type\ArrayType) {
					$parameterType = new \PHPStan\Type\ArrayType(new \PHPStan\Type\IntegerType(), $parameterType);

				} elseif ($parameterType->getIterableKeyType() instanceof \PHPStan\Type\MixedType) {
					$parameterType = new \PHPStan\Type\ArrayType(new \PHPStan\Type\IntegerType(), $parameterType->getItemType());
				}
			}

			$resolved[$parameterName] = new \PHPStan\PhpDoc\Tag\ParamTag(
				$parameterType,
				$tagValue->isVariadic
			);
		}

		return $resolved;
	}

	/**
	 * @param  PhpDocNode $phpDocNode
	 * @param  NameScope $nameScope
	 * @return \PHPStan\PhpDoc\Tag\ReturnTag|null
	 */
	private function resolveReturnTag(\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode $phpDocNode, \PHPStan\Analyser\NameScope $nameScope)
	{
		foreach ($phpDocNode->getReturnTagValues() as $tagValue) {
			return new \PHPStan\PhpDoc\Tag\ReturnTag($this->typeNodeResolver->resolve($tagValue->type, $nameScope));
		}

		return null;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDoc;

use PHPStan\Analyser\NameScope;
use PHPStan\PhpDocParser\Lexer\Lexer;
use PHPStan\PhpDocParser\Parser\PhpDocParser;
use PHPStan\PhpDocParser\Parser\TokenIterator;

class PhpDocStringResolver
{

	/** @var Lexer */
	private $phpDocLexer;

	/** @var PhpDocParser */
	private $phpDocParser;

	/** @var PhpDocNodeResolver */
	private $phpDocNodeResolver;

	public function __construct(\PHPStan\PhpDocParser\Lexer\Lexer $phpDocLexer, \PHPStan\PhpDocParser\Parser\PhpDocParser $phpDocParser, \PHPStan\PhpDoc\PhpDocNodeResolver $phpDocNodeResolver)
	{
		$this->phpDocNodeResolver = $phpDocNodeResolver;
		$this->phpDocLexer = $phpDocLexer;
		$this->phpDocParser = $phpDocParser;
	}

	public function resolve(string $phpDocString, \PHPStan\Analyser\NameScope $nameScope): \PHPStan\PhpDoc\ResolvedPhpDocBlock
	{
		$tokens = new \PHPStan\PhpDocParser\Parser\TokenIterator($this->phpDocLexer->tokenize($phpDocString));
		$phpDocNode = $this->phpDocParser->parse($tokens);
		$tokens->consumeTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_END);

		return $this->phpDocNodeResolver->resolve($phpDocNode, $nameScope);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDoc;

use PHPStan\PhpDoc\Tag\ReturnTag;

class ResolvedPhpDocBlock
{

	/**
	 * @var \PHPStan\PhpDoc\Tag\VarTag[]
	 */
	private $varTags;

	/**
	 * @var \PHPStan\PhpDoc\Tag\MethodTag[]
	 */
	private $methodTags;

	/**
	 * @var \PHPStan\PhpDoc\Tag\PropertyTag[]
	 */
	private $propertyTags;

	/**
	 * @var \PHPStan\PhpDoc\Tag\ParamTag[]
	 */
	private $paramTags;

	/**
	 * @var \PHPStan\PhpDoc\Tag\ReturnTag|null
	 */
	private $returnTag;

	/**
	 * @param \PHPStan\PhpDoc\Tag\VarTag[] $varTags
	 * @param \PHPStan\PhpDoc\Tag\MethodTag[] $methodTags
	 * @param \PHPStan\PhpDoc\Tag\PropertyTag[] $propertyTags
	 * @param \PHPStan\PhpDoc\Tag\ParamTag[] $paramTags
	 * @param \PHPStan\PhpDoc\Tag\ReturnTag|null $returnTag
	 */
	public function __construct(
		array $varTags,
		array $methodTags,
		array $propertyTags,
		array $paramTags,
		\PHPStan\PhpDoc\Tag\ReturnTag $returnTag = null
	)
	{
		$this->varTags = $varTags;
		$this->methodTags = $methodTags;
		$this->propertyTags = $propertyTags;
		$this->paramTags = $paramTags;
		$this->returnTag = $returnTag;
	}

	/**
	 * @return \PHPStan\PhpDoc\Tag\VarTag[]
	 */
	public function getVarTags(): array
	{
		return $this->varTags;
	}

	/**
	 * @return \PHPStan\PhpDoc\Tag\MethodTag[]
	 */
	public function getMethodTags(): array
	{
		return $this->methodTags;
	}

	/**
	 * @return \PHPStan\PhpDoc\Tag\PropertyTag[]
	 */
	public function getPropertyTags(): array
	{
		return $this->propertyTags;
	}

	/**
	 * @return \PHPStan\PhpDoc\Tag\ParamTag[]
	 */
	public function getParamTags(): array
	{
		return $this->paramTags;
	}

	/**
	 * @return \PHPStan\PhpDoc\Tag\ReturnTag|null
	 */
	public function getReturnTag()
	{
		return $this->returnTag;
	}

	public static function __set_state(array $properties): self
	{
		return new self(
			$properties['varTags'],
			$properties['methodTags'],
			$properties['propertyTags'],
			$properties['paramTags'],
			$properties['returnTag']
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDoc\Tag;

use PHPStan\Type\Type;

class MethodTag
{

	/** @var \PHPStan\Type\Type */
	private $returnType;

	/** @var bool */
	private $isStatic;

	/** @var \PHPStan\PhpDoc\Tag\MethodTagParameter[] */
	private $parameters;

	/**
	 * @param \PHPStan\Type\Type $returnType
	 * @param bool $isStatic
	 * @param \PHPStan\PhpDoc\Tag\MethodTagParameter[] $parameters
	 */
	public function __construct(
		\PHPStan\Type\Type $returnType,
		bool $isStatic,
		array $parameters
	)
	{
		$this->returnType = $returnType;
		$this->isStatic = $isStatic;
		$this->parameters = $parameters;
	}

	public function getReturnType(): \PHPStan\Type\Type
	{
		return $this->returnType;
	}

	public function isStatic(): bool
	{
		return $this->isStatic;
	}

	/**
	 * @return \PHPStan\PhpDoc\Tag\MethodTagParameter[]
	 */
	public function getParameters(): array
	{
		return $this->parameters;
	}

	public static function __set_state(array $properties): self
	{
		return new self(
			$properties['returnType'],
			$properties['isStatic'],
			$properties['parameters']
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDoc\Tag;

use PHPStan\Type\Type;

class MethodTagParameter
{

	/** @var \PHPStan\Type\Type */
	private $type;

	/** @var bool */
	private $isPassedByReference;

	/** @var bool */
	private $isOptional;

	/** @var bool */
	private $isVariadic;

	public function __construct(
		\PHPStan\Type\Type $type,
		bool $isPassedByReference,
		bool $isOptional,
		bool $isVariadic
	)
	{
		$this->type = $type;
		$this->isPassedByReference = $isPassedByReference;
		$this->isOptional = $isOptional;
		$this->isVariadic = $isVariadic;
	}

	public function getType(): \PHPStan\Type\Type
	{
		return $this->type;
	}

	public function isPassedByReference(): bool
	{
		return $this->isPassedByReference;
	}

	public function isOptional(): bool
	{
		return $this->isOptional;
	}

	public function isVariadic(): bool
	{
		return $this->isVariadic;
	}

	public static function __set_state(array $properties): self
	{
		return new self(
			$properties['type'],
			$properties['isPassedByReference'],
			$properties['isOptional'],
			$properties['isVariadic']
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDoc\Tag;

use PHPStan\Type\Type;

class ParamTag
{

	/** @var \PHPStan\Type\Type */
	private $type;

	/** @var bool */
	private $isVariadic;

	public function __construct(\PHPStan\Type\Type $type, bool $isVariadic)
	{
		$this->type = $type;
		$this->isVariadic = $isVariadic;
	}

	public function getType(): \PHPStan\Type\Type
	{
		return $this->type;
	}

	public function isVariadic(): bool
	{
		return $this->isVariadic;
	}

	public static function __set_state(array $properties): self
	{
		return new self(
			$properties['type'],
			$properties['isVariadic']
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDoc\Tag;

use PHPStan\Type\Type;

class PropertyTag
{

	/** @var \PHPStan\Type\Type */
	private $type;

	/** @var bool */
	private $readable;

	/** @var bool */
	private $writable;

	public function __construct(
		\PHPStan\Type\Type $type,
		bool $readable,
		bool $writable
	)
	{
		$this->type = $type;
		$this->readable = $readable;
		$this->writable = $writable;
	}

	public function getType(): \PHPStan\Type\Type
	{
		return $this->type;
	}

	public function isReadable(): bool
	{
		return $this->readable;
	}

	public function isWritable(): bool
	{
		return $this->writable;
	}

	public static function __set_state(array $properties): self
	{
		return new self(
			$properties['type'],
			$properties['readable'],
			$properties['writable']
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDoc\Tag;

use PHPStan\Type\Type;

class ReturnTag
{

	/** @var \PHPStan\Type\Type */
	private $type;

	public function __construct(\PHPStan\Type\Type $type)
	{
		$this->type = $type;
	}

	public function getType(): \PHPStan\Type\Type
	{
		return $this->type;
	}

	public static function __set_state(array $properties): self
	{
		return new self(
			$properties['type']
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDoc\Tag;

use PHPStan\Type\Type;

class VarTag
{

	/** @var \PHPStan\Type\Type */
	private $type;

	public function __construct(\PHPStan\Type\Type $type)
	{
		$this->type = $type;
	}

	public function getType(): \PHPStan\Type\Type
	{
		return $this->type;
	}

	public static function __set_state(array $properties): self
	{
		return new self(
			$properties['type']
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDoc;

use PHPStan\Analyser\NameScope;
use PHPStan\Broker\Broker;
use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\IntersectionTypeNode;
use PHPStan\PhpDocParser\Ast\Type\NullableTypeNode;
use PHPStan\PhpDocParser\Ast\Type\ThisTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode;
use PHPStan\Type\ArrayType;
use PHPStan\Type\CallableType;
use PHPStan\Type\ErrorType;
use PHPStan\Type\FalseBooleanType;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\IterableIterableType;
use PHPStan\Type\MixedType;
use PHPStan\Type\NonexistentParentClassType;
use PHPStan\Type\NullType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\ObjectWithoutClassType;
use PHPStan\Type\ResourceType;
use PHPStan\Type\StaticType;
use PHPStan\Type\StringType;
use PHPStan\Type\ThisType;
use PHPStan\Type\TrueBooleanType;
use PHPStan\Type\TrueOrFalseBooleanType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\TypeWithClassName;
use PHPStan\Type\UnionType;
use PHPStan\Type\VoidType;

class TypeNodeResolver
{

	public function resolve(\PHPStan\PhpDocParser\Ast\Type\TypeNode $typeNode, \PHPStan\Analyser\NameScope $nameScope): \PHPStan\Type\Type
	{
		if ($typeNode instanceof \PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode) {
			return $this->resolveIdentifierTypeNode($typeNode, $nameScope);

		} elseif ($typeNode instanceof \PHPStan\PhpDocParser\Ast\Type\ThisTypeNode) {
			return $this->resolveThisTypeNode($typeNode, $nameScope);

		} elseif ($typeNode instanceof \PHPStan\PhpDocParser\Ast\Type\NullableTypeNode) {
			return $this->resolveNullableTypeNode($typeNode, $nameScope);

		} elseif ($typeNode instanceof \PHPStan\PhpDocParser\Ast\Type\UnionTypeNode) {
			return $this->resolveUnionTypeNode($typeNode, $nameScope);

		} elseif ($typeNode instanceof \PHPStan\PhpDocParser\Ast\Type\IntersectionTypeNode) {
			return $this->resolveIntersectionTypeNode($typeNode, $nameScope);

		} elseif ($typeNode instanceof \PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode) {
			return $this->resolveArrayTypeNode($typeNode, $nameScope);

		} elseif ($typeNode instanceof \PHPStan\PhpDocParser\Ast\Type\GenericTypeNode) {
			return $this->resolveGenericTypeNode($typeNode, $nameScope);
		}

		return new \PHPStan\Type\ErrorType();
	}

	private function resolveIdentifierTypeNode(\PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode $typeNode, \PHPStan\Analyser\NameScope $nameScope): \PHPStan\Type\Type
	{
		switch (strtolower($typeNode->name)) {
			case 'int':
			case 'integer':
				return new \PHPStan\Type\IntegerType();

			case 'string':
				return new \PHPStan\Type\StringType();

			case 'bool':
			case 'boolean':
				return new \PHPStan\Type\TrueOrFalseBooleanType();

			case 'true':
				return new \PHPStan\Type\TrueBooleanType();

			case 'false':
				return new \PHPStan\Type\FalseBooleanType();

			case 'null':
				return new \PHPStan\Type\NullType();

			case 'float':
			case 'double':
				return new \PHPStan\Type\FloatType();

			case 'array':
				return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType());

			case 'scalar':
				return new \PHPStan\Type\UnionType([
					new \PHPStan\Type\IntegerType(),
					new \PHPStan\Type\FloatType(),
					new \PHPStan\Type\StringType(),
					new \PHPStan\Type\TrueOrFalseBooleanType(),
				]);

			case 'number':
				return new \PHPStan\Type\UnionType([
					new \PHPStan\Type\IntegerType(),
					new \PHPStan\Type\FloatType(),
				]);

			case 'iterable':
				return new \PHPStan\Type\IterableIterableType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType());

			case 'callable':
				return new \PHPStan\Type\CallableType();

			case 'resource':
				return new \PHPStan\Type\ResourceType();

			case 'mixed':
				return new \PHPStan\Type\MixedType(true);

			case 'void':
				return new \PHPStan\Type\VoidType();

			case 'object':
				return new \PHPStan\Type\ObjectWithoutClassType();
		}

		if ($nameScope->getClassName() !== null) {
			switch (strtolower($typeNode->name)) {
				case 'self':
					return new \PHPStan\Type\ObjectType($nameScope->getClassName());

				case 'static':
					return new \PHPStan\Type\StaticType($nameScope->getClassName());

				case 'parent':
					$broker = \PHPStan\Broker\Broker::getInstance();
					if ($broker->hasClass($nameScope->getClassName())) {
						$classReflection = $broker->getClass($nameScope->getClassName());
						if ($classReflection->getParentClass() !== false) {
							return new \PHPStan\Type\ObjectType($classReflection->getParentClass()->getName());
						}
					}

					return new \PHPStan\Type\NonexistentParentClassType();
			}
		}

		return new \PHPStan\Type\ObjectType($nameScope->resolveStringName($typeNode->name));
	}

	private function resolveThisTypeNode(\PHPStan\PhpDocParser\Ast\Type\ThisTypeNode $typeNode, \PHPStan\Analyser\NameScope $nameScope): \PHPStan\Type\Type
	{
		if ($nameScope->getClassName() !== null) {
			return new \PHPStan\Type\ThisType($nameScope->getClassName());
		}

		return new \PHPStan\Type\ErrorType();
	}

	private function resolveNullableTypeNode(\PHPStan\PhpDocParser\Ast\Type\NullableTypeNode $typeNode, \PHPStan\Analyser\NameScope $nameScope): \PHPStan\Type\Type
	{
		return \PHPStan\Type\TypeCombinator::addNull($this->resolve($typeNode->type, $nameScope));
	}

	private function resolveUnionTypeNode(\PHPStan\PhpDocParser\Ast\Type\UnionTypeNode $typeNode, \PHPStan\Analyser\NameScope $nameScope): \PHPStan\Type\Type
	{
		$iterableTypeNodes = [];
		$otherTypeNodes = [];

		foreach ($typeNode->types as $innerTypeNode) {
			if ($innerTypeNode instanceof \PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode) {
				$iterableTypeNodes[] = $innerTypeNode->type;
			} else {
				$otherTypeNodes[] = $innerTypeNode;
			}
		}

		$otherTypeTypes = $this->resolveMultiple($otherTypeNodes, $nameScope);

		if (count($otherTypeTypes) === 2) {
			static $mockClassNames = [
				'PHPUnit_Framework_MockObject_MockObject' => true,
				'PHPUnit\Framework\MockObject\MockObject' => true,
			];

			foreach ($otherTypeTypes as $otherType) {
				if ($otherType instanceof \PHPStan\Type\TypeWithClassName && isset($mockClassNames[$otherType->getClassName()])) {
					return \PHPStan\Type\TypeCombinator::intersect(...$otherTypeTypes);
				}
			}
		}

		if (count($iterableTypeNodes) > 0) {
			$arrayTypeTypes = $this->resolveMultiple($iterableTypeNodes, $nameScope);
			$arrayTypeType = \PHPStan\Type\TypeCombinator::union(...$arrayTypeTypes);
			$addArray = true;

			foreach ($otherTypeTypes as &$type) {
				if ($type->isIterable()->yes() && $type->getIterableValueType()->isSuperTypeOf($arrayTypeType)->yes()) {
					if ($type instanceof \PHPStan\Type\ObjectType) {
						$type = new \PHPStan\Type\IntersectionType([$type, new \PHPStan\Type\IterableIterableType(new \PHPStan\Type\MixedType(), $arrayTypeType)]);
					} elseif ($type instanceof \PHPStan\Type\ArrayType) {
						$type = new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), $arrayTypeType);
					} elseif ($type instanceof \PHPStan\Type\IterableIterableType) {
						$type = new \PHPStan\Type\IterableIterableType(new \PHPStan\Type\MixedType(), $arrayTypeType);
					} else {
						continue;
					}

					$addArray = false;
				}
			}

			if ($addArray) {
				$otherTypeTypes[] = new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), $arrayTypeType);
			}
		}

		return \PHPStan\Type\TypeCombinator::union(...$otherTypeTypes);
	}

	private function resolveIntersectionTypeNode(\PHPStan\PhpDocParser\Ast\Type\IntersectionTypeNode $typeNode, \PHPStan\Analyser\NameScope $nameScope): \PHPStan\Type\Type
	{
		$types = $this->resolveMultiple($typeNode->types, $nameScope);
		return \PHPStan\Type\TypeCombinator::intersect(...$types);
	}

	private function resolveArrayTypeNode(\PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode $typeNode, \PHPStan\Analyser\NameScope $nameScope): \PHPStan\Type\Type
	{
		$itemType = $this->resolve($typeNode->type, $nameScope);
		return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), $itemType);
	}

	private function resolveGenericTypeNode(\PHPStan\PhpDocParser\Ast\Type\GenericTypeNode $typeNode, \PHPStan\Analyser\NameScope $nameScope): \PHPStan\Type\Type
	{
		$mainType = strtolower($typeNode->type->name);
		$genericTypes = $this->resolveMultiple($typeNode->genericTypes, $nameScope);

		if ($mainType === 'array') {
			if (count($genericTypes) === 1) { // array<ValueType>
				return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), $genericTypes[0]);

			} elseif (count($genericTypes) === 2) { // array<KeyType, ValueType>
				return new \PHPStan\Type\ArrayType($genericTypes[0], $genericTypes[1]);
			}

		} elseif ($mainType === 'iterable') {
			if (count($genericTypes) === 1) { // iterable<ValueType>
				return new \PHPStan\Type\IterableIterableType(new \PHPStan\Type\MixedType(), $genericTypes[0]);

			} elseif (count($genericTypes) === 2) { // iterable<KeyType, ValueType>
				return new \PHPStan\Type\IterableIterableType($genericTypes[0], $genericTypes[1]);
			}
		}

		return new \PHPStan\Type\ErrorType();
	}

	/**
	 * @param TypeNode[] $typeNodes
	 * @param NameScope $nameScope
	 * @return Type[]
	 */
	private function resolveMultiple(array $typeNodes, \PHPStan\Analyser\NameScope $nameScope): array
	{
		$types = [];
		foreach ($typeNodes as $typeNode) {
			$types[] = $this->resolve($typeNode, $nameScope);
		}

		return $types;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDoc;

use PHPStan\Analyser\NameScope;
use PHPStan\PhpDocParser\Lexer\Lexer;
use PHPStan\PhpDocParser\Parser\TokenIterator;
use PHPStan\PhpDocParser\Parser\TypeParser;
use PHPStan\Type\Type;

class TypeStringResolver
{

	/** @var Lexer */
	private $typeLexer;

	/** @var TypeParser */
	private $typeParser;

	/** @var TypeNodeResolver */
	private $typeNodeResolver;

	public function __construct(\PHPStan\PhpDocParser\Lexer\Lexer $typeLexer, \PHPStan\PhpDocParser\Parser\TypeParser $typeParser, \PHPStan\PhpDoc\TypeNodeResolver $typeNodeResolver)
	{
		$this->typeLexer = $typeLexer;
		$this->typeParser = $typeParser;
		$this->typeNodeResolver = $typeNodeResolver;
	}

	public function resolve(string $typeString, \PHPStan\Analyser\NameScope $nameScope = null): \PHPStan\Type\Type
	{
		$tokens = new \PHPStan\PhpDocParser\Parser\TokenIterator($this->typeLexer->tokenize($typeString));
		$typeNode = $this->typeParser->parse($tokens);
		$tokens->consumeTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_END);

		return $this->typeNodeResolver->resolve($typeNode, $nameScope ?? new \PHPStan\Analyser\NameScope(null, []));
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\Annotations;

use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Type\Type;

class AnnotationMethodReflection implements \PHPStan\Reflection\MethodReflection
{

	/** @var string */
	private $name;

	/** @var \PHPStan\Reflection\ClassReflection */
	private $declaringClass;

	/** @var  Type */
	private $returnType;

	/** @var bool */
	private $isStatic;

	/** @var \PHPStan\Reflection\Annotations\AnnotationsMethodParameterReflection[] */
	private $parameters;

	/** @var bool */
	private $isVariadic;

	public function __construct(string $name, \PHPStan\Reflection\ClassReflection $declaringClass, \PHPStan\Type\Type $returnType, array $parameters, bool $isStatic, bool $isVariadic)
	{
		$this->name = $name;
		$this->declaringClass = $declaringClass;
		$this->returnType = $returnType;
		$this->parameters = $parameters;
		$this->isStatic = $isStatic;
		$this->isVariadic = $isVariadic;
	}

	public function getDeclaringClass(): \PHPStan\Reflection\ClassReflection
	{
		return $this->declaringClass;
	}

	public function getPrototype(): \PHPStan\Reflection\MethodReflection
	{
		return $this;
	}

	public function isStatic(): bool
	{
		return $this->isStatic;
	}

	public function getParameters(): array
	{
		return $this->parameters;
	}

	public function isVariadic(): bool
	{
		return $this->isVariadic;
	}

	public function isPrivate(): bool
	{
		return false;
	}

	public function isPublic(): bool
	{
		return true;
	}

	public function getName(): string
	{
		return $this->name;
	}

	public function getReturnType(): \PHPStan\Type\Type
	{
		return $this->returnType;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\Annotations;

use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\Type\Type;

class AnnotationPropertyReflection implements \PHPStan\Reflection\PropertyReflection
{

	/** @var \PHPStan\Reflection\ClassReflection */
	private $declaringClass;

	/** @var \PHPStan\Type\Type */
	private $type;

	/** @var bool */
	private $readable;

	/** @var bool */
	private $writable;

	public function __construct(
		\PHPStan\Reflection\ClassReflection $declaringClass,
		\PHPStan\Type\Type $type,
		bool $readable = true,
		bool $writable = true
	)
	{
		$this->declaringClass = $declaringClass;
		$this->type = $type;
		$this->readable = $readable;
		$this->writable = $writable;
	}

	public function getDeclaringClass(): \PHPStan\Reflection\ClassReflection
	{
		return $this->declaringClass;
	}

	public function isStatic(): bool
	{
		return false;
	}

	public function isPrivate(): bool
	{
		return false;
	}

	public function isPublic(): bool
	{
		return true;
	}

	public function getType(): \PHPStan\Type\Type
	{
		return $this->type;
	}

	public function isReadable(): bool
	{
		return $this->readable;
	}

	public function isWritable(): bool
	{
		return $this->writable;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\Annotations;

use PHPStan\Reflection\ParameterReflection;
use PHPStan\Type\Type;

class AnnotationsMethodParameterReflection implements \PHPStan\Reflection\ParameterReflection
{

	/** @var string */
	private $name;

	/** @var Type */
	private $type;

	/** @var bool */
	private $isPassedByReference;

	/** @var bool */
	private $isOptional;

	/** @var bool */
	private $isVariadic;

	public function __construct(string $name, \PHPStan\Type\Type $type, bool $isPassedByReference, bool $isOptional, bool $isVariadic)
	{
		$this->name = $name;
		$this->type = $type;
		$this->isPassedByReference = $isPassedByReference;
		$this->isOptional = $isOptional;
		$this->isVariadic = $isVariadic;
	}

	public function getName(): string
	{
		return $this->name;
	}

	public function isOptional(): bool
	{
		return $this->isOptional;
	}

	public function getType(): \PHPStan\Type\Type
	{
		return $this->type;
	}

	public function isPassedByReference(): bool
	{
		return $this->isPassedByReference;
	}

	public function isVariadic(): bool
	{
		return $this->isVariadic;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\Annotations;

use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\MethodsClassReflectionExtension;
use PHPStan\Type\FileTypeMapper;

class AnnotationsMethodsClassReflectionExtension implements \PHPStan\Reflection\MethodsClassReflectionExtension
{

	/** @var FileTypeMapper */
	private $fileTypeMapper;

	/** @var MethodReflection[][] */
	private $methods = [];

	public function __construct(\PHPStan\Type\FileTypeMapper $fileTypeMapper)
	{
		$this->fileTypeMapper = $fileTypeMapper;
	}

	public function hasMethod(\PHPStan\Reflection\ClassReflection $classReflection, string $methodName): bool
	{
		if (!isset($this->methods[$classReflection->getName()])) {
			$this->methods[$classReflection->getName()] = $this->createMethods($classReflection, $classReflection);
		}

		return isset($this->methods[$classReflection->getName()][$methodName]);
	}

	public function getMethod(\PHPStan\Reflection\ClassReflection $classReflection, string $methodName): \PHPStan\Reflection\MethodReflection
	{
		return $this->methods[$classReflection->getName()][$methodName];
	}

	/**
	 * @param ClassReflection $classReflection
	 * @param ClassReflection $declaringClass
	 * @return MethodReflection[]
	 */
	private function createMethods(
		\PHPStan\Reflection\ClassReflection $classReflection,
		\PHPStan\Reflection\ClassReflection $declaringClass
	): array
	{
		$methods = [];
		foreach ($classReflection->getTraits() as $traitClass) {
			$methods += $this->createMethods($traitClass, $classReflection);
		}
		foreach ($classReflection->getParents() as $parentClass) {
			$methods += $this->createMethods($parentClass, $parentClass);
			foreach ($parentClass->getTraits() as $traitClass) {
				$methods += $this->createMethods($traitClass, $parentClass);
			}
		}
		foreach ($classReflection->getInterfaces() as $interfaceClass) {
			$methods += $this->createMethods($interfaceClass, $interfaceClass);
		}

		$fileName = $classReflection->getFileName();
		if ($fileName === false) {
			return $methods;
		}

		$docComment = $classReflection->getNativeReflection()->getDocComment();
		if ($docComment === false) {
			return $methods;
		}

		$resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($fileName, $classReflection->getName(), $docComment);
		foreach ($resolvedPhpDoc->getMethodTags() as $methodName => $methodTag) {
			$parameters = [];
			foreach ($methodTag->getParameters() as $parameterName => $parameterTag) {
				$parameters[] = new \PHPStan\Reflection\Annotations\AnnotationsMethodParameterReflection(
					$parameterName,
					$parameterTag->getType(),
					$parameterTag->isPassedByReference(),
					$parameterTag->isOptional(),
					$parameterTag->isVariadic()
				);
			}

			$methods[$methodName] = new \PHPStan\Reflection\Annotations\AnnotationMethodReflection(
				$methodName,
				$declaringClass,
				$methodTag->getReturnType(),
				$parameters,
				$methodTag->isStatic(),
				$this->detectMethodVariadic($parameters)
			);
		}
		return $methods;
	}

	/**
	 * @param AnnotationsMethodParameterReflection[] $parameters
	 * @return bool
	 */
	private function detectMethodVariadic(array $parameters): bool
	{
		if ($parameters === []) {
			return false;
		}

		$possibleVariadicParameterIndex = count($parameters) - 1;
		$possibleVariadicParameter = $parameters[$possibleVariadicParameterIndex];

		return $possibleVariadicParameter->isVariadic();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\Annotations;

use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\PropertiesClassReflectionExtension;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\Type\FileTypeMapper;

class AnnotationsPropertiesClassReflectionExtension implements \PHPStan\Reflection\PropertiesClassReflectionExtension
{

	/** @var \PHPStan\Type\FileTypeMapper */
	private $fileTypeMapper;

	/** @var \PHPStan\Reflection\PropertyReflection[][] */
	private $properties = [];

	public function __construct(\PHPStan\Type\FileTypeMapper $fileTypeMapper)
	{
		$this->fileTypeMapper = $fileTypeMapper;
	}

	public function hasProperty(\PHPStan\Reflection\ClassReflection $classReflection, string $propertyName): bool
	{
		if (!isset($this->properties[$classReflection->getName()])) {
			$this->properties[$classReflection->getName()] = $this->createProperties($classReflection, $classReflection);
		}

		return isset($this->properties[$classReflection->getName()][$propertyName]);
	}

	public function getProperty(\PHPStan\Reflection\ClassReflection $classReflection, string $propertyName): \PHPStan\Reflection\PropertyReflection
	{
		return $this->properties[$classReflection->getName()][$propertyName];
	}

	/**
	 * @param \PHPStan\Reflection\ClassReflection $classReflection
	 * @param \PHPStan\Reflection\ClassReflection $declaringClass
	 * @return \PHPStan\Reflection\PropertyReflection[]
	 */
	private function createProperties(
		\PHPStan\Reflection\ClassReflection $classReflection,
		\PHPStan\Reflection\ClassReflection $declaringClass
	): array
	{
		$properties = [];
		foreach ($classReflection->getTraits() as $traitClass) {
			$properties += $this->createProperties($traitClass, $classReflection);
		}
		foreach ($classReflection->getParents() as $parentClass) {
			$properties += $this->createProperties($parentClass, $parentClass);
			foreach ($parentClass->getTraits() as $traitClass) {
				$properties += $this->createProperties($traitClass, $parentClass);
			}
		}

		foreach ($classReflection->getInterfaces() as $interfaceClass) {
			$properties += $this->createProperties($interfaceClass, $interfaceClass);
		}

		$fileName = $classReflection->getFileName();
		if ($fileName === false) {
			return $properties;
		}

		$docComment = $classReflection->getNativeReflection()->getDocComment();
		if ($docComment === false) {
			return $properties;
		}

		$resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($fileName, $classReflection->getName(), $docComment);
		foreach ($resolvedPhpDoc->getPropertyTags() as $propertyName => $propertyTag) {
			$properties[$propertyName] = new \PHPStan\Reflection\Annotations\AnnotationPropertyReflection(
				$declaringClass,
				$propertyTag->getType(),
				$propertyTag->isReadable(),
				$propertyTag->isWritable()
			);
		}

		return $properties;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

/**
 * @deprecated
 */
interface BrokerAwareClassReflectionExtension extends \PHPStan\Reflection\BrokerAwareExtension
{

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

use PHPStan\Broker\Broker;

interface BrokerAwareExtension
{

	public function setBroker(\PHPStan\Broker\Broker $broker);

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

interface ClassConstantReflection extends \PHPStan\Reflection\ClassMemberReflection
{

	public function getName(): string;

	/**
	 * @return mixed
	 */
	public function getValue();

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

class ClassConstantWithVisibilityReflection implements \PHPStan\Reflection\ClassConstantReflection
{

	/** @var \PHPStan\Reflection\ClassReflection */
	private $declaringClass;

	/** @var \ReflectionClassConstant */
	private $reflection;

	public function __construct(
		\PHPStan\Reflection\ClassReflection $declaringClass,
		\ReflectionClassConstant $reflection
	)
	{
		$this->declaringClass = $declaringClass;
		$this->reflection = $reflection;
	}

	public function getName(): string
	{
		return $this->reflection->getName();
	}

	/**
	 * @return mixed
	 */
	public function getValue()
	{
		return $this->reflection->getValue();
	}

	public function getDeclaringClass(): \PHPStan\Reflection\ClassReflection
	{
		return $this->declaringClass;
	}

	public function isStatic(): bool
	{
		return true;
	}

	public function isPrivate(): bool
	{
		return $this->reflection->isPrivate();
	}

	public function isPublic(): bool
	{
		return $this->reflection->isPublic();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

interface ClassMemberReflection
{

	public function getDeclaringClass(): \PHPStan\Reflection\ClassReflection;

	public function isStatic(): bool;

	public function isPrivate(): bool;

	public function isPublic(): bool;

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\Reflection\Php\PhpClassReflectionExtension;
use PHPStan\Reflection\Php\PhpMethodReflection;
use PHPStan\Reflection\Php\PhpPropertyReflection;

class ClassReflection
{

	/** @var \PHPStan\Broker\Broker */
	private $broker;

	/** @var \PHPStan\Reflection\PropertiesClassReflectionExtension[] */
	private $propertiesClassReflectionExtensions;

	/** @var \PHPStan\Reflection\MethodsClassReflectionExtension[] */
	private $methodsClassReflectionExtensions;

	/** @var string */
	private $displayName;

	/** @var \ReflectionClass */
	private $reflection;

	/** @var bool */
	private $anonymous;

	/** @var \PHPStan\Reflection\MethodReflection[] */
	private $methods = [];

	/** @var \PHPStan\Reflection\PropertyReflection[] */
	private $properties = [];

	/** @var \PHPStan\Reflection\ClassConstantReflection[] */
	private $constants;

	/** @var int[]|null */
	private $classHierarchyDistances;

	public function __construct(
		\PHPStan\Broker\Broker $broker,
		array $propertiesClassReflectionExtensions,
		array $methodsClassReflectionExtensions,
		string $displayName,
		\ReflectionClass $reflection,
		bool $anonymous
	)
	{
		$this->broker = $broker;
		$this->propertiesClassReflectionExtensions = $propertiesClassReflectionExtensions;
		$this->methodsClassReflectionExtensions = $methodsClassReflectionExtensions;
		$this->displayName = $displayName;
		$this->reflection = $reflection;
		$this->anonymous = $anonymous;
	}

	public function getNativeReflection(): \ReflectionClass
	{
		return $this->reflection;
	}

	/**
	 * @return string|false
	 */
	public function getFileName()
	{
		$fileName = $this->reflection->getFileName();
		if ($fileName === false) {
			return false;
		}

		if (!file_exists($fileName)) {
			return false;
		}

		return $fileName;
	}

	/**
	 * @return false|\PHPStan\Reflection\ClassReflection
	 */
	public function getParentClass()
	{
		if ($this->reflection->getParentClass() === false) {
			return false;
		}

		return $this->broker->getClass($this->reflection->getParentClass()->getName());
	}

	public function getName(): string
	{
		return $this->reflection->getName();
	}

	public function getDisplayName(): string
	{
		return $this->displayName;
	}

	/**
	 * @return int[]
	 */
	public function getClassHierarchyDistances(): array
	{
		if ($this->classHierarchyDistances === null) {
			$distance = 0;
			$distances = [
				$this->getName() => $distance,
			];
			$currentClassReflection = $this->getNativeReflection();
			while ($currentClassReflection->getParentClass() !== false) {
				$distance++;
				$parentClassName = $currentClassReflection->getParentClass()->getName();
				if (!array_key_exists($parentClassName, $distances)) {
					$distances[$parentClassName] = $distance;
				}
				$currentClassReflection = $currentClassReflection->getParentClass();
			}
			foreach ($this->getNativeReflection()->getInterfaces() as $interface) {
				$distance++;
				if (array_key_exists($interface->getName(), $distances)) {
					continue;
				}

				$distances[$interface->getName()] = $distance;
			}

			$this->classHierarchyDistances = $distances;
		}

		return $this->classHierarchyDistances;
	}

	public function hasProperty(string $propertyName): bool
	{
		foreach ($this->propertiesClassReflectionExtensions as $extension) {
			if ($extension->hasProperty($this, $propertyName)) {
				return true;
			}
		}

		return false;
	}

	public function hasMethod(string $methodName): bool
	{
		foreach ($this->methodsClassReflectionExtensions as $extension) {
			if ($extension->hasMethod($this, $methodName)) {
				return true;
			}
		}

		return false;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		$key = $methodName;
		if ($scope->isInClass()) {
			$key = sprintf('%s-%s', $key, $scope->getClassReflection()->getName());
		}
		if (!isset($this->methods[$key])) {
			foreach ($this->methodsClassReflectionExtensions as $extension) {
				if ($extension->hasMethod($this, $methodName)) {
					$method = $extension->getMethod($this, $methodName);
					if ($scope->canCallMethod($method)) {
						return $this->methods[$key] = $method;
					}
					$this->methods[$key] = $method;
				}
			}
		}

		if (!isset($this->methods[$key])) {
			throw new \PHPStan\Reflection\MissingMethodFromReflectionException($this->getName(), $methodName);
		}

		return $this->methods[$key];
	}

	public function hasNativeMethod(string $methodName): bool
	{
		return $this->getPhpExtension()->hasMethod($this, $methodName);
	}

	public function getNativeMethod(string $methodName): \PHPStan\Reflection\Php\PhpMethodReflection
	{
		if (!$this->hasNativeMethod($methodName)) {
			throw new \PHPStan\Reflection\MissingMethodFromReflectionException($this->getName(), $methodName);
		}
		return $this->getPhpExtension()->getNativeMethod($this, $methodName);
	}

	private function getPhpExtension(): \PHPStan\Reflection\Php\PhpClassReflectionExtension
	{
		$extension = $this->methodsClassReflectionExtensions[0];
		if (!$extension instanceof \PHPStan\Reflection\Php\PhpClassReflectionExtension) {
			throw new \PHPStan\ShouldNotHappenException();
		}

		return $extension;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		$key = $propertyName;
		if ($scope->isInClass()) {
			$key = sprintf('%s-%s', $key, $scope->getClassReflection()->getName());
		}
		if (!isset($this->properties[$key])) {
			foreach ($this->propertiesClassReflectionExtensions as $extension) {
				if ($extension->hasProperty($this, $propertyName)) {
					$property = $extension->getProperty($this, $propertyName);
					if ($scope->canAccessProperty($property)) {
						return $this->properties[$key] = $property;
					}
					$this->properties[$key] = $property;
				}
			}
		}

		if (!isset($this->properties[$key])) {
			throw new \PHPStan\Reflection\MissingPropertyFromReflectionException($this->getName(), $propertyName);
		}

		return $this->properties[$key];
	}

	public function hasNativeProperty(string $propertyName): bool
	{
		return $this->getPhpExtension()->hasProperty($this, $propertyName);
	}

	public function getNativeProperty(string $propertyName): \PHPStan\Reflection\Php\PhpPropertyReflection
	{
		if (!$this->hasNativeProperty($propertyName)) {
			throw new \PHPStan\Reflection\MissingPropertyFromReflectionException($this->getName(), $propertyName);
		}
		return $this->getPhpExtension()->getNativeProperty($this, $propertyName);
	}

	public function isAbstract(): bool
	{
		return $this->reflection->isAbstract();
	}

	public function isInterface(): bool
	{
		return $this->reflection->isInterface();
	}

	public function isTrait(): bool
	{
		return $this->reflection->isTrait();
	}

	public function isAnonymous(): bool
	{
		return $this->anonymous;
	}

	public function isSubclassOf(string $className): bool
	{
		return $this->reflection->isSubclassOf($className);
	}

	/**
	 * @return \PHPStan\Reflection\ClassReflection[]
	 */
	public function getParents(): array
	{
		$parents = [];
		$parent = $this->getParentClass();
		while ($parent !== false) {
			$parents[] = $parent;
			$parent = $parent->getParentClass();
		}

		return $parents;
	}

	/**
	 * @return \PHPStan\Reflection\ClassReflection[]
	 */
	public function getInterfaces(): array
	{
		return array_map(function (\ReflectionClass $interface) {
			return $this->broker->getClass($interface->getName());
		}, $this->getNativeReflection()->getInterfaces());
	}

	/**
	 * @return \PHPStan\Reflection\ClassReflection[]
	 */
	public function getTraits(): array
	{
		return array_map(function (\ReflectionClass $trait) {
			return $this->broker->getClass($trait->getName());
		}, $this->getNativeReflection()->getTraits());
	}

	/**
	 * @return string[]
	 */
	public function getParentClassesNames(): array
	{
		$parentNames = [];
		$currentClassReflection = $this;
		while ($currentClassReflection->getParentClass() !== false) {
			$parentNames[] = $currentClassReflection->getParentClass()->getName();
			$currentClassReflection = $currentClassReflection->getParentClass();
		}

		return $parentNames;
	}

	public function hasConstant(string $name): bool
	{
		return $this->getNativeReflection()->hasConstant($name);
	}

	public function getConstant(string $name): \PHPStan\Reflection\ClassConstantReflection
	{
		if (!isset($this->constants[$name])) {
			if (PHP_VERSION_ID < 70100) {
				$this->constants[$name] = new \PHPStan\Reflection\ObsoleteClassConstantReflection(
					$this,
					$name,
					$this->getNativeReflection()->getConstant($name)
				);
			} else {
				$reflectionConstant = $this->getNativeReflection()->getReflectionConstant($name);
				$this->constants[$name] = new \PHPStan\Reflection\ClassConstantWithVisibilityReflection(
					$this->broker->getClass($reflectionConstant->getDeclaringClass()->getName()),
					$reflectionConstant
				);
			}
		}
		return $this->constants[$name];
	}

	public function hasTraitUse(string $traitName): bool
	{
		return in_array($traitName, $this->getTraitNames(), true);
	}

	private function getTraitNames(): array
	{
		$class = $this->reflection;
		$traitNames = $class->getTraitNames();
		while ($class->getParentClass() !== false) {
			$traitNames = array_values(array_unique(array_merge($traitNames, $class->getParentClass()->getTraitNames())));
			$class = $class->getParentClass();
		}

		return $traitNames;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;
use PHPStan\Cache\Cache;
use PHPStan\Parser\FunctionCallStatementFinder;
use PHPStan\Parser\Parser;
use PHPStan\Reflection\Php\DummyParameter;
use PHPStan\Reflection\Php\PhpParameterReflection;
use PHPStan\Type\ArrayType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectWithoutClassType;
use PHPStan\Type\StringType;
use PHPStan\Type\TrueOrFalseBooleanType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\TypehintHelper;

class FunctionReflection implements \PHPStan\Reflection\ParametersAcceptorWithPhpDocs
{

	/** @var \ReflectionFunction */
	private $reflection;

	/** @var \PHPStan\Parser\Parser */
	private $parser;

	/** @var \PHPStan\Parser\FunctionCallStatementFinder */
	private $functionCallStatementFinder;

	/** @var \PHPStan\Cache\Cache */
	private $cache;

	/** @var \PHPStan\Type\Type[] */
	private $phpDocParameterTypes;

	/** @var \PHPStan\Type\Type|null */
	private $phpDocReturnType;

	/** @var \PHPStan\Reflection\ParameterReflection[] */
	private $parameters;

	/** @var \PHPStan\Type\Type */
	private $returnType;

	/** @var \PHPStan\Type\Type */
	private $nativeReturnType;

	public function __construct(
		\ReflectionFunction $reflection,
		\PHPStan\Parser\Parser $parser,
		\PHPStan\Parser\FunctionCallStatementFinder $functionCallStatementFinder,
		\PHPStan\Cache\Cache $cache,
		array $phpDocParameterTypes,
		\PHPStan\Type\Type $phpDocReturnType = null
	)
	{
		$this->reflection = $reflection;
		$this->parser = $parser;
		$this->functionCallStatementFinder = $functionCallStatementFinder;
		$this->cache = $cache;
		$this->phpDocParameterTypes = $phpDocParameterTypes;
		$this->phpDocReturnType = $phpDocReturnType;
	}

	public function getNativeReflection(): \ReflectionFunction
	{
		return $this->reflection;
	}

	public function getName(): string
	{
		return $this->reflection->getName();
	}

	/**
	 * @return \PHPStan\Reflection\ParameterReflection[]
	 */
	public function getParameters(): array
	{
		if ($this->parameters === null) {
			$this->parameters = array_map(function (\ReflectionParameter $reflection) {
				return new \PHPStan\Reflection\Php\PhpParameterReflection(
					$reflection,
					isset($this->phpDocParameterTypes[$reflection->getName()]) ? $this->phpDocParameterTypes[$reflection->getName()] : null
				);
			}, $this->reflection->getParameters());
			if (
				$this->reflection->getName() === 'array_unique'
				&& count($this->parameters) === 1
			) {
				// PHP bug #70960
				$this->parameters[] = new \PHPStan\Reflection\Php\DummyParameter(
					'sort_flags',
					new \PHPStan\Type\IntegerType(),
					true
				);
			}
			if (
				$this->reflection->getName() === 'fputcsv'
				&& count($this->parameters) === 4
			) {
				$this->parameters[] = new \PHPStan\Reflection\Php\DummyParameter(
					'escape_char',
					new \PHPStan\Type\StringType(),
					true
				);
			}
			if (
				$this->reflection->getName() === 'unpack'
				&& PHP_VERSION_ID >= 70101
			) {
				$this->parameters[2] = new \PHPStan\Reflection\Php\DummyParameter(
					'offset',
					new \PHPStan\Type\IntegerType(),
					true
				);
			}
			if (
				$this->reflection->getName() === 'imagepng'
				&& count($this->parameters) === 2
			) {
				$this->parameters[] = new \PHPStan\Reflection\Php\DummyParameter(
					'quality',
					new \PHPStan\Type\IntegerType(),
					true
				);
				$this->parameters[] = new \PHPStan\Reflection\Php\DummyParameter(
					'filters',
					new \PHPStan\Type\IntegerType(),
					true
				);
			}

			if (
				$this->reflection->getName() === 'session_start'
				&& count($this->parameters) === 0
			) {
				$this->parameters[] = new \PHPStan\Reflection\Php\DummyParameter(
					'options',
					new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType()),
					true
				);
			}

			if ($this->reflection->getName() === 'locale_get_display_language') {
				$this->parameters[1] = new \PHPStan\Reflection\Php\DummyParameter(
					'in_locale',
					new \PHPStan\Type\StringType(),
					true
				);
			}

			if (
				$this->reflection->getName() === 'imagewebp'
				&& count($this->parameters) === 2
			) {
				$this->parameters[] = new \PHPStan\Reflection\Php\DummyParameter(
					'quality',
					new \PHPStan\Type\IntegerType(),
					true
				);
			}

			if (
				$this->reflection->getName() === 'setproctitle'
				&& count($this->parameters) === 0
			) {
				$this->parameters[] = new \PHPStan\Reflection\Php\DummyParameter(
					'title',
					new \PHPStan\Type\StringType(),
					false
				);
			}

			if (
				$this->reflection->getName() === 'get_class'
			) {
				$this->parameters = [
					new \PHPStan\Reflection\Php\DummyParameter(
						'object',
						new \PHPStan\Type\ObjectWithoutClassType(),
						true
					),
				];
			}

			if (
				$this->reflection->getName() === 'mysqli_fetch_all'
				&& count($this->parameters) === 1
			) {
				$this->parameters[] = new \PHPStan\Reflection\Php\DummyParameter(
					'resulttype',
					new \PHPStan\Type\IntegerType(),
					true
				);
			}

			if (
				$this->reflection->getName() === 'openssl_open'
				&& count($this->parameters) === 5
			) {
				$this->parameters[4] = new \PHPStan\Reflection\Php\DummyParameter(
					'method',
					new \PHPStan\Type\StringType(),
					true
				);
				$this->parameters[5] = new \PHPStan\Reflection\Php\DummyParameter(
					'iv',
					new \PHPStan\Type\StringType(),
					true
				);
			}

			if (
				$this->reflection->getName() === 'openssl_x509_parse'
			) {
				$this->parameters[1] = new \PHPStan\Reflection\Php\DummyParameter(
					'shortnames',
					new \PHPStan\Type\TrueOrFalseBooleanType(),
					true
				);
			}

			if (
				$this->reflection->getName() === 'get_defined_functions'
				&& count($this->parameters) > 0
				&& !$this->parameters[0]->isOptional()
			) {
				// PHP bug #75799
				$this->parameters[0] = new \PHPStan\Reflection\Php\DummyParameter(
					'exclude_disabled',
					new \PHPStan\Type\TrueOrFalseBooleanType(),
					true
				);
			}
		}

		return $this->parameters;
	}

	public function isVariadic(): bool
	{
		$isNativelyVariadic = $this->reflection->isVariadic();
		if (!$isNativelyVariadic && $this->reflection->getFileName() !== false) {
			$key = sprintf('variadic-function-%s-v0', $this->reflection->getName());
			$cachedResult = $this->cache->load($key);
			if ($cachedResult === null) {
				$nodes = $this->parser->parseFile($this->reflection->getFileName());
				$result = $this->callsFuncGetArgs($nodes);
				$this->cache->save($key, $result);
				return $result;
			}

			return $cachedResult;
		}

		return $isNativelyVariadic;
	}

	/**
	 * @param mixed $nodes
	 * @return bool
	 */
	private function callsFuncGetArgs($nodes): bool
	{
		foreach ($nodes as $node) {
			if (is_array($node)) {
				if ($this->callsFuncGetArgs($node)) {
					return true;
				}
			}

			if (!($node instanceof \PhpParser\Node)) {
				continue;
			}

			if ($node instanceof \PhpParser\Node\Stmt\Function_) {
				$functionName = (string) $node->namespacedName;

				if ($functionName === $this->reflection->getName()) {
					return $this->functionCallStatementFinder->findFunctionCallInStatements(self::VARIADIC_FUNCTIONS, $node->getStmts()) !== null;
				}

				continue;
			}

			if ($this->callsFuncGetArgs($node)) {
				return true;
			}
		}

		return false;
	}

	public function getReturnType(): \PHPStan\Type\Type
	{
		if ($this->returnType === null) {
			if ($this->reflection->getName() === 'count') {
				return $this->returnType = new \PHPStan\Type\IntegerType();
			}
			$returnType = $this->reflection->getReturnType();
			$phpDocReturnType = $this->phpDocReturnType;
			if (
				$returnType !== null
				&& $phpDocReturnType !== null
				&& $returnType->allowsNull() !== \PHPStan\Type\TypeCombinator::containsNull($phpDocReturnType)
			) {
				$phpDocReturnType = null;
			}
			$this->returnType = \PHPStan\Type\TypehintHelper::decideTypeFromReflection(
				$returnType,
				$phpDocReturnType
			);
		}

		return $this->returnType;
	}

	public function getPhpDocReturnType(): \PHPStan\Type\Type
	{
		if ($this->phpDocReturnType !== null) {
			return $this->phpDocReturnType;
		}

		return new \PHPStan\Type\MixedType();
	}

	public function getNativeReturnType(): \PHPStan\Type\Type
	{
		if ($this->nativeReturnType === null) {
			$this->nativeReturnType = \PHPStan\Type\TypehintHelper::decideTypeFromReflection($this->reflection->getReturnType());
		}

		return $this->nativeReturnType;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

use PHPStan\Type\Type;

interface FunctionReflectionFactory
{

	public function create(
		\ReflectionFunction $reflection,
		array $phpDocParameterTypes,
		\PHPStan\Type\Type $phpDocReturnType = null
	): \PHPStan\Reflection\FunctionReflection;

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

interface MethodReflection extends \PHPStan\Reflection\ParametersAcceptor, \PHPStan\Reflection\ClassMemberReflection
{

	public function getPrototype(): self;

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

interface MethodsClassReflectionExtension
{

	public function hasMethod(\PHPStan\Reflection\ClassReflection $classReflection, string $methodName): bool;

	public function getMethod(\PHPStan\Reflection\ClassReflection $classReflection, string $methodName): \PHPStan\Reflection\MethodReflection;

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

class MissingMethodFromReflectionException extends \PHPStan\AnalysedCodeException
{

	public function __construct(string $className, string $methodName)
	{
		parent::__construct(
			sprintf(
				'Method %s() was not found in reflection of class %s - probably the wrong version of class is autoloaded.',
				$methodName,
				$className
			)
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

class MissingPropertyFromReflectionException extends \PHPStan\AnalysedCodeException
{

	public function __construct(string $className, string $propertyName)
	{
		parent::__construct(
			sprintf(
				'Property $%s was not found in reflection of class %s - probably the wrong version of class is autoloaded.',
				$propertyName,
				$className
			)
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

class ObsoleteClassConstantReflection implements \PHPStan\Reflection\ClassConstantReflection
{

	/** @var \PHPStan\Reflection\ClassReflection */
	private $declaringClass;

	/** @var string */
	private $name;

	/** @var mixed */
	private $value;

	/**
	 * @param \PHPStan\Reflection\ClassReflection $declaringClass
	 * @param string $name
	 * @param mixed $value
	 */
	public function __construct(
		\PHPStan\Reflection\ClassReflection $declaringClass,
		string $name,
		$value
	)
	{
		$this->declaringClass = $declaringClass;
		$this->name = $name;
		$this->value = $value;
	}

	public function getName(): string
	{
		return $this->name;
	}

	/**
	 * @return mixed
	 */
	public function getValue()
	{
		return $this->value;
	}

	public function getDeclaringClass(): \PHPStan\Reflection\ClassReflection
	{
		return $this->declaringClass;
	}

	public function isStatic(): bool
	{
		return true;
	}

	public function isPrivate(): bool
	{
		return false;
	}

	public function isPublic(): bool
	{
		return true;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

use PHPStan\Type\Type;

interface ParameterReflection
{

	public function getName(): string;

	public function isOptional(): bool;

	public function getType(): \PHPStan\Type\Type;

	public function isPassedByReference(): bool;

	public function isVariadic(): bool;

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

use PHPStan\Type\Type;

interface ParametersAcceptor
{

	const VARIADIC_FUNCTIONS = [
		'func_get_args',
		'func_get_arg',
		'func_num_args',
	];

	public function getName(): string;

	/**
	 * @return \PHPStan\Reflection\ParameterReflection[]
	 */
	public function getParameters(): array;

	public function isVariadic(): bool;

	public function getReturnType(): \PHPStan\Type\Type;

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

use PHPStan\Type\Type;

interface ParametersAcceptorWithPhpDocs extends \PHPStan\Reflection\ParametersAcceptor
{

	/**
	 * @return \PHPStan\Reflection\Php\PhpParameterReflection[]
	 */
	public function getParameters(): array;

	public function getPhpDocReturnType(): \PHPStan\Type\Type;

	public function getNativeReturnType(): \PHPStan\Type\Type;

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\Php;

use PHPStan\Reflection\ParameterReflection;
use PHPStan\Type\Type;

class DummyParameter implements \PHPStan\Reflection\ParameterReflection
{

	/** @var string */
	private $name;

	/** @var \PHPStan\Type\Type  */
	private $type;

	/** @var bool */
	private $optional;

	/** @var bool */
	private $passedByReference;

	/** @var bool */
	private $variadic;

	public function __construct(string $name, \PHPStan\Type\Type $type, bool $optional, bool $passedByReference = false, bool $variadic = false)
	{
		$this->name = $name;
		$this->type = $type;
		$this->optional = $optional;
		$this->passedByReference = $passedByReference;
		$this->variadic = $variadic;
	}

	public function getName(): string
	{
		return $this->name;
	}

	public function isOptional(): bool
	{
		return $this->optional;
	}

	public function getType(): \PHPStan\Type\Type
	{
		return $this->type;
	}

	public function isPassedByReference(): bool
	{
		return $this->passedByReference;
	}

	public function isVariadic(): bool
	{
		return $this->variadic;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\Php;

use PHPStan\Broker\Broker;
use PHPStan\PhpDoc\PhpDocBlock;
use PHPStan\PhpDoc\Tag\ParamTag;
use PHPStan\Reflection\Annotations\AnnotationsMethodsClassReflectionExtension;
use PHPStan\Reflection\Annotations\AnnotationsPropertiesClassReflectionExtension;
use PHPStan\Reflection\BrokerAwareExtension;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\MethodsClassReflectionExtension;
use PHPStan\Reflection\PropertiesClassReflectionExtension;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\Type\FileTypeMapper;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;

class PhpClassReflectionExtension
	implements \PHPStan\Reflection\PropertiesClassReflectionExtension, \PHPStan\Reflection\MethodsClassReflectionExtension, \PHPStan\Reflection\BrokerAwareExtension
{

	/** @var \PHPStan\Reflection\Php\PhpMethodReflectionFactory */
	private $methodReflectionFactory;

	/** @var \PHPStan\Type\FileTypeMapper */
	private $fileTypeMapper;

	/** @var \PHPStan\Reflection\Annotations\AnnotationsMethodsClassReflectionExtension */
	private $annotationsMethodsClassReflectionExtension;

	/** @var \PHPStan\Reflection\Annotations\AnnotationsPropertiesClassReflectionExtension */
	private $annotationsPropertiesClassReflectionExtension;

	/** @var \PHPStan\Broker\Broker */
	private $broker;

	/** @var \PHPStan\Reflection\PropertyReflection[][] */
	private $propertiesIncludingAnnotations = [];

	/** @var \PHPStan\Reflection\Php\PhpPropertyReflection[][] */
	private $nativeProperties;

	/** @var \PHPStan\Reflection\MethodReflection[][] */
	private $methodsIncludingAnnotations = [];

	/** @var \PHPStan\Reflection\Php\PhpMethodReflection[][] */
	private $nativeMethods = [];

	public function __construct(
		\PHPStan\Reflection\Php\PhpMethodReflectionFactory $methodReflectionFactory,
		\PHPStan\Type\FileTypeMapper $fileTypeMapper,
		\PHPStan\Reflection\Annotations\AnnotationsMethodsClassReflectionExtension $annotationsMethodsClassReflectionExtension,
		\PHPStan\Reflection\Annotations\AnnotationsPropertiesClassReflectionExtension $annotationsPropertiesClassReflectionExtension
	)
	{
		$this->methodReflectionFactory = $methodReflectionFactory;
		$this->fileTypeMapper = $fileTypeMapper;
		$this->annotationsMethodsClassReflectionExtension = $annotationsMethodsClassReflectionExtension;
		$this->annotationsPropertiesClassReflectionExtension = $annotationsPropertiesClassReflectionExtension;
	}

	public function setBroker(\PHPStan\Broker\Broker $broker)
	{
		$this->broker = $broker;
	}

	public function hasProperty(\PHPStan\Reflection\ClassReflection $classReflection, string $propertyName): bool
	{
		return $classReflection->getNativeReflection()->hasProperty($propertyName);
	}

	public function getProperty(\PHPStan\Reflection\ClassReflection $classReflection, string $propertyName): \PHPStan\Reflection\PropertyReflection
	{
		if (!isset($this->propertiesIncludingAnnotations[$classReflection->getName()][$propertyName])) {
			$this->propertiesIncludingAnnotations[$classReflection->getName()][$propertyName] = $this->createProperty($classReflection, $propertyName, true);
		}

		return $this->propertiesIncludingAnnotations[$classReflection->getName()][$propertyName];
	}

	public function getNativeProperty(\PHPStan\Reflection\ClassReflection $classReflection, string $propertyName): \PHPStan\Reflection\Php\PhpPropertyReflection
	{
		if (!isset($this->nativeProperties[$classReflection->getName()][$propertyName])) {
			/** @var \PHPStan\Reflection\Php\PhpPropertyReflection $property */
			$property = $this->createProperty($classReflection, $propertyName, false);
			$this->nativeProperties[$classReflection->getName()][$propertyName] = $property;
		}

		return $this->nativeProperties[$classReflection->getName()][$propertyName];
	}

	private function createProperty(
		\PHPStan\Reflection\ClassReflection $classReflection,
		string $propertyName,
		bool $includingAnnotations
	): \PHPStan\Reflection\PropertyReflection
	{
		$propertyReflection = $classReflection->getNativeReflection()->getProperty($propertyName);
		$propertyName = $propertyReflection->getName();
		$declaringClassReflection = $this->broker->getClass($propertyReflection->getDeclaringClass()->getName());

		if ($includingAnnotations && $this->annotationsPropertiesClassReflectionExtension->hasProperty($classReflection, $propertyName)) {
			$hierarchyDistances = $classReflection->getClassHierarchyDistances();
			$annotationProperty = $this->annotationsPropertiesClassReflectionExtension->getProperty($classReflection, $propertyName);
			if (!isset($hierarchyDistances[$annotationProperty->getDeclaringClass()->getName()])) {
				throw new \PHPStan\ShouldNotHappenException();
			}
			if (!isset($hierarchyDistances[$propertyReflection->getDeclaringClass()->getName()])) {
				throw new \PHPStan\ShouldNotHappenException();
			}

			if ($hierarchyDistances[$annotationProperty->getDeclaringClass()->getName()] < $hierarchyDistances[$propertyReflection->getDeclaringClass()->getName()]) {
				return $annotationProperty;
			}
		}
		if ($propertyReflection->getDocComment() === false) {
			$type = new \PHPStan\Type\MixedType();
		} elseif (!$classReflection->isAnonymous() && !$declaringClassReflection->isAnonymous() && $declaringClassReflection->getFileName() !== false) {
			$phpDocBlock = \PHPStan\PhpDoc\PhpDocBlock::resolvePhpDocBlockForProperty(
				$this->broker,
				$propertyReflection->getDocComment(),
				$declaringClassReflection->getName(),
				$propertyName,
				$declaringClassReflection->getFileName()
			);

			$resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc(
				$phpDocBlock->getFile(),
				$phpDocBlock->getClass(),
				$phpDocBlock->getDocComment()
			);
			$varTags = $resolvedPhpDoc->getVarTags();
			if (isset($varTags[0]) && count($varTags) === 1) {
				$type = $varTags[0]->getType();
			} elseif (isset($varTags[$propertyName])) {
				$type = $varTags[$propertyName]->getType();
			} else {
				$type = new \PHPStan\Type\MixedType();
			}
		} else {
			$type = new \PHPStan\Type\MixedType();
		}

		return new \PHPStan\Reflection\Php\PhpPropertyReflection(
			$declaringClassReflection,
			$type,
			$propertyReflection
		);
	}

	public function hasMethod(\PHPStan\Reflection\ClassReflection $classReflection, string $methodName): bool
	{
		return $classReflection->getNativeReflection()->hasMethod($methodName);
	}

	public function getMethod(\PHPStan\Reflection\ClassReflection $classReflection, string $methodName): \PHPStan\Reflection\MethodReflection
	{
		if (isset($this->methodsIncludingAnnotations[$classReflection->getName()][$methodName])) {
			return $this->methodsIncludingAnnotations[$classReflection->getName()][$methodName];
		}

		$nativeMethodReflection = $classReflection->getNativeReflection()->getMethod($methodName);
		if (!isset($this->methodsIncludingAnnotations[$classReflection->getName()][$nativeMethodReflection->getName()])) {
			/** @var \PHPStan\Reflection\Php\PhpMethodReflection $method */
			$method = $this->createMethod($classReflection, $nativeMethodReflection, true);
			$this->methodsIncludingAnnotations[$classReflection->getName()][$nativeMethodReflection->getName()] = $method;
			if ($nativeMethodReflection->getName() !== $methodName) {
				$this->methodsIncludingAnnotations[$classReflection->getName()][$methodName] = $method;
			}
		}

		return $this->methodsIncludingAnnotations[$classReflection->getName()][$nativeMethodReflection->getName()];
	}

	public function getNativeMethod(\PHPStan\Reflection\ClassReflection $classReflection, string $methodName): \PHPStan\Reflection\Php\PhpMethodReflection
	{
		if (isset($this->nativeMethods[$classReflection->getName()][$methodName])) {
			return $this->nativeMethods[$classReflection->getName()][$methodName];
		}

		$nativeMethodReflection = $classReflection->getNativeReflection()->getMethod($methodName);
		if (!isset($this->nativeMethods[$classReflection->getName()][$nativeMethodReflection->getName()])) {
			/** @var \PHPStan\Reflection\Php\PhpMethodReflection $method */
			$method = $this->createMethod($classReflection, $nativeMethodReflection, false);
			$this->nativeMethods[$classReflection->getName()][$nativeMethodReflection->getName()] = $method;
		}

		return $this->nativeMethods[$classReflection->getName()][$nativeMethodReflection->getName()];
	}

	private function createMethod(
		\PHPStan\Reflection\ClassReflection $classReflection,
		\ReflectionMethod $methodReflection,
		bool $includingAnnotations
	): \PHPStan\Reflection\MethodReflection
	{
		if ($includingAnnotations && $this->annotationsMethodsClassReflectionExtension->hasMethod($classReflection, $methodReflection->getName())) {
			$hierarchyDistances = $classReflection->getClassHierarchyDistances();
			$annotationMethod = $this->annotationsMethodsClassReflectionExtension->getMethod($classReflection, $methodReflection->getName());
			if (!isset($hierarchyDistances[$annotationMethod->getDeclaringClass()->getName()])) {
				throw new \PHPStan\ShouldNotHappenException();
			}
			if (!isset($hierarchyDistances[$methodReflection->getDeclaringClass()->getName()])) {
				throw new \PHPStan\ShouldNotHappenException();
			}

			if ($hierarchyDistances[$annotationMethod->getDeclaringClass()->getName()] < $hierarchyDistances[$methodReflection->getDeclaringClass()->getName()]) {
				return $annotationMethod;
			}
		}
		$declaringClass = $this->broker->getClass($methodReflection->getDeclaringClass()->getName());

		$phpDocParameterTypes = [];
		$phpDocReturnType = null;
		if (!$classReflection->isAnonymous() && !$declaringClass->isAnonymous() && $declaringClass->getFileName() !== false) {
			if ($methodReflection->getDocComment() !== false) {
				$phpDocBlock = \PHPStan\PhpDoc\PhpDocBlock::resolvePhpDocBlockForMethod(
					$this->broker,
					$methodReflection->getDocComment(),
					$declaringClass->getName(),
					$methodReflection->getName(),
					$declaringClass->getFileName()
				);

				$resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc(
					$phpDocBlock->getFile(),
					$phpDocBlock->getClass(),
					$phpDocBlock->getDocComment()
				);
				$phpDocParameterTypes = array_map(function (\PHPStan\PhpDoc\Tag\ParamTag $tag): \PHPStan\Type\Type {
					return $tag->getType();
				}, $resolvedPhpDoc->getParamTags());
				$phpDocReturnType = $resolvedPhpDoc->getReturnTag() !== null ? $resolvedPhpDoc->getReturnTag()->getType() : null;
			}
		}

		return $this->methodReflectionFactory->create(
			$declaringClass,
			$methodReflection,
			$phpDocParameterTypes,
			$phpDocReturnType
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\Php;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\TypehintHelper;

class PhpFunctionFromParserNodeReflection implements \PHPStan\Reflection\ParametersAcceptor
{

	/** @var \PhpParser\Node\FunctionLike */
	private $functionLike;

	/** @var \PHPStan\Type\Type[] */
	private $realParameterTypes;

	/** @var \PHPStan\Type\Type[] */
	private $phpDocParameterTypes;

	/** @var bool */
	private $realReturnTypePresent;

	/** @var \PHPStan\Type\Type */
	private $realReturnType;

	/** @var \PHPStan\Type\Type|null */
	private $phpDocReturnType;

	/** @var bool */
	private $isVariadic;

	/** @var \PHPStan\Reflection\Php\PhpParameterFromParserNodeReflection[] */
	private $parameters;

	/** @var \PHPStan\Type\Type */
	private $returnType;

	public function __construct(
		\PhpParser\Node\FunctionLike $functionLike,
		array $realParameterTypes,
		array $phpDocParameterTypes,
		bool $realReturnTypePresent,
		\PHPStan\Type\Type $realReturnType,
		\PHPStan\Type\Type $phpDocReturnType = null
	)
	{
		$this->functionLike = $functionLike;
		$this->realParameterTypes = $realParameterTypes;
		$this->phpDocParameterTypes = $phpDocParameterTypes;
		$this->realReturnTypePresent = $realReturnTypePresent;
		$this->realReturnType = $realReturnType;
		$this->phpDocReturnType = $phpDocReturnType;
	}

	protected function getFunctionLike(): \PhpParser\Node\FunctionLike
	{
		return $this->functionLike;
	}

	public function getName(): string
	{
		if ($this->functionLike instanceof \PhpParser\Node\Stmt\ClassMethod) {
			return $this->functionLike->name;
		}

		return (string) $this->functionLike->namespacedName;
	}

	/**
	 * @return \PHPStan\Reflection\ParameterReflection[]
	 */
	public function getParameters(): array
	{
		if ($this->parameters === null) {
			$parameters = [];
			$isOptional = true;
			foreach (array_reverse($this->functionLike->getParams()) as $parameter) {
				if (!$isOptional || $parameter->default === null) {
					$isOptional = false;
				}

				$parameters[] = new \PHPStan\Reflection\Php\PhpParameterFromParserNodeReflection(
					$parameter->name,
					$isOptional,
					$this->realParameterTypes[$parameter->name],
					isset($this->phpDocParameterTypes[$parameter->name]) ? $this->phpDocParameterTypes[$parameter->name] : null,
					$parameter->byRef,
					$parameter->default,
					$parameter->variadic
				);
			}

			$this->parameters = array_reverse($parameters);
		}

		return $this->parameters;
	}

	public function isVariadic(): bool
	{
		if ($this->isVariadic === null) {
			$isVariadic = false;
			foreach ($this->functionLike->getParams() as $parameter) {
				if ($parameter->variadic) {
					$isVariadic = true;
					break;
				}
			}

			$this->isVariadic = $isVariadic;
		}

		return $this->isVariadic;
	}

	public function getReturnType(): \PHPStan\Type\Type
	{
		if ($this->returnType === null) {
			$phpDocReturnType = $this->phpDocReturnType;
			if (
				$this->realReturnTypePresent
				&& $phpDocReturnType !== null
				&& \PHPStan\Type\TypeCombinator::containsNull($this->realReturnType) !== \PHPStan\Type\TypeCombinator::containsNull($phpDocReturnType)
			) {
				$phpDocReturnType = null;
			}
			$this->returnType = \PHPStan\Type\TypehintHelper::decideType($this->realReturnType, $phpDocReturnType);
		}

		return $this->returnType;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\Php;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Type\Type;
use PHPStan\Type\VoidType;

class PhpMethodFromParserNodeReflection extends \PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection implements \PHPStan\Reflection\MethodReflection
{

	/** @var \PHPStan\Reflection\ClassReflection */
	private $declaringClass;

	public function __construct(
		\PHPStan\Reflection\ClassReflection $declaringClass,
		\PhpParser\Node\Stmt\ClassMethod $classMethod,
		array $realParameterTypes,
		array $phpDocParameterTypes,
		bool $realReturnTypePresent,
		\PHPStan\Type\Type $realReturnType,
		\PHPStan\Type\Type $phpDocReturnType = null
	)
	{
		parent::__construct(
			$classMethod,
			$realParameterTypes,
			$phpDocParameterTypes,
			$realReturnTypePresent,
			$realReturnType,
			$phpDocReturnType
		);
		$this->declaringClass = $declaringClass;
	}

	public function getDeclaringClass(): \PHPStan\Reflection\ClassReflection
	{
		return $this->declaringClass;
	}

	public function getPrototype(): \PHPStan\Reflection\MethodReflection
	{
		return $this->declaringClass->getNativeMethod($this->getClassMethod()->name)->getPrototype();
	}

	private function getClassMethod(): \PhpParser\Node\Stmt\ClassMethod
	{
		/** @var \PhpParser\Node\Stmt\ClassMethod $functionLike */
		$functionLike = $this->getFunctionLike();
		return $functionLike;
	}

	public function isStatic(): bool
	{
		return $this->getClassMethod()->isStatic();
	}

	public function isPrivate(): bool
	{
		return $this->getClassMethod()->isPrivate();
	}

	public function isPublic(): bool
	{
		return $this->getClassMethod()->isPublic();
	}

	public function getReturnType(): \PHPStan\Type\Type
	{
		if ($this->getName() === '__construct') {
			return new \PHPStan\Type\VoidType();
		}

		return parent::getReturnType();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\Php;
use PHPStan\Broker\Broker;
use PHPStan\Cache\Cache;
use PHPStan\Parser\FunctionCallStatementFinder;
use PHPStan\Parser\Parser;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParametersAcceptor;
use PHPStan\Reflection\ParametersAcceptorWithPhpDocs;
use PHPStan\Type\ArrayType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\TypehintHelper;
use PHPStan\Type\VoidType;

class PhpMethodReflection implements \PHPStan\Reflection\MethodReflection, \PHPStan\Reflection\ParametersAcceptorWithPhpDocs
{

	/** @var \PHPStan\Reflection\ClassReflection */
	private $declaringClass;

	/** @var \ReflectionMethod */
	private $reflection;

	/** @var \PHPStan\Broker\Broker */
	private $broker;

	/** @var \PHPStan\Parser\Parser */
	private $parser;

	/** @var \PHPStan\Parser\FunctionCallStatementFinder */
	private $functionCallStatementFinder;

	/** @var \PHPStan\Cache\Cache */
	private $cache;

	/** @var \PHPStan\Type\Type[] */
	private $phpDocParameterTypes;

	/** @var \PHPStan\Type\Type|null */
	private $phpDocReturnType;

	/** @var \PHPStan\Reflection\ParameterReflection[] */
	private $parameters;

	/** @var \PHPStan\Type\Type */
	private $returnType;

	/** @var \PHPStan\Type\Type */
	private $nativeReturnType;

	public function __construct(
		\PHPStan\Reflection\ClassReflection $declaringClass,
		\ReflectionMethod $reflection,
		\PHPStan\Broker\Broker $broker,
		\PHPStan\Parser\Parser $parser,
		\PHPStan\Parser\FunctionCallStatementFinder $functionCallStatementFinder,
		\PHPStan\Cache\Cache $cache,
		array $phpDocParameterTypes,
		\PHPStan\Type\Type $phpDocReturnType = null
	)
	{
		$this->declaringClass = $declaringClass;
		$this->reflection = $reflection;
		$this->broker = $broker;
		$this->parser = $parser;
		$this->functionCallStatementFinder = $functionCallStatementFinder;
		$this->cache = $cache;
		$this->phpDocParameterTypes = $phpDocParameterTypes;
		$this->phpDocReturnType = $phpDocReturnType;
	}

	public function getDeclaringClass(): \PHPStan\Reflection\ClassReflection
	{
		return $this->declaringClass;
	}

	/**
	 * @return string|false
	 */
	public function getDocComment()
	{
		return $this->reflection->getDocComment();
	}

	public function getPrototype(): \PHPStan\Reflection\MethodReflection
	{
		try {
			$prototypeReflection = $this->reflection->getPrototype();
			$prototypeDeclaringClass = $this->broker->getClassFromReflection(
				$prototypeReflection->getDeclaringClass(),
				$prototypeReflection->getDeclaringClass()->getName(),
				$prototypeReflection->getDeclaringClass()->isAnonymous()
			);

			return new self(
				$prototypeDeclaringClass,
				$prototypeReflection,
				$this->broker,
				$this->parser,
				$this->functionCallStatementFinder,
				$this->cache,
				$this->phpDocParameterTypes,
				$this->phpDocReturnType
			);
		} catch (\ReflectionException $e) {
			return $this;
		}
	}

	public function isStatic(): bool
	{
		return $this->reflection->isStatic();
	}

	public function getName(): string
	{
		$name = $this->reflection->getName();
		$lowercaseName = strtolower($name);
		if ($lowercaseName === $name) {
			// fix for https://bugs.php.net/bug.php?id=74939
			foreach ($this->getDeclaringClass()->getNativeReflection()->getTraitAliases() as $traitTarget) {
				$correctName = $this->getMethodNameWithCorrectCase($name, $traitTarget);
				if ($correctName !== null) {
					$name = $correctName;
					break;
				}
			}
		}

		return $name;
	}

	/**
	 * @param string $lowercaseMethodName
	 * @param string $traitTarget
	 * @return string|null
	 */
	private function getMethodNameWithCorrectCase(string $lowercaseMethodName, string $traitTarget)
	{
		list ($trait, $method) = explode('::', $traitTarget);
		$traitReflection = $this->broker->getClass($trait)->getNativeReflection();
		foreach ($traitReflection->getTraitAliases() as $methodAlias => $traitTarget) {
			if ($lowercaseMethodName === strtolower($methodAlias)) {
				return $methodAlias;
			}

			$correctName = $this->getMethodNameWithCorrectCase($lowercaseMethodName, $traitTarget);
			if ($correctName !== null) {
				return $correctName;
			}
		}

		return null;
	}

	/**
	 * @return \PHPStan\Reflection\ParameterReflection[]
	 */
	public function getParameters(): array
	{
		if ($this->parameters === null) {
			$this->parameters = array_map(function (\ReflectionParameter $reflection) {
				return new \PHPStan\Reflection\Php\PhpParameterReflection(
					$reflection,
					isset($this->phpDocParameterTypes[$reflection->getName()]) ? $this->phpDocParameterTypes[$reflection->getName()] : null
				);
			}, $this->reflection->getParameters());

			if (
				$this->reflection->getName() === '__construct'
				&& $this->declaringClass->getName() === 'ArrayObject'
				&& count($this->parameters) === 1
			) {
				// PHP bug #71077
				$this->parameters[] = new \PHPStan\Reflection\Php\DummyParameter(
					'flags',
					new \PHPStan\Type\IntegerType(),
					true
				);
				$this->parameters[] = new \PHPStan\Reflection\Php\DummyParameter(
					'iterator_class',
					new \PHPStan\Type\StringType(),
					true
				);
			}

			if (
				$this->declaringClass->getName() === 'ReflectionMethod'
				&& $this->reflection->getName() === 'invoke'
				&& !$this->parameters[1]->isOptional()
			) {
				// PHP bug #71416
				$this->parameters[1] = new \PHPStan\Reflection\Php\DummyParameter(
					'parameter',
					new \PHPStan\Type\MixedType(),
					true,
					false,
					true
				);
			}

			if (
				$this->declaringClass->getName() === 'PDO'
				&& $this->reflection->getName() === 'query'
				&& count($this->parameters) < 4
			) {
				$this->parameters[] = new \PHPStan\Reflection\Php\DummyParameter(
					'statement',
					new \PHPStan\Type\StringType(),
					false
				);
				$this->parameters[] = new \PHPStan\Reflection\Php\DummyParameter(
					'fetchColumn',
					new \PHPStan\Type\IntegerType(),
					true
				);
				$this->parameters[] = new \PHPStan\Reflection\Php\DummyParameter(
					'colno',
					new \PHPStan\Type\MixedType(),
					true
				);
				$this->parameters[] = new \PHPStan\Reflection\Php\DummyParameter(
					'constructorArgs',
					new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType(), false),
					true
				);
			}
			if (
				$this->declaringClass->getName() === 'DatePeriod'
				&& $this->reflection->getName() === '__construct'
				&& count($this->parameters) < 4
			) {
				$this->parameters[] = new \PHPStan\Reflection\Php\DummyParameter(
					'options',
					new \PHPStan\Type\IntegerType(),
					true
				);
			}
			if (
				$this->declaringClass->getName() === 'Closure'
				&& $this->reflection->getName() === '__invoke'
				&& count($this->parameters) < 1
			) {
				$this->parameters[] = new \PHPStan\Reflection\Php\DummyParameter(
					'args',
					new \PHPStan\Type\MixedType(),
					true,
					false,
					true
				);
			}
			if (
				$this->declaringClass->getName() === 'ReflectionClass'
				&& $this->reflection->getName() === 'newInstance'
				&& count($this->parameters) === 1
			) {
				$this->parameters[0] = new \PHPStan\Reflection\Php\DummyParameter(
					'args',
					new \PHPStan\Type\MixedType(),
					true,
					false,
					true
				);
			}
			if (
				$this->declaringClass->getName() === 'DateTimeZone'
				&& $this->reflection->getName() === 'getTransitions'
				&& count($this->parameters) === 2
			) {
				$this->parameters[0] = new \PHPStan\Reflection\Php\DummyParameter(
					'timestamp_begin',
					new \PHPStan\Type\IntegerType(),
					true
				);
				$this->parameters[1] = new \PHPStan\Reflection\Php\DummyParameter(
					'timestamp_end',
					new \PHPStan\Type\IntegerType(),
					true
				);
			}

			if (
				$this->declaringClass->getName() === 'Locale'
				&& $this->reflection->getName() === 'getDisplayLanguage'
			) {
				$this->parameters[1] = new \PHPStan\Reflection\Php\DummyParameter(
					'in_locale',
					new \PHPStan\Type\StringType(),
					true
				);
			}

			if (
				$this->declaringClass->getName() === 'DOMDocument'
				&& $this->reflection->getName() === 'saveHTML'
				&& count($this->parameters) === 0
			) {
				$this->parameters[] = new \PHPStan\Reflection\Php\DummyParameter(
					'node',
					\PHPStan\Type\TypeCombinator::addNull(new \PHPStan\Type\ObjectType('DOMNode')),
					true
				);
			}
		}

		return $this->parameters;
	}

	public function isVariadic(): bool
	{
		$isNativelyVariadic = $this->reflection->isVariadic();
		if (
			!$isNativelyVariadic
			&& (
				(
					$this->declaringClass->getName() === 'ReflectionMethod'
					&& $this->reflection->getName() === 'invoke'
				)
				|| (
					$this->declaringClass->getName() === 'Closure'
					&& $this->reflection->getName() === '__invoke'
				)
				|| (
					$this->declaringClass->getName() === 'ReflectionClass'
					&& $this->reflection->getName() === 'newInstance'
				)
			)
		) {
			return true;
		}

		if (!$isNativelyVariadic && $this->declaringClass->getFileName() !== false) {
			$key = sprintf('variadic-method-%s-%s-v0', $this->declaringClass->getName(), $this->reflection->getName());
			$cachedResult = $this->cache->load($key);
			if ($cachedResult === null) {
				$nodes = $this->parser->parseFile($this->declaringClass->getFileName());
				$result = $this->callsFuncGetArgs($nodes);
				$this->cache->save($key, $result);
				return $result;
			}

			return $cachedResult;
		}

		return $isNativelyVariadic;
	}

	/**
	 * @param mixed $nodes
	 * @return bool
	 */
	private function callsFuncGetArgs($nodes): bool
	{
		foreach ($nodes as $node) {
			if (is_array($node)) {
				if ($this->callsFuncGetArgs($node)) {
					return true;
				}
			}

			if (!($node instanceof \PhpParser\Node)) {
				continue;
			}

			if (
				$node instanceof \PhpParser\Node\Stmt\ClassLike
				&& isset($node->namespacedName)
				&& $this->declaringClass->getName() !== (string) $node->namespacedName
			) {
				continue;
			}

			if ($node instanceof \PhpParser\Node\Stmt\ClassMethod) {
				if ($node->getStmts() === null) {
					continue; // interface
				}

				$methodName = $node->name;
				if ($methodName === $this->reflection->getName()) {
					return $this->functionCallStatementFinder->findFunctionCallInStatements(\PHPStan\Reflection\ParametersAcceptor::VARIADIC_FUNCTIONS, $node->getStmts()) !== null;
				}

				continue;
			}

			if ($this->callsFuncGetArgs($node)) {
				return true;
			}
		}

		return false;
	}

	public function isPrivate(): bool
	{
		return $this->reflection->isPrivate();
	}

	public function isPublic(): bool
	{
		return $this->reflection->isPublic();
	}

	public function getReturnType(): \PHPStan\Type\Type
	{
		if ($this->returnType === null) {
			if ($this->getName() === '__construct') {
				return $this->returnType = new \PHPStan\Type\VoidType();
			}
			$returnType = $this->reflection->getReturnType();
			$phpDocReturnType = $this->phpDocReturnType;
			if (
				$returnType !== null
				&& $phpDocReturnType !== null
				&& $returnType->allowsNull() !== \PHPStan\Type\TypeCombinator::containsNull($phpDocReturnType)
			) {
				$phpDocReturnType = null;
			}
			$this->returnType = \PHPStan\Type\TypehintHelper::decideTypeFromReflection(
				$returnType,
				$phpDocReturnType,
				$this->declaringClass->getName()
			);
		}

		return $this->returnType;
	}

	public function getPhpDocReturnType(): \PHPStan\Type\Type
	{
		if ($this->phpDocReturnType !== null) {
			return $this->phpDocReturnType;
		}

		return new \PHPStan\Type\MixedType();
	}

	public function getNativeReturnType(): \PHPStan\Type\Type
	{
		if ($this->nativeReturnType === null) {
			$this->nativeReturnType = \PHPStan\Type\TypehintHelper::decideTypeFromReflection(
				$this->reflection->getReturnType(),
				null,
				$this->declaringClass->getName()
			);
		}

		return $this->nativeReturnType;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\Php;

use PHPStan\Reflection\ClassReflection;
use PHPStan\Type\Type;

interface PhpMethodReflectionFactory
{

	/**
	 * @param \PHPStan\Reflection\ClassReflection $declaringClass
	 * @param \ReflectionMethod $reflection
	 * @param \PHPStan\Type\Type[] $phpDocParameterTypes
	 * @param \PHPStan\Type\Type|null $phpDocReturnType
	 * @return \PHPStan\Reflection\Php\PhpMethodReflection
	 */
	public function create(
		\PHPStan\Reflection\ClassReflection $declaringClass,
		\ReflectionMethod $reflection,
		array $phpDocParameterTypes,
		\PHPStan\Type\Type $phpDocReturnType = null
	): \PHPStan\Reflection\Php\PhpMethodReflection;

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\Php;
use PHPStan\Type\Type;
use PHPStan\Type\TypehintHelper;

class PhpParameterFromParserNodeReflection implements \PHPStan\Reflection\ParameterReflection
{

	/** @var string */
	private $name;

	/** @var bool */
	private $optional;

	/** @var \PHPStan\Type\Type */
	private $realType;

	/** @var \PHPStan\Type\Type|null */
	private $phpDocType;

	/** @var bool */
	private $passedByReference;

	/** @var \PhpParser\Node\Expr|null */
	private $defaultValue;

	/** @var bool */
	private $variadic;

	/** @var \PHPStan\Type\Type */
	private $type;

	public function __construct(
		string $name,
		bool $optional,
		\PHPStan\Type\Type $realType,
		\PHPStan\Type\Type $phpDocType = null,
		bool $passedByReference,
		\PhpParser\Node\Expr $defaultValue = null,
		bool $variadic
	)
	{
		$this->name = $name;
		$this->optional = $optional;
		$this->realType = $realType;
		$this->phpDocType = $phpDocType;
		$this->passedByReference = $passedByReference;
		$this->defaultValue = $defaultValue;
		$this->variadic = $variadic;
	}

	public function getName(): string
	{
		return $this->name;
	}

	public function isOptional(): bool
	{
		return $this->optional;
	}

	public function getType(): \PHPStan\Type\Type
	{
		if ($this->type === null) {
			$phpDocType = $this->phpDocType;
			if ($phpDocType !== null && $this->defaultValue !== null) {
				if (
					$this->defaultValue instanceof \PhpParser\Node\Expr\ConstFetch
					&& strtolower((string) $this->defaultValue->name) === 'null'
				) {
					$phpDocType = \PHPStan\Type\TypeCombinator::addNull($phpDocType);
				}
			}
			$this->type = \PHPStan\Type\TypehintHelper::decideType($this->realType, $phpDocType);
		}

		return $this->type;
	}

	public function isPassedByReference(): bool
	{
		return $this->passedByReference;
	}

	public function isVariadic(): bool
	{
		return $this->variadic;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\Php;

use PHPStan\Reflection\ParameterReflection;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use PHPStan\Type\TypehintHelper;

class PhpParameterReflection implements \PHPStan\Reflection\ParameterReflection
{

	/** @var \ReflectionParameter */
	private $reflection;

	/** @var \PHPStan\Type\Type|null */
	private $phpDocType = null;

	/** @var \PHPStan\Type\Type */
	private $type;

	/** @var \PHPStan\Type\Type */
	private $nativeType;

	public function __construct(\ReflectionParameter $reflection, \PHPStan\Type\Type $phpDocType = null)
	{
		$this->reflection = $reflection;
		$this->phpDocType = $phpDocType;
	}

	public function isOptional(): bool
	{
		return $this->reflection->isOptional();
	}

	public function getName(): string
	{
		return $this->reflection->getName();
	}

	public function getType(): \PHPStan\Type\Type
	{
		if ($this->type === null) {
			$phpDocType = $this->phpDocType;
			if ($phpDocType !== null && $this->reflection->isDefaultValueAvailable() && $this->reflection->getDefaultValue() === null) {
				$phpDocType = \PHPStan\Type\TypeCombinator::addNull($phpDocType);
			}
			$this->type = \PHPStan\Type\TypehintHelper::decideTypeFromReflection(
				$this->reflection->getType(),
				$phpDocType,
				$this->reflection->getDeclaringClass() !== null ? $this->reflection->getDeclaringClass()->getName() : null,
				$this->isVariadic()
			);
		}

		return $this->type;
	}

	public function isPassedByReference(): bool
	{
		return $this->reflection->isPassedByReference();
	}

	public function isVariadic(): bool
	{
		return $this->reflection->isVariadic();
	}

	public function getPhpDocType(): \PHPStan\Type\Type
	{
		if ($this->phpDocType !== null) {
			return $this->phpDocType;
		}

		return new \PHPStan\Type\MixedType();
	}

	public function getNativeType(): \PHPStan\Type\Type
	{
		if ($this->nativeType === null) {
			$this->nativeType = \PHPStan\Type\TypehintHelper::decideTypeFromReflection(
				$this->reflection->getType(),
				null,
				$this->reflection->getDeclaringClass() !== null ? $this->reflection->getDeclaringClass()->getName() : null,
				$this->isVariadic()
			);
		}

		return $this->nativeType;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\Php;

use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\Type\Type;

class PhpPropertyReflection implements \PHPStan\Reflection\PropertyReflection
{

	/** @var \PHPStan\Reflection\ClassReflection */
	private $declaringClass;

	/** @var \PHPStan\Type\Type */
	private $type;

	/** @var \ReflectionProperty */
	private $reflection;

	public function __construct(
		\PHPStan\Reflection\ClassReflection $declaringClass,
		\PHPStan\Type\Type $type,
		\ReflectionProperty $reflection
	)
	{
		$this->declaringClass = $declaringClass;
		$this->type = $type;
		$this->reflection = $reflection;
	}

	public function getDeclaringClass(): \PHPStan\Reflection\ClassReflection
	{
		return $this->declaringClass;
	}

	/**
	 * @return string|false
	 */
	public function getDocComment()
	{
		return $this->reflection->getDocComment();
	}

	public function isStatic(): bool
	{
		return $this->reflection->isStatic();
	}

	public function isPrivate(): bool
	{
		return $this->reflection->isPrivate();
	}

	public function isPublic(): bool
	{
		return $this->reflection->isPublic();
	}

	public function getType(): \PHPStan\Type\Type
	{
		return $this->type;
	}

	public function isReadable(): bool
	{
		return true;
	}

	public function isWritable(): bool
	{
		return true;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\Php;

use PHPStan\Reflection\ClassReflection;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;

class UniversalObjectCrateProperty implements \PHPStan\Reflection\PropertyReflection
{

	/** @var \PHPStan\Reflection\ClassReflection */
	private $declaringClass;

	public function __construct(\PHPStan\Reflection\ClassReflection $declaringClass)
	{
		$this->declaringClass = $declaringClass;
	}

	public function getDeclaringClass(): \PHPStan\Reflection\ClassReflection
	{
		return $this->declaringClass;
	}

	public function isStatic(): bool
	{
		return false;
	}

	public function isPrivate(): bool
	{
		return false;
	}

	public function isPublic(): bool
	{
		return true;
	}

	public function getType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\MixedType();
	}

	public function isReadable(): bool
	{
		return true;
	}

	public function isWritable(): bool
	{
		return true;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\Php;

use PHPStan\Broker\Broker;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\PropertyReflection;

class UniversalObjectCratesClassReflectionExtension
	implements \PHPStan\Reflection\PropertiesClassReflectionExtension, \PHPStan\Reflection\BrokerAwareExtension
{

	/** @var string[] */
	private $classes;

	/** @var string[]|null */
	private $filteredClasses;

	/** @var \PHPStan\Broker\Broker */
	private $broker;

	/**
	 * @param string[] $classes
	 */
	public function __construct(array $classes)
	{
		$this->classes = $classes;
	}

	public function setBroker(\PHPStan\Broker\Broker $broker)
	{
		$this->broker = $broker;
	}

	public function hasProperty(\PHPStan\Reflection\ClassReflection $classReflection, string $propertyName): bool
	{
		if ($this->filteredClasses === null) {
			$this->filteredClasses = array_values(array_filter($this->classes, function (string $class): bool {
				return $this->broker->hasClass($class);
			}));
		}
		foreach ($this->filteredClasses as $className) {
			if (
				$classReflection->getName() === $className
				|| $classReflection->isSubclassOf($className)
			) {
				return true;
			}
		}

		return false;
	}

	public function getProperty(\PHPStan\Reflection\ClassReflection $classReflection, string $propertyName): \PHPStan\Reflection\PropertyReflection
	{
		return new \PHPStan\Reflection\Php\UniversalObjectCrateProperty($classReflection);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\PhpDefect;

use PHPStan\PhpDoc\TypeStringResolver;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\PropertiesClassReflectionExtension;
use PHPStan\Reflection\PropertyReflection;

class PhpDefectClassReflectionExtension implements \PHPStan\Reflection\PropertiesClassReflectionExtension
{

	/** @var string[][] */
	private static $defaultProperties = [
		\DateInterval::class => [
			'y' => 'int',
			'm' => 'int',
			'd' => 'int',
			'h' => 'int',
			'i' => 'int',
			's' => 'int',
			'invert' => 'int',
			'days' => 'mixed',
		],
		\DOMAttr::class => [ // extends DOMNode
			'name' => 'string',
			'ownerElement' => \DOMElement::class,
			'schemaTypeInfo' => 'bool',
			'specified' => 'bool',
			'value' => 'string',
		],
		\DOMCharacterData::class => [ // extends DOMNode
			'data' => 'string',
			'length' => 'int',
		],
		\DOMDocument::class => [
			'actualEncoding' => 'string',
			'config' => \DOMConfiguration::class,
			'doctype' => \DOMDocumentType::class,
			'documentElement' => \DOMElement::class,
			'documentURI' => 'string',
			'encoding' => 'string',
			'formatOutput' => 'bool',
			'implementation' => \DOMImplementation::class,
			'preserveWhiteSpace' => 'bool',
			'recover' => 'bool',
			'resolveExternals' => 'bool',
			'standalone' => 'bool',
			'strictErrorChecking' => 'bool',
			'substituteEntities' => 'bool',
			'validateOnParse' => 'bool',
			'version' => 'string',
			'xmlEncoding' => 'string',
			'xmlStandalone' => 'bool',
			'xmlVersion' => 'string',
		],
		\DOMDocumentType::class => [ // extends DOMNode
			'publicId' => 'string',
			'systemId' => 'string',
			'name' => 'string',
			'entities' => \DOMNamedNodeMap::class,
			'notations' => \DOMNamedNodeMap::class,
			'internalSubset' => 'string',
		],
		\DOMElement::class => [ // extends DOMNode
			'schemaTypeInfo' => 'bool',
			'tagName' => 'string',
		],
		\DOMEntity::class => [ // extends DOMNode
			'publicId' => 'string',
			'systemId' => 'string',
			'notationName' => 'string',
			'actualEncoding' => 'string',
			'encoding' => 'string',
			'version' => 'string',
		],
		\DOMNamedNodeMap::class => [
			'length' => 'int',
		],
		\DOMNode::class => [
			'nodeName' => 'string',
			'nodeValue' => 'string',
			'nodeType' => 'int',
			'parentNode' => \DOMNode::class,
			'childNodes' => \DOMNodeList::class,
			'firstChild' => \DOMNode::class,
			'lastChild' => \DOMNode::class,
			'previousSibling' => \DOMNode::class,
			'nextSibling' => \DOMNode::class,
			'attributes' => \DOMNamedNodeMap::class,
			'ownerDocument' => \DOMDocument::class,
			'namespaceURI' => 'string',
			'prefix' => 'string',
			'localName' => 'string',
			'baseURI' => 'string',
			'textContent' => 'string',
		],
		\DOMNodeList::class => [
			'length' => 'int',
		],
		\DOMNotation::class => [ // extends DOMNode
			'publicId' => 'string',
			'systemId' => 'string',
		],
		\DOMProcessingInstruction::class => [ // extends DOMNode
			'target' => 'string',
			'data' => 'string',
		],
		\DOMText::class => [ // extends DOMCharacterData
			'wholeText' => 'string',
		],
		\DOMXPath::class => [ // extends DOMCharacterData
			'document' => \DOMDocument::class,
		],
		\XMLReader::class => [
			'attributeCount' => 'int',
			'baseURI' => 'string',
			'depth' => 'int',
			'hasAttributes' => 'bool',
			'hasValue' => 'bool',
			'isDefault' => 'bool',
			'isEmptyElement' => 'bool',
			'localName' => 'string',
			'name' => 'string',
			'namespaceURI' => 'string',
			'nodeType' => 'int',
			'prefix' => 'string',
			'value' => 'string',
			'xmlLang' => 'string',
		],
		\ZipArchive::class => [
			'status' => 'int',
			'statusSys' => 'int',
			'numFiles' => 'int',
			'filename' => 'string',
			'comment' => 'string',
		],
		\LibXMLError::class => [
			'level' => 'int',
			'code' => 'int',
			'column' => 'int',
			'message' => 'string',
			'file' => 'string',
			'line' => 'int',
		],
	];

	/** @var string[][] */
	private static $properties71 = [
		\DateInterval::class => [
			'f' => 'float',
		],
	];

	/** @var TypeStringResolver */
	private $typeStringResolver;

	/** @var string[][] */
	private $properties = [];

	public function __construct(\PHPStan\PhpDoc\TypeStringResolver $typeStringResolver)
	{
		$this->typeStringResolver = $typeStringResolver;
		$this->properties = self::$defaultProperties;
		if (PHP_VERSION_ID >= 70100) { // since PHP 7.1
			$this->properties = array_merge_recursive($this->properties, self::$properties71);
		}
	}

	public function hasProperty(\PHPStan\Reflection\ClassReflection $classReflection, string $propertyName): bool
	{
		$classWithProperties = $this->getClassWithProperties($classReflection, $propertyName);
		return $classWithProperties !== null;
	}

	public function getProperty(\PHPStan\Reflection\ClassReflection $classReflection, string $propertyName): \PHPStan\Reflection\PropertyReflection
	{
		/** @var \PHPStan\Reflection\ClassReflection $classWithProperties */
		$classWithProperties = $this->getClassWithProperties($classReflection, $propertyName);
		$typeString = $this->properties[$classWithProperties->getName()][$propertyName];
		return new \PHPStan\Reflection\PhpDefect\PhpDefectPropertyReflection(
			$classWithProperties,
			$this->typeStringResolver->resolve($typeString)
		);
	}

	/**
	 * @param \PHPStan\Reflection\ClassReflection $classReflection
	 * @param string $propertyName
	 * @return \PHPStan\Reflection\ClassReflection|null
	 */
	private function getClassWithProperties(\PHPStan\Reflection\ClassReflection $classReflection, string $propertyName)
	{
		if (isset($this->properties[$classReflection->getName()][$propertyName])) {
			return $classReflection;
		}

		foreach ($classReflection->getParents() as $parentClass) {
			if (isset($this->properties[$parentClass->getName()][$propertyName])) {
				return $parentClass;
			}
		}

		return null;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\PhpDefect;

use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\Type\Type;

class PhpDefectPropertyReflection implements \PHPStan\Reflection\PropertyReflection
{

	/** @var \PHPStan\Reflection\ClassReflection */
	private $declaringClass;

	/** @var \PHPStan\Type\Type */
	private $type;

	public function __construct(
		\PHPStan\Reflection\ClassReflection $declaringClass,
		\PHPStan\Type\Type $type
	)
	{
		$this->declaringClass = $declaringClass;
		$this->type = $type;
	}

	public function getDeclaringClass(): \PHPStan\Reflection\ClassReflection
	{
		return $this->declaringClass;
	}

	public function isStatic(): bool
	{
		return false;
	}

	public function isPrivate(): bool
	{
		return false;
	}

	public function isPublic(): bool
	{
		return true;
	}

	public function getType(): \PHPStan\Type\Type
	{
		return $this->type;
	}

	public function isReadable(): bool
	{
		return true;
	}

	public function isWritable(): bool
	{
		return true;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

interface PropertiesClassReflectionExtension
{

	public function hasProperty(\PHPStan\Reflection\ClassReflection $classReflection, string $propertyName): bool;

	public function getProperty(\PHPStan\Reflection\ClassReflection $classReflection, string $propertyName): \PHPStan\Reflection\PropertyReflection;

}
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

use PHPStan\Type\Type;

interface PropertyReflection extends \PHPStan\Reflection\ClassMemberReflection
{

	public function getType(): \PHPStan\Type\Type;

	public function isReadable(): bool;

	public function isWritable(): bool;

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Arrays;

use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\NullType;
use PHPStan\Type\StringType;
use PHPStan\Type\TrueOrFalseBooleanType;
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;

class AllowedArrayKeysTypes
{

	public static function getType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\UnionType([
			new \PHPStan\Type\IntegerType(),
			new \PHPStan\Type\StringType(),
			new \PHPStan\Type\FloatType(),
			new \PHPStan\Type\TrueOrFalseBooleanType(),
			new \PHPStan\Type\NullType(),
		]);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Arrays;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\ArrayType;

class AppendedArrayItemTypeRule implements \PHPStan\Rules\Rule
{

	/** @var \PHPStan\Rules\RuleLevelHelper */
	private $ruleLevelHelper;

	public function __construct(\PHPStan\Rules\RuleLevelHelper $ruleLevelHelper)
	{
		$this->ruleLevelHelper = $ruleLevelHelper;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\Assign::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\Assign $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (!($node->var instanceof \PhpParser\Node\Expr\ArrayDimFetch)) {
			return [];
		}

		$assignedToType = $scope->getType($node->var->var);
		if (!($assignedToType instanceof \PHPStan\Type\ArrayType)) {
			return [];
		}

		if ($assignedToType->isItemTypeInferredFromLiteralArray()) {
			return [];
		}

		$assignedValueType = $scope->getType($node->expr);
		if (!$this->ruleLevelHelper->accepts($assignedToType->getItemType(), $assignedValueType)) {
			return [
				sprintf(
					'Array (%s) does not accept %s.',
					$assignedToType->describe(),
					$assignedValueType->describe()
				),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Arrays;

use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;

class DuplicateKeysInLiteralArraysRule implements \PHPStan\Rules\Rule
{

	/** @var \PHPStan\Broker\Broker */
	private $broker;

	/** @var \PhpParser\PrettyPrinter\Standard */
	private $printer;

	public function __construct(
		\PHPStan\Broker\Broker $broker,
		\PhpParser\PrettyPrinter\Standard $printer
	)
	{
		$this->broker = $broker;
		$this->printer = $printer;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\Array_::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\Array_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		$values = [];
		$duplicateKeys = [];
		foreach ($node->items as $item) {
			if ($item === null) {
				continue;
			}
			if ($item->key === null) {
				continue;
			}

			$key = $item->key;
			if (
				!$key instanceof \PhpParser\Node\Scalar\String_
				&& !$key instanceof \PhpParser\Node\Scalar\LNumber
				&& !$key instanceof \PhpParser\Node\Scalar\DNumber
				&& !$key instanceof \PhpParser\Node\Expr\ConstFetch
			) {
				continue;
			}

			if ($key instanceof \PhpParser\Node\Expr\ConstFetch) {
				$printedValue = (string) $key->name;
				$constName = strtolower($printedValue);
				if ($constName === 'true') {
					$value = true;
				} elseif ($constName === 'false') {
					$value = false;
				} elseif ($constName === 'null') {
					$value = null;
				} elseif ($this->broker->hasConstant($key->name, $scope)) {
					$value = constant($this->broker->resolveConstantName($key->name, $scope));
				} else {
					continue;
				}
			} else {
				$printedValue = $this->printer->prettyPrintExpr($key);
				$value = eval(sprintf('return %s;', $printedValue));
			}

			$previousCount = count($values);
			$values[$value] = $printedValue;
			if ($previousCount === count($values)) {
				if (!isset($duplicateKeys[$value])) {
					$duplicateKeys[$value] = [$values[$value]];
				}

				$duplicateKeys[$value][] = $printedValue;
			}
		}

		$messages = [];
		foreach ($duplicateKeys as $key => $values) {
			$messages[] = sprintf(
				'Array has %d %s with value %s (%s).',
				count($values),
				count($values) === 1 ? 'duplicate key' : 'duplicate keys',
				var_export($key, true),
				implode(', ', $values)
			);
		}

		return $messages;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Arrays;

use PHPStan\Analyser\Scope;
use PHPStan\Type\ArrayType;

class InvalidKeyInArrayDimFetchRule implements \PHPStan\Rules\Rule
{

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\ArrayDimFetch::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\ArrayDimFetch $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if ($node->dim === null) {
			return [];
		}

		$varType = $scope->getType($node->var);
		if (!$varType instanceof \PHPStan\Type\ArrayType) {
			return [];
		}

		$dimensionType = $scope->getType($node->dim);
		if (!\PHPStan\Rules\Arrays\AllowedArrayKeysTypes::getType()->accepts($dimensionType)) {
			return [
				sprintf('Invalid array key type %s.', $dimensionType->describe()),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Arrays;

use PHPStan\Analyser\Scope;

class InvalidKeyInArrayItemRule implements \PHPStan\Rules\Rule
{

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\ArrayItem::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\ArrayItem $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if ($node->key === null) {
			return [];
		}

		$dimensionType = $scope->getType($node->key);
		if (!\PHPStan\Rules\Arrays\AllowedArrayKeysTypes::getType()->accepts($dimensionType)) {
			return [
				sprintf('Invalid array key type %s.', $dimensionType->describe()),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Arrays;

use PHPStan\Analyser\Scope;
use PHPStan\Type\MixedType;
use PHPStan\Type\UnionType;

class IterableInForeachRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var bool
	 */
	private $checkUnionTypes;

	public function __construct(bool $checkUnionTypes)
	{
		$this->checkUnionTypes = $checkUnionTypes;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\Foreach_::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\Foreach_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		$iteratedExpressionType = $scope->getType($node->expr);
		if (!$this->checkUnionTypes && $iteratedExpressionType instanceof \PHPStan\Type\UnionType) {
			return [];
		}

		if (!$iteratedExpressionType instanceof \PHPStan\Type\MixedType && !$iteratedExpressionType->isIterable()->yes()) {
			return [
				sprintf(
					'Argument of an invalid type %s supplied for foreach, only iterables are supported.',
					$iteratedExpressionType->describe()
				),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Cast;
use PHPStan\Analyser\Scope;
use PHPStan\Type\FloatType;
use PHPStan\Type\UnionType;

class UselessCastRule implements \PHPStan\Rules\Rule
{

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\Cast::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\Cast $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[] errors
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if ($node instanceof \PhpParser\Node\Expr\Cast\Object_) {
			return [];
		}

		$expressionType = $scope->getType($node->expr);
		if ($expressionType instanceof \PHPStan\Type\UnionType) {
			return [];
		}

		$castType = $scope->getType($node);
		if ($castType instanceof \PHPStan\Type\FloatType && $node->expr instanceof \PhpParser\Node\Expr\BinaryOp\Div) {
			return [];
		}

		if (get_class($expressionType) === get_class($castType)) {
			return [
				sprintf(
					'Casting to %s something that\'s already %s.',
					$castType->describe(),
					$expressionType->describe()
				),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules;

use PHPStan\Broker\Broker;
use PHPStan\Reflection\ClassReflection;

class ClassCaseSensitivityCheck
{

	/** @var \PHPStan\Broker\Broker */
	private $broker;

	public function __construct(\PHPStan\Broker\Broker $broker)
	{
		$this->broker = $broker;
	}

	/**
	 * @param string[] $classNames
	 * @return string[]
	 */
	public function checkClassNames(array $classNames): array
	{
		$messages = [];
		foreach ($classNames as $className) {
			if (!$this->broker->hasClass($className)) {
				continue;
			}
			$classReflection = $this->broker->getClass($className);
			$realClassName = $classReflection->getName();
			if (strtolower($realClassName) !== strtolower($className)) {
				continue; // skip class alias
			}
			if ($realClassName === $className) {
				continue;
			}

			$messages[] = sprintf(
				'%s %s referenced with incorrect case: %s.',
				$this->getTypeName($classReflection),
				$realClassName,
				$className
			);
		}

		return $messages;
	}

	private function getTypeName(\PHPStan\Reflection\ClassReflection $classReflection): string
	{
		if ($classReflection->isInterface()) {
			return 'Interface';
		} elseif ($classReflection->isTrait()) {
			return 'Trait';
		}

		return 'Class';
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Classes;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\Rules\ClassCaseSensitivityCheck;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\ErrorType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use PHPStan\Type\TypeCombinator;

class ClassConstantRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	/**
	 * @var \PHPStan\Rules\RuleLevelHelper
	 */
	private $ruleLevelHelper;

	/**
	 * @var \PHPStan\Rules\ClassCaseSensitivityCheck
	 */
	private $classCaseSensitivityCheck;

	public function __construct(
		\PHPStan\Broker\Broker $broker,
		\PHPStan\Rules\RuleLevelHelper $ruleLevelHelper,
		\PHPStan\Rules\ClassCaseSensitivityCheck $classCaseSensitivityCheck
	)
	{
		$this->broker = $broker;
		$this->ruleLevelHelper = $ruleLevelHelper;
		$this->classCaseSensitivityCheck = $classCaseSensitivityCheck;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\ClassConstFetch::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\ClassConstFetch $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		$constantName = $node->name;
		if (!is_string($constantName)) {
			return [];
		}

		$class = $node->class;
		$messages = [];
		if ($class instanceof \PhpParser\Node\Name) {
			$className = (string) $class;
			if ($className === 'self' || $className === 'static') {
				if (!$scope->isInClass()) {
					return [
						sprintf('Using %s outside of class scope.', $className),
					];
				}

				$className = $scope->getClassReflection()->getName();
			} elseif ($className === 'parent') {
				if (!$scope->isInClass()) {
					return [
						sprintf('Using %s outside of class scope.', $className),
					];
				}
				$currentClassReflection = $scope->getClassReflection();
				if ($currentClassReflection->getParentClass() === false) {
					return [
						sprintf(
							'Access to parent::%s but %s does not extend any class.',
							$constantName,
							$currentClassReflection->getDisplayName()
						),
					];
				}
				$className = $currentClassReflection->getParentClass()->getName();
			} else {
				if (!$this->broker->hasClass($className)) {
					if (strtolower($constantName) === 'class') {
						return [
							sprintf('Class %s not found.', $className),
						];
					}

					return [
						sprintf('Access to constant %s on an unknown class %s.', $constantName, $className),
					];
				} else {
					$messages = $this->classCaseSensitivityCheck->checkClassNames([$className]);
				}

				$className = $this->broker->getClass($className)->getName();
			}

			$classType = new \PHPStan\Type\ObjectType($className);
		} else {
			$classTypeResult = $this->ruleLevelHelper->findTypeToCheck(
				$scope,
				$class,
				sprintf('Access to constant %s on an unknown class %%s.', $constantName)
			);
			$classType = $classTypeResult->getType();
			if ($classType instanceof \PHPStan\Type\ErrorType) {
				return $classTypeResult->getUnknownClassErrors();
			}
		}

		if ($classType instanceof \PHPStan\Type\StringType) {
			return $messages;
		}

		$typeForDescribe = $classType;
		$classType = \PHPStan\Type\TypeCombinator::remove($classType, new \PHPStan\Type\StringType());

		if (!$classType->canAccessConstants()) {
			return array_merge($messages, [
				sprintf('Cannot access constant %s on %s.', $constantName, $typeForDescribe->describe()),
			]);
		}

		if (strtolower($constantName) === 'class') {
			return $messages;
		}

		if (!$classType->hasConstant($constantName)) {
			return array_merge($messages, [
				sprintf(
					'Access to undefined constant %s::%s.',
					$typeForDescribe->describe(),
					$constantName
				),
			]);
		}

		$constantReflection = $classType->getConstant($constantName);
		if (!$scope->canAccessConstant($constantReflection)) {
			return array_merge($messages, [
				sprintf(
					'Access to %s constant %s of class %s.',
					$constantReflection->isPrivate() ? 'private' : 'protected',
					$constantName,
					$constantReflection->getDeclaringClass()->getDisplayName()
				),
			]);
		}

		return $messages;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Classes;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\ClassCaseSensitivityCheck;

class ExistingClassInClassExtendsRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Rules\ClassCaseSensitivityCheck
	 */
	private $classCaseSensitivityCheck;

	public function __construct(\PHPStan\Rules\ClassCaseSensitivityCheck $classCaseSensitivityCheck)
	{
		$this->classCaseSensitivityCheck = $classCaseSensitivityCheck;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\Class_::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\Class_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if ($node->extends === null) {
			return [];
		}
		return $this->classCaseSensitivityCheck->checkClassNames([(string) $node->extends]);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Classes;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\Rules\ClassCaseSensitivityCheck;

class ExistingClassInInstanceOfRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	/**
	 * @var \PHPStan\Rules\ClassCaseSensitivityCheck
	 */
	private $classCaseSensitivityCheck;

	/**
	 * @var bool
	 */
	private $checkClassCaseSensitivity;

	public function __construct(
		\PHPStan\Broker\Broker $broker,
		\PHPStan\Rules\ClassCaseSensitivityCheck $classCaseSensitivityCheck,
		bool $checkClassCaseSensitivity
	)
	{
		$this->broker = $broker;
		$this->classCaseSensitivityCheck = $classCaseSensitivityCheck;
		$this->checkClassCaseSensitivity = $checkClassCaseSensitivity;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\Instanceof_::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\Instanceof_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		$class = $node->class;
		if (!($class instanceof \PhpParser\Node\Name)) {
			return [];
		}

		$name = (string) $class;
		$lowercaseName = strtolower($name);

		if (in_array($lowercaseName, [
			'self',
			'static',
			'parent',
		], true)) {
			if (!$scope->isInClass()) {
				return [
					sprintf('Using %s outside of class scope.', $lowercaseName),
				];
			}

			return [];
		}

		if (!$this->broker->hasClass($name)) {
			return [
				sprintf('Class %s not found.', $name),
			];
		} elseif ($this->checkClassCaseSensitivity) {
			return $this->classCaseSensitivityCheck->checkClassNames([$name]);
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Classes;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\ClassCaseSensitivityCheck;

class ExistingClassInTraitUseRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Rules\ClassCaseSensitivityCheck
	 */
	private $classCaseSensitivityCheck;

	public function __construct(\PHPStan\Rules\ClassCaseSensitivityCheck $classCaseSensitivityCheck)
	{
		$this->classCaseSensitivityCheck = $classCaseSensitivityCheck;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\TraitUse::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\TraitUse $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		return $this->classCaseSensitivityCheck->checkClassNames(
			array_map(function (\PhpParser\Node\Name $traitName): string {
				return (string) $traitName;
			}, $node->traits)
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Classes;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\ClassCaseSensitivityCheck;

class ExistingClassesInClassImplementsRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Rules\ClassCaseSensitivityCheck
	 */
	private $classCaseSensitivityCheck;

	public function __construct(\PHPStan\Rules\ClassCaseSensitivityCheck $classCaseSensitivityCheck)
	{
		$this->classCaseSensitivityCheck = $classCaseSensitivityCheck;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\Class_::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\Class_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		return $this->classCaseSensitivityCheck->checkClassNames(
			array_map(function (\PhpParser\Node\Name $traitName): string {
				return (string) $traitName;
			}, $node->implements)
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Classes;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\ClassCaseSensitivityCheck;

class ExistingClassesInInterfaceExtendsRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Rules\ClassCaseSensitivityCheck
	 */
	private $classCaseSensitivityCheck;

	public function __construct(\PHPStan\Rules\ClassCaseSensitivityCheck $classCaseSensitivityCheck)
	{
		$this->classCaseSensitivityCheck = $classCaseSensitivityCheck;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\Interface_::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\Interface_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		return $this->classCaseSensitivityCheck->checkClassNames(
			array_map(function (\PhpParser\Node\Name $traitName): string {
				return (string) $traitName;
			}, $node->extends)
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Classes;
use PHPStan\Analyser\Scope;
use PHPStan\Type\ObjectType;
use PHPStan\Type\ObjectWithoutClassType;
use PHPStan\Type\StringType;

class ImpossibleInstanceOfRule implements \PHPStan\Rules\Rule
{

	/** @var bool */
	private $checkAlwaysTrueInstanceof;

	public function __construct(bool $checkAlwaysTrueInstanceof)
	{
		$this->checkAlwaysTrueInstanceof = $checkAlwaysTrueInstanceof;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\Instanceof_::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\Instanceof_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if ($node->class instanceof \PhpParser\Node\Name) {
			$className = $scope->resolveName($node->class);
			$type = new \PHPStan\Type\ObjectType($className);
		} else {
			$type = $scope->getType($node->class);
		}

		$expressionType = $scope->getType($node->expr);
		$isExpressionObject = (new \PHPStan\Type\ObjectWithoutClassType())->isSuperTypeOf($expressionType);
		if (!$isExpressionObject->no() && $type instanceof \PHPStan\Type\StringType) {
			return [];
		}

		$isSuperType = $type->isSuperTypeOf($expressionType)
			->and($isExpressionObject);

		if ($isSuperType->no()) {
			return [
				sprintf(
					'Instanceof between %s and %s will always evaluate to false.',
					$expressionType->describe(),
					$type->describe()
				),
			];
		} elseif ($isSuperType->yes() && $this->checkAlwaysTrueInstanceof) {
			return [
				sprintf(
					'Instanceof between %s and %s will always evaluate to true.',
					$expressionType->describe(),
					$type->describe()
				),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Classes;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\Rules\ClassCaseSensitivityCheck;
use PHPStan\Rules\FunctionCallParametersCheck;

class InstantiationRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	/**
	 * @var \PHPStan\Rules\FunctionCallParametersCheck
	 */
	private $check;

	/**
	 * @var \PHPStan\Rules\ClassCaseSensitivityCheck
	 */
	private $classCaseSensitivityCheck;

	public function __construct(
		\PHPStan\Broker\Broker $broker,
		\PHPStan\Rules\FunctionCallParametersCheck $check,
		\PHPStan\Rules\ClassCaseSensitivityCheck $classCaseSensitivityCheck
	)
	{
		$this->broker = $broker;
		$this->check = $check;
		$this->classCaseSensitivityCheck = $classCaseSensitivityCheck;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\New_::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\New_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (!($node->class instanceof \PhpParser\Node\Name)) {
			return [];
		}

		$class = (string) $node->class;
		$messages = [];
		if ($class === 'static') {
			if (!$scope->isInClass()) {
				return [
					sprintf('Using %s outside of class scope.', $class),
				];
			}
			return [];
		} elseif ($class === 'self') {
			if (!$scope->isInClass()) {
				return [
					sprintf('Using %s outside of class scope.', $class),
				];
			}
			$classReflection = $scope->getClassReflection();
		} elseif ($class === 'parent') {
			if (!$scope->isInClass()) {
				return [
					sprintf('Using %s outside of class scope.', $class),
				];
			}
			if ($scope->getClassReflection()->getParentClass() === false) {
				return [
					sprintf(
						'%s::%s() calls new parent but %s does not extend any class.',
						$scope->getClassReflection()->getDisplayName(),
						$scope->getFunctionName(),
						$scope->getClassReflection()->getDisplayName()
					),
				];
			}
			$classReflection = $scope->getClassReflection()->getParentClass();
		} else {
			if (!$this->broker->hasClass($class)) {
				return [
					sprintf('Instantiated class %s not found.', $class),
				];
			} else {
				$messages = $this->classCaseSensitivityCheck->checkClassNames([$class]);
			}

			$classReflection = $this->broker->getClass($class);
		}

		if ($classReflection->isInterface()) {
			return [
				sprintf('Cannot instantiate interface %s.', $classReflection->getDisplayName()),
			];
		}

		if ($classReflection->isAbstract()) {
			return [
				sprintf('Instantiated class %s is abstract.', $classReflection->getDisplayName()),
			];
		}

		if (!$classReflection->hasNativeMethod('__construct') && !$classReflection->hasNativeMethod($class)) {
			if (count($node->args) > 0) {
				return array_merge($messages, [
					sprintf(
						'Class %s does not have a constructor and must be instantiated without any parameters.',
						$classReflection->getDisplayName()
					),
				]);
			}

			return [];
		}

		$constructorReflection = $classReflection->hasNativeMethod('__construct') ? $classReflection->getNativeMethod('__construct') : $classReflection->getNativeMethod($class);
		if (!$scope->canCallMethod($constructorReflection)) {
			$messages[] = sprintf(
				'Cannot instantiate class %s via %s constructor %s::%s().',
				$classReflection->getDisplayName(),
				$constructorReflection->isPrivate() ? 'private' : 'protected',
				$constructorReflection->getDeclaringClass()->getDisplayName(),
				$constructorReflection->getName()
			);
		}

		return array_merge($messages, $this->check->check(
			$constructorReflection,
			$scope,
			$node,
			[
				'Class ' . $classReflection->getDisplayName() . ' constructor invoked with %d parameter, %d required.',
				'Class ' . $classReflection->getDisplayName() . ' constructor invoked with %d parameters, %d required.',
				'Class ' . $classReflection->getDisplayName() . ' constructor invoked with %d parameter, at least %d required.',
				'Class ' . $classReflection->getDisplayName() . ' constructor invoked with %d parameters, at least %d required.',
				'Class ' . $classReflection->getDisplayName() . ' constructor invoked with %d parameter, %d-%d required.',
				'Class ' . $classReflection->getDisplayName() . ' constructor invoked with %d parameters, %d-%d required.',
				'Parameter #%d %s of class ' . $classReflection->getDisplayName() . ' constructor expects %s, %s given.',
				'', // constructor does not have a return type
				'Parameter #%d %s of class ' . $classReflection->getDisplayName() . ' constructor is passed by reference, so it expects variables only',
			]
		));
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Classes;
use PHPStan\Analyser\Scope;

class RequireParentConstructCallRule implements \PHPStan\Rules\Rule
{

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\ClassMethod::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\ClassMethod $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (strpos($scope->getAnalysedContextFile(), '(in context of ') !== false) {
			return []; // skip traits
		}

		if ($node->name !== '__construct') {
			return [];
		}

		$classReflection = $scope->getClassReflection()->getNativeReflection();
		if ($classReflection->isInterface() || $classReflection->isAnonymous()) {
			return [];
		}

		if ($this->callsParentConstruct($node)) {
			if ($classReflection->getParentClass() === false) {
				return [
					sprintf(
						'%s::__construct() calls parent constructor but does not extend any class.',
						$classReflection->getName()
					),
				];
			}

			if ($this->getParentConstructorClass($classReflection) === false) {
				return [
					sprintf(
						'%s::__construct() calls parent constructor but parent does not have one.',
						$classReflection->getName()
					),
				];
			}
		} else {
			$parentClass = $this->getParentConstructorClass($classReflection);
			if ($parentClass !== false) {
				return [
					sprintf(
						'%s::__construct() does not call parent constructor from %s.',
						$classReflection->getName(),
						$parentClass->getName()
					),
				];
			}
		}

		return [];
	}

	private function callsParentConstruct(\PhpParser\Node $parserNode): bool
	{
		if (!isset($parserNode->stmts)) {
			return false;
		}

		foreach ($parserNode->stmts as $statement) {
			$statement = $this->ignoreErrorSuppression($statement);
			if ($statement instanceof \PhpParser\Node\Expr\StaticCall) {
				if (
					$statement->class instanceof \PhpParser\Node\Name
					&& ((string) $statement->class === 'parent')
					&& $statement->name === '__construct'
				) {
					return true;
				}
			} else {
				if ($this->callsParentConstruct($statement)) {
					return true;
				}
			}
		}

		return false;
	}

	/**
	 * @param \ReflectionClass $classReflection
	 * @return \ReflectionClass|false
	 */
	private function getParentConstructorClass(\ReflectionClass $classReflection)
	{
		while ($classReflection->getParentClass() !== false) {
			$constructor = $classReflection->getParentClass()->hasMethod('__construct') ? $classReflection->getParentClass()->getMethod('__construct') : null;
			$constructorWithClassName = $classReflection->getParentClass()->hasMethod($classReflection->getParentClass()->getName()) ? $classReflection->getParentClass()->getMethod($classReflection->getParentClass()->getName()) : null;
			if (
				(
					$constructor !== null
					&& $constructor->getDeclaringClass()->getName() === $classReflection->getParentClass()->getName()
					&& !$constructor->isAbstract()
				) || (
					$constructorWithClassName !== null
					&& $constructorWithClassName->getDeclaringClass()->getName() === $classReflection->getParentClass()->getName()
					&& !$constructorWithClassName->isAbstract()
				)
			) {
				return $classReflection->getParentClass();
			}

			$classReflection = $classReflection->getParentClass();
		}

		return false;
	}

	private function ignoreErrorSuppression(\PhpParser\Node $statement): \PhpParser\Node
	{
		if ($statement instanceof \PhpParser\Node\Expr\ErrorSuppress) {

			return $statement->expr;
		}

		return $statement;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Classes;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\UnusedFunctionParametersCheck;

class UnusedConstructorParametersRule implements \PHPStan\Rules\Rule
{

	/** @var \PHPStan\Rules\UnusedFunctionParametersCheck */
	private $check;

	public function __construct(\PHPStan\Rules\UnusedFunctionParametersCheck $check)
	{
		$this->check = $check;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\ClassMethod::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\ClassMethod $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if ($node->name !== '__construct' || $node->stmts === null) {
			return [];
		}

		if (count($node->params) === 0) {
			return [];
		}

		$message = sprintf('Constructor of class %s has an unused parameter $%%s.', $scope->getClassReflection()->getDisplayName());
		if ($scope->getClassReflection()->isAnonymous()) {
			$message = 'Constructor of an anonymous class has an unused parameter $%s.';
		}

		return $this->check->getUnusedParameters(
			array_map(function (\PhpParser\Node\Param $parameter): string {
				return $parameter->name;
			}, $node->params),
			$node->stmts,
			$message
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Comparison;
use PHPStan\Analyser\Scope;
use PHPStan\Analyser\TypeSpecifier;

class ImpossibleCheckTypeFunctionCallRule implements \PHPStan\Rules\Rule
{

	/** @var \PHPStan\Analyser\TypeSpecifier */
	private $typeSpecifier;

	/** @var bool */
	private $checkAlwaysTrueCheckTypeFunctionCall;

	public function __construct(
		\PHPStan\Analyser\TypeSpecifier $typeSpecifier,
		bool $checkAlwaysTrueCheckTypeFunctionCall
	)
	{
		$this->typeSpecifier = $typeSpecifier;
		$this->checkAlwaysTrueCheckTypeFunctionCall = $checkAlwaysTrueCheckTypeFunctionCall;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\FuncCall::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\FuncCall $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[] errors
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (!$node->name instanceof \PhpParser\Node\Name) {
			return [];
		}

		$sureTypes = $this->typeSpecifier->specifyTypesInCondition($scope, $node)->getSureTypes();
		if (count($sureTypes) !== 1) {
			return [];
		}

		$sureType = reset($sureTypes);
		$argumentType = $scope->getType($sureType[0]);

		/** @var \PHPStan\Type\Type $resultType */
		$resultType = $sureType[1];

		$isSuperType = $resultType->isSuperTypeOf($argumentType);
		$functionName = (string) $node->name;
		if ($functionName === 'is_a') {
			return [];
		}

		if ($isSuperType->no()) {
			return [sprintf(
				'Call to function %s() will always evaluate to false.',
				$functionName
			)];
		} elseif ($isSuperType->yes() && $this->checkAlwaysTrueCheckTypeFunctionCall) {
			return [sprintf(
				'Call to function %s() will always evaluate to true.',
				$functionName
			)];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Comparison;
use PHPStan\Analyser\Scope;
use PHPStan\Type\NullType;

class StrictComparisonOfDifferentTypesRule implements \PHPStan\Rules\Rule
{

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\BinaryOp::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\BinaryOp $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[] errors
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (!$node instanceof \PhpParser\Node\Expr\BinaryOp\Identical && !$node instanceof \PhpParser\Node\Expr\BinaryOp\NotIdentical) {
			return [];
		}

		$leftType = $scope->getType($node->left);
		$rightType = $scope->getType($node->right);

		if (
			(
				$node->left instanceof \PhpParser\Node\Expr\PropertyFetch
				|| $node->left instanceof \PhpParser\Node\Expr\StaticPropertyFetch
			)
			&& $rightType instanceof \PHPStan\Type\NullType
		) {
			return [];
		}

		if (
			(
				$node->right instanceof \PhpParser\Node\Expr\PropertyFetch
				|| $node->right instanceof \PhpParser\Node\Expr\StaticPropertyFetch
			)
			&& $leftType instanceof \PHPStan\Type\NullType
		) {
			return [];
		}

		if ($leftType->isSuperTypeOf($rightType)->no()) {
			return [
				sprintf(
					'Strict comparison using %s between %s and %s will always evaluate to %s.',
					$node instanceof \PhpParser\Node\Expr\BinaryOp\Identical ? '===' : '!==',
					$leftType->describe(),
					$rightType->describe(),
					$node instanceof \PhpParser\Node\Expr\BinaryOp\Identical ? 'false' : 'true'
				),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Constants;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;

class ConstantRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	public function __construct(\PHPStan\Broker\Broker $broker)
	{
		$this->broker = $broker;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\ConstFetch::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\ConstFetch $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (!$this->broker->hasConstant($node->name, $scope)) {
			return [
				sprintf(
					'Constant %s not found.',
					(string) $node->name
				),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Exceptions;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;

class CaughtExceptionExistenceRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	public function __construct(\PHPStan\Broker\Broker $broker)
	{
		$this->broker = $broker;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\Catch_::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\Catch_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (isset($node->types)) {
			$classes = $node->types;
		} elseif (isset($node->type)) {
			$classes = [$node->type];
		} else {
			throw new \PHPStan\ShouldNotHappenException();
		}
		$errors = [];
		foreach ($classes as $className) {
			$class = (string) $className;
			if (!$this->broker->hasClass($class)) {
				$errors[] = sprintf('Caught class %s not found.', $class);
				continue;
			}

			$classReflection = $this->broker->getClass($class);
			if (!$classReflection->isInterface() && !$classReflection->getNativeReflection()->implementsInterface(\Throwable::class)) {
				$errors[] = sprintf('Caught class %s is not an exception.', $classReflection->getDisplayName());
			}
		}

		return $errors;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules;

use PHPStan\Type\Type;

class FoundTypeResult
{

	/** @var \PHPStan\Type\Type */
	private $type;

	/** @var string[] */
	private $referencedClasses;

	/** @var string[] */
	private $unknownClassErrors;

	/**
	 * @param \PHPStan\Type\Type $type
	 * @param string[] $referencedClasses
	 * @param string[] $unknownClassErrors
	 */
	public function __construct(
		\PHPStan\Type\Type $type,
		array $referencedClasses,
		array $unknownClassErrors
	)
	{
		$this->type = $type;
		$this->referencedClasses = $referencedClasses;
		$this->unknownClassErrors = $unknownClassErrors;
	}

	public function getType(): \PHPStan\Type\Type
	{
		return $this->type;
	}

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return $this->referencedClasses;
	}

	/**
	 * @return string[]
	 */
	public function getUnknownClassErrors(): array
	{
		return $this->unknownClassErrors;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParametersAcceptor;
use PHPStan\Type\ArrayType;
use PHPStan\Type\IterableIterableType;
use PHPStan\Type\MixedType;
use PHPStan\Type\StringType;
use PHPStan\Type\VoidType;

class FunctionCallParametersCheck
{

	/** @var \PHPStan\Rules\RuleLevelHelper */
	private $ruleLevelHelper;

	/** @var bool */
	private $checkArgumentTypes;

	/** @var bool */
	private $checkArgumentsPassedByReference;

	public function __construct(
		\PHPStan\Rules\RuleLevelHelper $ruleLevelHelper,
		bool $checkArgumentTypes,
		bool $checkArgumentsPassedByReference
	)
	{
		$this->ruleLevelHelper = $ruleLevelHelper;
		$this->checkArgumentTypes = $checkArgumentTypes;
		$this->checkArgumentsPassedByReference = $checkArgumentsPassedByReference;
	}

	/**
	 * @param \PHPStan\Reflection\ParametersAcceptor $function
	 * @param \PHPStan\Analyser\Scope $scope
	 * @param \PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\New_ $funcCall
	 * @param string[] $messages Eight message templates
	 * @return string[]
	 */
	public function check(\PHPStan\Reflection\ParametersAcceptor $function, \PHPStan\Analyser\Scope $scope, $funcCall, array $messages): array
	{
		if (
			$function instanceof \PHPStan\Reflection\FunctionReflection
			&& in_array($function->getName(), [
				'implode',
				'strtok',
			], true)
		) {
			$functionParametersMinCount = 1;
			$functionParametersMaxCount = 2;
		} elseif (
			$function instanceof \PHPStan\Reflection\MethodReflection
			&& $function->getDeclaringClass()->getName() === 'DatePeriod'
			&& $function->getName() === '__construct'
		) {
			$functionParametersMinCount = 1;
			$functionParametersMaxCount = 4;
		} elseif (
			$function instanceof \PHPStan\Reflection\MethodReflection
			&& $function->getDeclaringClass()->getName() === 'mysqli'
			&& $function->getName() === 'query'
		) {
			$functionParametersMinCount = 1;
			$functionParametersMaxCount = 2;
		} else {
			$functionParametersMinCount = 0;
			$functionParametersMaxCount = 0;
			foreach ($function->getParameters() as $parameter) {
				if (!$parameter->isOptional()) {
					$functionParametersMinCount++;
				}

				$functionParametersMaxCount++;
			}

			if ($function->isVariadic()) {
				$functionParametersMaxCount = -1;
			}
		}

		$errors = [];
		$invokedParametersCount = count($funcCall->args);
		foreach ($funcCall->args as $arg) {
			if ($arg->unpack) {
				$invokedParametersCount = max($functionParametersMinCount, $functionParametersMaxCount);
				break;
			}
		}

		if ($invokedParametersCount < $functionParametersMinCount || $invokedParametersCount > $functionParametersMaxCount) {
			if ($functionParametersMinCount === $functionParametersMaxCount) {
				$errors[] = sprintf(
					$invokedParametersCount === 1 ? $messages[0] : $messages[1],
					$invokedParametersCount,
					$functionParametersMinCount
				);
			} elseif ($functionParametersMaxCount === -1 && $invokedParametersCount < $functionParametersMinCount) {
				$errors[] = sprintf(
					$invokedParametersCount === 1 ? $messages[2] : $messages[3],
					$invokedParametersCount,
					$functionParametersMinCount
				);
			} elseif ($functionParametersMaxCount !== -1) {
				$errors[] = sprintf(
					$invokedParametersCount === 1 ? $messages[4] : $messages[5],
					$invokedParametersCount,
					$functionParametersMinCount,
					$functionParametersMaxCount
				);
			}
		}

		if (
			$function->getReturnType() instanceof \PHPStan\Type\VoidType
			&& !$scope->isInFirstLevelStatement()
			&& !$funcCall instanceof \PhpParser\Node\Expr\New_
		) {
			$errors[] = $messages[7];
		}

		if (!$this->checkArgumentTypes && !$this->checkArgumentsPassedByReference) {
			return $errors;
		}

		$parameters = $function->getParameters();
		foreach ($funcCall->args as $i => $argument) {
			if (!isset($parameters[$i])) {
				if (!$function->isVariadic() || count($parameters) === 0) {
					break;
				}

				$parameter = $parameters[count($parameters) - 1];
				$parameterType = $parameter->getType();
				if ($parameterType instanceof \PHPStan\Type\ArrayType) {
					if (!$argument->unpack) {
						$parameterType = $parameterType->getItemType();
					}
				} else {
					break;
				}
			} else {
				$parameter = $parameters[$i];
				$parameterType = $parameter->getType();
				if ($parameter->isVariadic()) {
					if ($parameterType instanceof \PHPStan\Type\ArrayType && !$argument->unpack) {
						$parameterType = $parameterType->getItemType();
					}
				} elseif ($argument->unpack) {
					continue;
				}
			}

			$argumentValueType = $scope->getType($argument->value);
			$secondAccepts = null;
			if ($parameterType->isIterable()->yes() && $parameter->isVariadic()) {
				$secondAccepts = $this->ruleLevelHelper->accepts(
					new \PHPStan\Type\IterableIterableType(
						new \PHPStan\Type\MixedType(),
						$parameterType->getIterableValueType()
					),
					$argumentValueType
				);
			}

			if (
				$this->checkArgumentTypes
				&& !$this->ruleLevelHelper->accepts($parameterType, $argumentValueType)
				&& ($secondAccepts === null || !$secondAccepts)
				&& (
					!($parameterType instanceof \PHPStan\Type\StringType)
					|| !$argumentValueType->hasMethod('__toString')
				)
			) {
				$errors[] = sprintf(
					$messages[6],
					$i + 1,
					sprintf('%s$%s', $parameter->isVariadic() ? '...' : '', $parameter->getName()),
					$parameterType->describe(),
					$argumentValueType->describe()
				);
			}

			if (
				$this->checkArgumentsPassedByReference
				&& $parameter->isPassedByReference()
				&& !$argument->value instanceof \PhpParser\Node\Expr\Variable
				&& !$argument->value instanceof \PhpParser\Node\Expr\ArrayDimFetch
				&& !$argument->value instanceof \PhpParser\Node\Expr\PropertyFetch
				&& !$argument->value instanceof \PhpParser\Node\Expr\StaticPropertyFetch
			) {
				$errors[] = sprintf(
					$messages[8],
					$i + 1,
					sprintf('%s$%s', $parameter->isVariadic() ? '...' : '', $parameter->getName())
				);
			}
		}

		return $errors;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\Reflection\ParametersAcceptorWithPhpDocs;
use PHPStan\Type\NonexistentParentClassType;

class FunctionDefinitionCheck
{

	const VALID_TYPEHINTS = [
		'self',
		'array',
		'callable',
		'string',
		'int',
		'bool',
		'float',
		'void',
		'iterable',
		'object',
		'parent',
	];

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	/**
	 * @var \PHPStan\Rules\ClassCaseSensitivityCheck
	 */
	private $classCaseSensitivityCheck;

	/**
	 * @var bool
	 */
	private $checkClassCaseSensitivity;

	/**
	 * @var bool
	 */
	private $checkThisOnly;

	public function __construct(
		\PHPStan\Broker\Broker $broker,
		\PHPStan\Rules\ClassCaseSensitivityCheck $classCaseSensitivityCheck,
		bool $checkClassCaseSensitivity,
		bool $checkThisOnly
	)
	{
		$this->broker = $broker;
		$this->classCaseSensitivityCheck = $classCaseSensitivityCheck;
		$this->checkClassCaseSensitivity = $checkClassCaseSensitivity;
		$this->checkThisOnly = $checkThisOnly;
	}

	/**
	 * @param \PhpParser\Node\FunctionLike $function
	 * @param \PHPStan\Analyser\Scope $scope
	 * @param string $parameterMessage
	 * @param string $returnMessage
	 * @return string[]
	 */
	public function checkFunction(
		\PhpParser\Node\FunctionLike $function,
		\PHPStan\Analyser\Scope $scope,
		string $parameterMessage,
		string $returnMessage
	): array
	{
		if ($function instanceof \PhpParser\Node\Stmt\ClassMethod) {
			return $this->checkParametersAcceptor(
				$scope->getClassReflection()->getNativeMethod($function->name),
				$parameterMessage,
				$returnMessage
			);
		}
		if ($function instanceof \PhpParser\Node\Stmt\Function_) {
			$functionName = $function->name;
			if (isset($function->namespacedName)) {
				$functionName = (string) $function->namespacedName;
			}
			$functionNameName = new \PhpParser\Node\Name($functionName);
			if (!$this->broker->hasFunction($functionNameName)) {
				return [];
			}
			return $this->checkParametersAcceptor(
				$this->broker->getFunction($functionNameName),
				$parameterMessage,
				$returnMessage
			);
		}

		$errors = [];
		foreach ($function->getParams() as $param) {
			$class = $param->type instanceof \PhpParser\Node\NullableType
				? (string) $param->type->type
				: (string) $param->type;
			if ($class === '' || in_array($class, self::VALID_TYPEHINTS, true)) {
				continue;
			}

			if (!$this->broker->hasClass($class)) {
				$errors[] = sprintf($parameterMessage, $param->name, $class);
			} elseif ($this->checkClassCaseSensitivity) {
				$errors = array_merge(
					$errors,
					$this->classCaseSensitivityCheck->checkClassNames([$class])
				);
			}
		}

		$returnType = $function->getReturnType() instanceof \PhpParser\Node\NullableType
			? (string) $function->getReturnType()->type
			: (string) $function->getReturnType();

		if (
			$returnType !== ''
			&& !in_array($returnType, self::VALID_TYPEHINTS, true)
		) {
			if (!$this->broker->hasClass($returnType)) {
				$errors[] = sprintf($returnMessage, $returnType);
			} elseif ($this->checkClassCaseSensitivity) {
				$errors = array_merge(
					$errors,
					$this->classCaseSensitivityCheck->checkClassNames([$returnType])
				);
			}
		}

		return $errors;
	}

	private function checkParametersAcceptor(
		\PHPStan\Reflection\ParametersAcceptorWithPhpDocs $parametersAcceptor,
		string $parameterMessage,
		string $returnMessage
	): array
	{
		$errors = [];
		foreach ($parametersAcceptor->getParameters() as $parameter) {
			if ($this->checkThisOnly) {
				$referencedClasses = $parameter->getType()->getReferencedClasses();
			} else {
				$referencedClasses = array_merge(
					$parameter->getNativeType()->getReferencedClasses(),
					$parameter->getPhpDocType()->getReferencedClasses()
				);
			}
			foreach ($referencedClasses as $class) {
				if (!$this->broker->hasClass($class)) {
					$errors[] = sprintf($parameterMessage, $parameter->getName(), $class);
				}
			}

			if ($this->checkClassCaseSensitivity) {
				$errors = array_merge(
					$errors,
					$this->classCaseSensitivityCheck->checkClassNames($referencedClasses)
				);
			}
			if ($parameter->getType() instanceof \PHPStan\Type\NonexistentParentClassType) {
				$errors[] = sprintf($parameterMessage, $parameter->getName(), $parameter->getType()->describe());
			}
		}

		if ($this->checkThisOnly) {
			$returnTypeReferencedClasses = $parametersAcceptor->getReturnType()->getReferencedClasses();
		} else {
			$returnTypeReferencedClasses = array_merge(
				$parametersAcceptor->getNativeReturnType()->getReferencedClasses(),
				$parametersAcceptor->getPhpDocReturnType()->getReferencedClasses()
			);
		}

		foreach ($returnTypeReferencedClasses as $class) {
			if (!$this->broker->hasClass($class)) {
				$errors[] = sprintf($returnMessage, $class);
			}
		}

		if ($this->checkClassCaseSensitivity) {
			$errors = array_merge(
				$errors,
				$this->classCaseSensitivityCheck->checkClassNames($returnTypeReferencedClasses)
			);
		}
		if ($parametersAcceptor->getReturnType() instanceof \PHPStan\Type\NonexistentParentClassType) {
			$errors[] = sprintf($returnMessage, $parametersAcceptor->getReturnType()->describe());
		}

		return $errors;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules;
use PHPStan\Analyser\Scope;
use PHPStan\Type\MixedType;
use PHPStan\Type\ThisType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\VoidType;

class FunctionReturnTypeCheck
{

	/** @var \PhpParser\PrettyPrinter\Standard */
	private $printer;

	/** @var \PHPStan\Rules\RuleLevelHelper */
	private $ruleLevelHelper;

	public function __construct(
		\PhpParser\PrettyPrinter\Standard $printer,
		\PHPStan\Rules\RuleLevelHelper $ruleLevelHelper
	)
	{
		$this->printer = $printer;
		$this->ruleLevelHelper = $ruleLevelHelper;
	}

	/**
	 * @param \PHPStan\Analyser\Scope $scope
	 * @param \PHPStan\Type\Type $returnType
	 * @param \PhpParser\Node\Expr|null $returnValue
	 * @param string $emptyReturnStatementMessage
	 * @param string $voidMessage
	 * @param string $typeMismatchMessage
	 * @param bool $isGenerator
	 * @param bool $isAnonymousFunction
	 * @return string[]
	 */
	public function checkReturnType(
		\PHPStan\Analyser\Scope $scope,
		\PHPStan\Type\Type $returnType,
		\PhpParser\Node\Expr $returnValue = null,
		string $emptyReturnStatementMessage,
		string $voidMessage,
		string $typeMismatchMessage,
		bool $isGenerator,
		bool $isAnonymousFunction = false
	): array
	{
		if ($isGenerator) {
			return [];
		}
		if ($returnValue === null) {
			if (
				$returnType instanceof \PHPStan\Type\VoidType
				|| $returnType instanceof \PHPStan\Type\MixedType
			) {
				return [];
			}

			return [
				sprintf(
					$emptyReturnStatementMessage,
					$returnType->describe()
				),
			];
		}

		$returnValueType = $scope->getType($returnValue);
		if (
			\PHPStan\Type\TypeCombinator::removeNull($returnType) instanceof \PHPStan\Type\ThisType
			&& !$returnValueType instanceof \PHPStan\Type\ThisType
		) {
			if (\PHPStan\Type\TypeCombinator::containsNull($returnType) && $returnValueType instanceof \PHPStan\Type\NullType) {
				return [];
			}
			if (
				$returnValue instanceof \PhpParser\Node\Expr\Variable
				&& is_string($returnValue->name)
				&& $returnValue->name === 'this'
			) {
				return [];
			}

			return [
				sprintf(
					$typeMismatchMessage,
					'$this',
					$this->printer->prettyPrintExpr($returnValue)
				),
			];
		}

		if ($returnType instanceof \PHPStan\Type\VoidType) {
			return [
				sprintf(
					$voidMessage,
					$returnValueType->describe()
				),
			];
		}

		if (!$this->ruleLevelHelper->accepts($returnType, $returnValueType) && (!$isAnonymousFunction || $returnValueType->isDocumentableNatively())) {
			return [
				sprintf(
					$typeMismatchMessage,
					$returnType->describe(),
					$returnValueType->describe()
				),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Functions;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\ArrayType;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\UnionType;

class CallToCountOnlyWithArrayOrCountableRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Rules\RuleLevelHelper
	 */
	private $ruleLevelHelper;

	public function __construct(\PHPStan\Rules\RuleLevelHelper $ruleLevelHelper)
	{
		$this->ruleLevelHelper = $ruleLevelHelper;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\FuncCall::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\FuncCall $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (!$node->name instanceof \PhpParser\Node\Name) {
			return [];
		}

		$functionName = strtolower((string) $node->name);
		if ($functionName !== 'count') {
			return [];
		}

		if (!isset($node->args[0])) {
			return [];
		}

		$argumentType = $scope->getType($node->args[0]->value);
		$requiredType = new \PHPStan\Type\UnionType([
			new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType()),
			new \PHPStan\Type\ObjectType(\Countable::class),
		]);

		if (!$this->ruleLevelHelper->accepts($requiredType, $argumentType)) {
			return [
				sprintf(
					'Call to function count() with argument type %s will always result in number 1.',
					$argumentType->describe()
				),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Functions;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\Rules\FunctionCallParametersCheck;

class CallToFunctionParametersRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	/**
	 * @var \PHPStan\Rules\FunctionCallParametersCheck
	 */
	private $check;

	public function __construct(\PHPStan\Broker\Broker $broker, \PHPStan\Rules\FunctionCallParametersCheck $check)
	{
		$this->broker = $broker;
		$this->check = $check;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\FuncCall::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\FuncCall $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (!($node->name instanceof \PhpParser\Node\Name)) {
			return [];
		}

		if (!$this->broker->hasFunction($node->name, $scope)) {
			return [];
		}

		$function = $this->broker->getFunction($node->name, $scope);

		return $this->check->check(
			$function,
			$scope,
			$node,
			[
				'Function ' . $function->getName() . ' invoked with %d parameter, %d required.',
				'Function ' . $function->getName() . ' invoked with %d parameters, %d required.',
				'Function ' . $function->getName() . ' invoked with %d parameter, at least %d required.',
				'Function ' . $function->getName() . ' invoked with %d parameters, at least %d required.',
				'Function ' . $function->getName() . ' invoked with %d parameter, %d-%d required.',
				'Function ' . $function->getName() . ' invoked with %d parameters, %d-%d required.',
				'Parameter #%d %s of function ' . $function->getName() . ' expects %s, %s given.',
				'Result of function ' . $function->getName() . ' (void) is used.',
				'Parameter #%d %s of function ' . $function->getName() . ' is passed by reference, so it expects variables only.',
			]
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Functions;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;

class CallToNonExistentFunctionRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	public function __construct(\PHPStan\Broker\Broker $broker)
	{
		$this->broker = $broker;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\FuncCall::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\FuncCall $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (!($node->name instanceof \PhpParser\Node\Name)) {
			return [];
		}

		$lowercaseFunctionName = strtolower((string) $node->name);

		if (
			strpos($lowercaseFunctionName, 'apache_') === 0
			|| strpos($lowercaseFunctionName, 'fastcgi_') === 0
			|| $lowercaseFunctionName === 'getallheaders'
		) {
			return [];
		}

		if (!$this->broker->hasFunction($node->name, $scope)) {
			return [sprintf('Function %s not found.', (string) $node->name)];
		}

		$function = $this->broker->getFunction($node->name, $scope);
		$name = (string) $node->name;

		$calledFunctionName = $this->broker->resolveFunctionName($node->name, $scope);
		if (
			strtolower($function->getName()) === strtolower($calledFunctionName)
			&& $function->getName() !== $calledFunctionName
		) {
			return [sprintf('Call to function %s() with incorrect case: %s', $function->getName(), $name)];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Functions;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\FunctionReturnTypeCheck;
use PHPStan\Type\ObjectType;

class ClosureReturnTypeRule implements \PHPStan\Rules\Rule
{

	/** @var \PHPStan\Rules\FunctionReturnTypeCheck */
	private $returnTypeCheck;

	public function __construct(\PHPStan\Rules\FunctionReturnTypeCheck $returnTypeCheck)
	{
		$this->returnTypeCheck = $returnTypeCheck;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\Return_::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\Return_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (!$scope->isInAnonymousFunction()) {
			return [];
		}

		/** @var \PHPStan\Type\Type $returnType */
		$returnType = $scope->getAnonymousFunctionReturnType();
		$generatorType = new \PHPStan\Type\ObjectType(\Generator::class);

		return $this->returnTypeCheck->checkReturnType(
			$scope,
			$returnType,
			$node->expr,
			'Anonymous function should return %s but empty return statement found.',
			'Anonymous function with return type void returns %s but should not return anything.',
			'Anonymous function should return %s but returns %s.',
			$generatorType->isSuperTypeOf($returnType)->yes(),
			true
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Functions;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\FunctionDefinitionCheck;

class ExistingClassesInClosureTypehintsRule implements \PHPStan\Rules\Rule
{

	/** @var \PHPStan\Rules\FunctionDefinitionCheck */
	private $check;

	public function __construct(\PHPStan\Rules\FunctionDefinitionCheck $check)
	{
		$this->check = $check;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\Closure::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\Closure $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		return $this->check->checkFunction(
			$node,
			$scope,
			'Parameter $%s of anonymous function has invalid typehint type %s.',
			'Return typehint of anonymous function has invalid type %s.'
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Functions;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\FunctionDefinitionCheck;

class ExistingClassesInTypehintsRule implements \PHPStan\Rules\Rule
{

	/** @var \PHPStan\Rules\FunctionDefinitionCheck */
	private $check;

	public function __construct(\PHPStan\Rules\FunctionDefinitionCheck $check)
	{
		$this->check = $check;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\Function_::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\Function_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		return $this->check->checkFunction(
			$node,
			$scope,
			sprintf(
				'Parameter $%%s of function %s() has invalid typehint type %%s.',
				$node->namespacedName
			),
			sprintf(
				'Return typehint of function %s() has invalid type %%s.',
				$node->namespacedName
			)
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Functions;
use PHPStan\Analyser\Scope;

class InnerFunctionRule implements \PHPStan\Rules\Rule
{

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\Function_::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\Function_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if ($scope->getFunction() === null) {
			return [];
		}

		return [
			'Inner named functions are not supported by PHPStan. Consider refactoring to an anonymous function, class method, or a top-level-defined function. See issue #165 (https://github.com/phpstan/phpstan/issues/165) for more details.',
		];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Functions;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;

class NonExistentDefinedFunctionRule implements \PHPStan\Rules\Rule
{

	/** @var \PHPStan\Broker\Broker */
	private $broker;

	public function __construct(\PHPStan\Broker\Broker $broker)
	{
		$this->broker = $broker;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\Function_::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\Function_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		$functionName = $node->name;
		if (isset($node->namespacedName)) {
			$functionName = (string) $node->namespacedName;
		}
		$functionNameName = new \PhpParser\Node\Name($functionName);
		if ($this->broker->hasFunction($functionNameName)) {
			return [];
		}

		return [
			sprintf(
				'Function %s not found while trying to analyse it - autoloading is probably not configured properly.',
				$functionName
			),
		];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Functions;
use PHPStan\Analyser\Scope;

class PrintfParametersRule implements \PHPStan\Rules\Rule
{

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\FuncCall::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\FuncCall $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (!($node->name instanceof \PhpParser\Node\Name)) {
			return [];
		}

		$functionsArgumentPositions = [
			'printf' => 0,
			'sprintf' => 0,
			'sscanf' => 1,
			'fscanf' => 1,
		];
		$minimumNumberOfArguments = [
			'printf' => 1,
			'sprintf' => 1,
			'sscanf' => 3,
			'fscanf' => 3,
		];

		$name = strtolower((string) $node->name);
		if (!isset($functionsArgumentPositions[$name])) {
			return [];
		}

		$formatArgumentPosition = $functionsArgumentPositions[$name];

		$args = $node->args;
		$argsCount = count($args);
		if ($argsCount < $minimumNumberOfArguments[$name]) {
			return []; // caught by CallToFunctionParametersRule
		}

		$formatArg = $args[$formatArgumentPosition]->value;
		if (!($formatArg instanceof \PhpParser\Node\Scalar\String_)) {
			return []; // inspect only literal string format
		}

		foreach ($node->args as $arg) {
			if ($arg->unpack) {
				return [];
			}
		}

		$format = $formatArg->value;
		$placeHoldersCount = $this->getPlaceholdersCount($name, $format);
		$argsCount -= $formatArgumentPosition;

		if ($argsCount !== $placeHoldersCount + 1) {
			return [
				sprintf(
					sprintf(
						'%s, %s.',
						$placeHoldersCount === 1 ? 'Call to %s contains %d placeholder' : 'Call to %s contains %d placeholders',
						$argsCount - 1 === 1 ? '%d value given' : '%d values given'
					),
					$name,
					$placeHoldersCount,
					$argsCount - 1
				),
			];
		}

		return [];
	}

	private function getPlaceholdersCount(string $functionName, string $format): int
	{
		$specifiers = in_array($functionName, ['sprintf', 'printf'], true) ? '[bcdeEfFgGosuxX]' : '(?:[cdDeEfinosuxX]|\[[^\]]+\])';
		$pattern = '~(?<before>%*)%(?:(?<position>\d+)\$)?[-+]?(?:[ 0]|(?:\'[^%]))?-?\d*(?:\.\d*)?' . $specifiers . '~';

		if (!preg_match_all($pattern, $format, $matches, PREG_SET_ORDER)) {
			return 0;
		}

		$placeholders = array_filter($matches, function (array $match): bool {
			return strlen($match['before']) % 2 === 0;
		});

		if (count($placeholders) === 0) {
			return 0;
		}

		$maxPositionedNumber = 0;
		$maxOrdinaryNumber = 0;
		foreach ($placeholders as $placeholder) {
			if (isset($placeholder['position']) && $placeholder['position'] !== '') {
				$maxPositionedNumber = max((int) $placeholder['position'], $maxPositionedNumber);
			} else {
				$maxOrdinaryNumber++;
			}
		}

		return max($maxPositionedNumber, $maxOrdinaryNumber);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Functions;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection;
use PHPStan\Reflection\Php\PhpMethodFromParserNodeReflection;
use PHPStan\Rules\FunctionReturnTypeCheck;

class ReturnTypeRule implements \PHPStan\Rules\Rule
{

	/** @var \PHPStan\Rules\FunctionReturnTypeCheck */
	private $returnTypeCheck;

	public function __construct(\PHPStan\Rules\FunctionReturnTypeCheck $returnTypeCheck)
	{
		$this->returnTypeCheck = $returnTypeCheck;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\Return_::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\Return_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if ($scope->getFunction() === null) {
			return [];
		}

		if ($scope->isInAnonymousFunction()) {
			return [];
		}

		$function = $scope->getFunction();
		if (
			!($function instanceof \PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection)
			|| $function instanceof \PHPStan\Reflection\Php\PhpMethodFromParserNodeReflection
		) {
			return [];
		}

		$reflection = null;
		if (function_exists($function->getName())) {
			$reflection = new \ReflectionFunction($function->getName());
		}

		return $this->returnTypeCheck->checkReturnType(
			$scope,
			$function->getReturnType(),
			$node->expr,
			sprintf(
				'Function %s() should return %%s but empty return statement found.',
				$function->getName()
			),
			sprintf(
				'Function %s() with return type void returns %%s but should not return anything.',
				$function->getName()
			),
			sprintf(
				'Function %s() should return %%s but returns %%s.',
				$function->getName()
			),
			$reflection !== null && $reflection->isGenerator(),
			false
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Functions;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\UnusedFunctionParametersCheck;

class UnusedClosureUsesRule implements \PHPStan\Rules\Rule
{

	/** @var \PHPStan\Rules\UnusedFunctionParametersCheck */
	private $check;

	public function __construct(\PHPStan\Rules\UnusedFunctionParametersCheck $check)
	{
		$this->check = $check;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\Closure::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\Closure $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (count($node->uses) === 0) {
			return [];
		}

		return $this->check->getUnusedParameters(
			array_map(function (\PhpParser\Node\Expr\ClosureUse $use): string {
				return $use->var;
			}, $node->uses),
			$node->stmts,
			'Anonymous function has an unused use $%s.'
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Methods;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\UnionType;

class CallMethodsOnPossiblyNullRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Rules\RuleLevelHelper
	 */
	private $ruleLevelHelper;

	/**
	 * @var bool
	 */
	private $checkThisOnly;

	public function __construct(
		\PHPStan\Rules\RuleLevelHelper $ruleLevelHelper,
		bool $checkThisOnly
	)
	{
		$this->ruleLevelHelper = $ruleLevelHelper;
		$this->checkThisOnly = $checkThisOnly;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\MethodCall::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\MethodCall $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (!is_string($node->name)) {
			return [];
		}

		if ($this->checkThisOnly && !$this->ruleLevelHelper->isThis($node->var)) {
			return [];
		}

		$type = $scope->getType($node->var);
		if (!$type instanceof \PHPStan\Type\UnionType) {
			return [];
		}

		if (\PHPStan\Type\TypeCombinator::containsNull($type)) {
			return [
				sprintf(
					'Calling method %s() on possibly null value of type %s.',
					$node->name,
					$type->describe()
				),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Methods;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\Rules\FunctionCallParametersCheck;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\ErrorType;

class CallMethodsRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	/**
	 * @var \PHPStan\Rules\FunctionCallParametersCheck
	 */
	private $check;

	/**
	 * @var \PHPStan\Rules\RuleLevelHelper
	 */
	private $ruleLevelHelper;

	public function __construct(
		\PHPStan\Broker\Broker $broker,
		\PHPStan\Rules\FunctionCallParametersCheck $check,
		\PHPStan\Rules\RuleLevelHelper $ruleLevelHelper
	)
	{
		$this->broker = $broker;
		$this->check = $check;
		$this->ruleLevelHelper = $ruleLevelHelper;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\MethodCall::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\MethodCall $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (!is_string($node->name)) {
			return [];
		}

		$name = $node->name;
		$typeResult = $this->ruleLevelHelper->findTypeToCheck(
			$scope,
			$node->var,
			sprintf('Call to method %s() on an unknown class %%s.', $name)
		);
		$type = $typeResult->getType();
		if ($type instanceof \PHPStan\Type\ErrorType) {
			return $typeResult->getUnknownClassErrors();
		}
		if (!$type->canCallMethods()) {
			return [
				sprintf('Cannot call method %s() on %s.', $name, $type->describe()),
			];
		}

		if (!$type->hasMethod($name)) {
			if (count($typeResult->getReferencedClasses()) === 1) {
				$referencedClass = $typeResult->getReferencedClasses()[0];
				$methodClassReflection = $this->broker->getClass($referencedClass);
				$parentClassReflection = $methodClassReflection->getParentClass();
				while ($parentClassReflection !== false) {
					if ($parentClassReflection->hasMethod($name)) {
						return [
							sprintf(
								'Call to private method %s() of parent class %s.',
								$parentClassReflection->getMethod($name, $scope)->getName(),
								$parentClassReflection->getDisplayName()
							),
						];
					}

					$parentClassReflection = $parentClassReflection->getParentClass();
				}
			}

			return [
				sprintf(
					'Call to an undefined method %s::%s().',
					$type->describe(),
					$name
				),
			];
		}

		$methodReflection = $type->getMethod($name, $scope);
		$messagesMethodName = $methodReflection->getDeclaringClass()->getDisplayName() . '::' . $methodReflection->getName() . '()';
		$errors = [];
		if (!$scope->canCallMethod($methodReflection)) {
			$errors[] = sprintf(
				'Call to %s method %s() of class %s.',
				$methodReflection->isPrivate() ? 'private' : 'protected',
				$methodReflection->getName(),
				$methodReflection->getDeclaringClass()->getDisplayName()
			);
		}

		$errors = array_merge($errors, $this->check->check(
			$methodReflection,
			$scope,
			$node,
			[
				'Method ' . $messagesMethodName . ' invoked with %d parameter, %d required.',
				'Method ' . $messagesMethodName . ' invoked with %d parameters, %d required.',
				'Method ' . $messagesMethodName . ' invoked with %d parameter, at least %d required.',
				'Method ' . $messagesMethodName . ' invoked with %d parameters, at least %d required.',
				'Method ' . $messagesMethodName . ' invoked with %d parameter, %d-%d required.',
				'Method ' . $messagesMethodName . ' invoked with %d parameters, %d-%d required.',
				'Parameter #%d %s of method ' . $messagesMethodName . ' expects %s, %s given.',
				'Result of method ' . $messagesMethodName . ' (void) is used.',
				'Parameter #%d %s of method ' . $messagesMethodName . ' is passed by reference, so it expects variables only.',
			]
		));

		if (strtolower($methodReflection->getName()) === strtolower($name) && $methodReflection->getName() !== $name) {
			$errors[] = sprintf('Call to method %s with incorrect case: %s', $messagesMethodName, $name);
		}

		return $errors;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Methods;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Rules\ClassCaseSensitivityCheck;
use PHPStan\Rules\FunctionCallParametersCheck;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\ErrorType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\TypeWithClassName;

class CallStaticMethodsRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	/**
	 * @var \PHPStan\Rules\FunctionCallParametersCheck
	 */
	private $check;

	/**
	 * @var \PHPStan\Rules\RuleLevelHelper
	 */
	private $ruleLevelHelper;

	/**
	 * @var \PHPStan\Rules\ClassCaseSensitivityCheck
	 */
	private $classCaseSensitivityCheck;

	public function __construct(
		\PHPStan\Broker\Broker $broker,
		\PHPStan\Rules\FunctionCallParametersCheck $check,
		\PHPStan\Rules\RuleLevelHelper $ruleLevelHelper,
		\PHPStan\Rules\ClassCaseSensitivityCheck $classCaseSensitivityCheck
	)
	{
		$this->broker = $broker;
		$this->check = $check;
		$this->ruleLevelHelper = $ruleLevelHelper;
		$this->classCaseSensitivityCheck = $classCaseSensitivityCheck;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\StaticCall::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\StaticCall $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		$methodName = $node->name;
		if (!is_string($methodName)) {
			return [];
		}

		$class = $node->class;
		$errors = [];
		if ($class instanceof \PhpParser\Node\Name) {
			$className = (string) $class;
			if ($className === 'self' || $className === 'static') {
				if (!$scope->isInClass()) {
					return [
						sprintf(
							'Calling %s::%s() outside of class scope.',
							$class,
							$methodName
						),
					];
				}
				$className = $scope->getClassReflection()->getName();
			} elseif ($className === 'parent') {
				if (!$scope->isInClass()) {
					return [
						sprintf(
							'Calling %s::%s() outside of class scope.',
							$className,
							$methodName
						),
					];
				}
				$currentClassReflection = $scope->getClassReflection();
				if ($currentClassReflection->getParentClass() === false) {
					return [
						sprintf(
							'%s::%s() calls parent::%s() but %s does not extend any class.',
							$scope->getClassReflection()->getDisplayName(),
							$scope->getFunctionName(),
							$methodName,
							$scope->getClassReflection()->getDisplayName()
						),
					];
				}

				if ($scope->getFunctionName() === null) {
					throw new \PHPStan\ShouldNotHappenException();
				}

				$className = $currentClassReflection->getParentClass()->getName();
			} else {
				if (!$this->broker->hasClass($className)) {
					return [
						sprintf('Call to static method %s() on an unknown class %s.', $methodName, $className),
					];
				} else {
					$errors = $this->classCaseSensitivityCheck->checkClassNames([$className]);
				}

				$className = $this->broker->getClass($className)->getName();
			}

			$classType = new \PHPStan\Type\ObjectType($className);
		} else {
			$classTypeResult = $this->ruleLevelHelper->findTypeToCheck(
				$scope,
				$class,
				sprintf('Call to static method %s() on an unknown class %%s.', $methodName)
			);
			$classType = $classTypeResult->getType();
			if ($classType instanceof \PHPStan\Type\ErrorType) {
				return $classTypeResult->getUnknownClassErrors();
			}
		}

		if ($classType instanceof \PHPStan\Type\StringType) {
			return [];
		}

		$typeForDescribe = $classType;
		$classType = \PHPStan\Type\TypeCombinator::remove($classType, new \PHPStan\Type\StringType());

		if (!$classType->canCallMethods()) {
			return array_merge($errors, [
				sprintf('Cannot call static method %s() on %s.', $methodName, $typeForDescribe->describe()),
			]);
		}

		if (!$classType->hasMethod($methodName)) {
			return array_merge($errors, [
				sprintf(
					'Call to an undefined static method %s::%s().',
					$typeForDescribe->describe(),
					$methodName
				),
			]);
		}

		$method = $classType->getMethod($methodName, $scope);
		if (!$method->isStatic()) {
			$function = $scope->getFunction();
			if (
				!$function instanceof \PHPStan\Reflection\MethodReflection
				|| $function->isStatic()
				|| !$scope->isInClass()
				|| (
					$classType instanceof \PHPStan\Type\TypeWithClassName
					&& $scope->getClassReflection()->getName() !== $classType->getClassName()
					&& !$scope->getClassReflection()->isSubclassOf($classType->getClassName())
				)
			) {
				return array_merge($errors, [
					sprintf(
						'Static call to instance method %s::%s().',
						$method->getDeclaringClass()->getDisplayName(),
						$method->getName()
					),
				]);
			}
		}

		if (!$scope->canCallMethod($method)) {
			$errors = array_merge($errors, [
				sprintf(
					'Call to %s %s %s() of class %s.',
					$method->isPrivate() ? 'private' : 'protected',
					$method->isStatic() ? 'static method' : 'method',
					$method->getName(),
					$method->getDeclaringClass()->getDisplayName()
				),
			]);
		}

		$lowercasedMethodName = sprintf(
			'%s %s',
			$method->isStatic() ? 'static method' : 'method',
			$method->getDeclaringClass()->getDisplayName() . '::' . $method->getName() . '()'
		);
		$displayMethodName = sprintf(
			'%s %s',
			$method->isStatic() ? 'Static method' : 'Method',
			$method->getDeclaringClass()->getDisplayName() . '::' . $method->getName() . '()'
		);

		$errors = array_merge($errors, $this->check->check(
			$method,
			$scope,
			$node,
			[
				$displayMethodName . ' invoked with %d parameter, %d required.',
				$displayMethodName . ' invoked with %d parameters, %d required.',
				$displayMethodName . ' invoked with %d parameter, at least %d required.',
				$displayMethodName . ' invoked with %d parameters, at least %d required.',
				$displayMethodName . ' invoked with %d parameter, %d-%d required.',
				$displayMethodName . ' invoked with %d parameters, %d-%d required.',
				'Parameter #%d %s of ' . $lowercasedMethodName . ' expects %s, %s given.',
				'Result of ' . $lowercasedMethodName . ' (void) is used.',
				'Parameter #%d %s of ' . $lowercasedMethodName . ' is passed by reference, so it expects variables only.',
			]
		));

		if ($method->getName() !== $methodName) {
			$errors[] = sprintf('Call to %s with incorrect case: %s', $lowercasedMethodName, $methodName);
		}

		return $errors;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Methods;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\FunctionDefinitionCheck;

class ExistingClassesInTypehintsRule implements \PHPStan\Rules\Rule
{

	/** @var \PHPStan\Rules\FunctionDefinitionCheck */
	private $check;

	public function __construct(\PHPStan\Rules\FunctionDefinitionCheck $check)
	{
		$this->check = $check;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\ClassMethod::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\ClassMethod $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		return $this->check->checkFunction(
			$node,
			$scope,
			sprintf(
				'Parameter $%%s of method %s::%s() has invalid typehint type %%s.',
				$scope->getClassReflection()->getDisplayName(),
				$node->name
			),
			sprintf(
				'Return typehint of method %s::%s() has invalid type %%s.',
				$scope->getClassReflection()->getDisplayName(),
				$node->name
			)
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Methods;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Rules\FunctionReturnTypeCheck;

class ReturnTypeRule implements \PHPStan\Rules\Rule
{

	/** @var \PHPStan\Rules\FunctionReturnTypeCheck */
	private $returnTypeCheck;

	public function __construct(\PHPStan\Rules\FunctionReturnTypeCheck $returnTypeCheck)
	{
		$this->returnTypeCheck = $returnTypeCheck;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\Return_::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\Return_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if ($scope->getFunction() === null) {
			return [];
		}

		if ($scope->isInAnonymousFunction()) {
			return [];
		}

		$method = $scope->getFunction();
		if (!($method instanceof \PHPStan\Reflection\MethodReflection)) {
			return [];
		}

		$reflection = null;
		if ($method->getDeclaringClass()->getNativeReflection()->hasMethod($method->getName())) {
			$reflection = $method->getDeclaringClass()->getNativeReflection()->getMethod($method->getName());
		}

		return $this->returnTypeCheck->checkReturnType(
			$scope,
			$method->getReturnType(),
			$node->expr,
			sprintf(
				'Method %s::%s() should return %%s but empty return statement found.',
				$method->getDeclaringClass()->getDisplayName(),
				$method->getName()
			),
			sprintf(
				'Method %s::%s() with return type void returns %%s but should not return anything.',
				$method->getDeclaringClass()->getDisplayName(),
				$method->getName()
			),
			sprintf(
				'Method %s::%s() should return %%s but returns %%s.',
				$method->getDeclaringClass()->getDisplayName(),
				$method->getName()
			),
			$reflection !== null && $reflection->isGenerator(),
			false
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Namespaces;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\Rules\ClassCaseSensitivityCheck;

class ExistingNamesInGroupUseRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	/**
	 * @var \PHPStan\Rules\ClassCaseSensitivityCheck
	 */
	private $classCaseSensitivityCheck;

	public function __construct(
		\PHPStan\Broker\Broker $broker,
		\PHPStan\Rules\ClassCaseSensitivityCheck $classCaseSensitivityCheck
	)
	{
		$this->broker = $broker;
		$this->classCaseSensitivityCheck = $classCaseSensitivityCheck;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\GroupUse::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\GroupUse $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		$messages = [];
		foreach ($node->uses as $use) {
			$message = null;

			/** @var Node\Name $name */
			$name = \PhpParser\Node\Name::concat($node->prefix, $use->name);
			if (
				$node->type === \PhpParser\Node\Stmt\Use_::TYPE_CONSTANT
				|| $use->type === \PhpParser\Node\Stmt\Use_::TYPE_CONSTANT
			) {
				$message = $this->checkConstant($name);
			} elseif (
				$node->type === \PhpParser\Node\Stmt\Use_::TYPE_FUNCTION
				|| $use->type === \PhpParser\Node\Stmt\Use_::TYPE_FUNCTION
			) {
				$message = $this->checkFunction($name);
			} elseif ($use->type === \PhpParser\Node\Stmt\Use_::TYPE_NORMAL) {
				$message = $this->checkClass($name);
			} else {
				throw new \PHPStan\ShouldNotHappenException();
			}

			if ($message !== null) {
				$messages[] = $message;
			}
		}

		return $messages;
	}

	/**
	 * @param \PhpParser\Node\Name $name
	 * @return string|null
	 */
	private function checkConstant(\PhpParser\Node\Name $name)
	{
		if (!$this->broker->hasConstant($name)) {
			return sprintf('Used constant %s not found.', (string) $name);
		}

		return null;
	}

	/**
	 * @param \PhpParser\Node\Name $name
	 * @return string|null
	 */
	private function checkFunction(\PhpParser\Node\Name $name)
	{
		if (!$this->broker->hasFunction($name)) {
			return sprintf('Used function %s not found.', (string) $name);
		}

		$functionReflection = $this->broker->getFunction($name);
		$realName = $functionReflection->getName();
		$usedName = (string) $name;
		if ($realName !== $usedName) {
			return sprintf(
				'Function %s used with incorrect case: %s.',
				$realName,
				$usedName
			);
		}

		return null;
	}

	/**
	 * @param \PhpParser\Node\Name $name
	 * @return string|null
	 */
	private function checkClass(\PhpParser\Node\Name $name)
	{
		$messages = $this->classCaseSensitivityCheck->checkClassNames([(string) $name]);
		if (count($messages) === 0) {
			return null;
		} elseif (count($messages) === 1) {
			return $messages[0];
		}

		throw new \PHPStan\ShouldNotHappenException();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Namespaces;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\Rules\ClassCaseSensitivityCheck;

class ExistingNamesInUseRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	/**
	 * @var \PHPStan\Rules\ClassCaseSensitivityCheck
	 */
	private $classCaseSensitivityCheck;

	public function __construct(
		\PHPStan\Broker\Broker $broker,
		\PHPStan\Rules\ClassCaseSensitivityCheck $classCaseSensitivityCheck
	)
	{
		$this->broker = $broker;
		$this->classCaseSensitivityCheck = $classCaseSensitivityCheck;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\Use_::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\Use_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if ($node->type === \PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN) {
			throw new \PHPStan\ShouldNotHappenException();
		}

		foreach ($node->uses as $use) {
			if ($use->type !== \PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN) {
				throw new \PHPStan\ShouldNotHappenException();
			}
		}

		if ($node->type === \PhpParser\Node\Stmt\Use_::TYPE_CONSTANT) {
			return $this->checkConstants($node->uses);
		}

		if ($node->type === \PhpParser\Node\Stmt\Use_::TYPE_FUNCTION) {
			return $this->checkFunctions($node->uses);
		}

		return $this->checkClasses($node->uses);
	}

	/**
	 * @param \PhpParser\Node\Stmt\UseUse[] $uses
	 * @return string[]
	 */
	private function checkConstants(array $uses): array
	{
		$messages = [];
		foreach ($uses as $use) {
			if (!$this->broker->hasConstant($use->name)) {
				$messages[] = sprintf('Used constant %s not found.', (string) $use->name);
			}
		}

		return $messages;
	}

	/**
	 * @param \PhpParser\Node\Stmt\UseUse[] $uses
	 * @return string[]
	 */
	private function checkFunctions(array $uses): array
	{
		$messages = [];
		foreach ($uses as $use) {
			if (!$this->broker->hasFunction($use->name)) {
				$messages[] = sprintf('Used function %s not found.', (string) $use->name);
			} else {
				$functionReflection = $this->broker->getFunction($use->name);
				$realName = $functionReflection->getName();
				$usedName = (string) $use->name;
				if ($realName !== $usedName) {
					$messages[] = sprintf(
						'Function %s used with incorrect case: %s.',
						$realName,
						$usedName
					);
				}
			}
		}

		return $messages;
	}

	/**
	 * @param \PhpParser\Node\Stmt\UseUse[] $uses
	 * @return string[]
	 */
	private function checkClasses(array $uses): array
	{
		return $this->classCaseSensitivityCheck->checkClassNames(
			array_map(function (\PhpParser\Node\Stmt\UseUse $use): string {
				return (string) $use->name;
			}, $uses)
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\PhpDoc;
use PHPStan\Analyser\Scope;
use PHPStan\Type\ArrayType;
use PHPStan\Type\ErrorType;
use PHPStan\Type\FileTypeMapper;
use PHPStan\Type\Type;

class IncompatiblePhpDocTypeRule implements \PHPStan\Rules\Rule
{

	/** @var FileTypeMapper */
	private $fileTypeMapper;

	public function __construct(\PHPStan\Type\FileTypeMapper $fileTypeMapper)
	{
		$this->fileTypeMapper = $fileTypeMapper;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\FunctionLike::class;
	}

	/**
	 * @param \PhpParser\Node\FunctionLike $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		$docComment = $node->getDocComment();
		if ($docComment === null) {
			return [];
		}

		$resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc(
			$scope->getFile(),
			$scope->isInClass() ? $scope->getClassReflection()->getName() : null,
			$docComment->getText()
		);
		$nativeParameterTypes = $this->getNativeParameterTypes($node, $scope);
		$nativeReturnType = $this->getNativeReturnType($node, $scope);

		$errors = [];

		foreach ($resolvedPhpDoc->getParamTags() as $parameterName => $phpDocParamTag) {
			$phpDocParamType = $phpDocParamTag->getType();
			if (!isset($nativeParameterTypes[$parameterName])) {
				$errors[] = sprintf(
					'PHPDoc tag @param references unknown parameter $%s',
					$parameterName
				);

			} elseif ($phpDocParamType instanceof \PHPStan\Type\ErrorType) {
				$errors[] = sprintf(
					'PHPDoc tag @param for parameter $%s contains unresolvable type',
					$parameterName
				);

			} else {
				$nativeParamType = $nativeParameterTypes[$parameterName];
				$isParamSuperType = $nativeParamType->isSuperTypeOf($phpDocParamType);

				if (
					$phpDocParamTag->isVariadic()
					&& $nativeParamType instanceof \PHPStan\Type\ArrayType
					&& $nativeParamType->getItemType() instanceof \PHPStan\Type\ArrayType
				) {
					continue;
				}

				if ($isParamSuperType->no()) {
					$errors[] = sprintf(
						'PHPDoc tag @param for parameter $%s with type %s is incompatible with native type %s',
						$parameterName,
						$phpDocParamType->describe(),
						$nativeParamType->describe()
					);

				} elseif ($isParamSuperType->maybe()) {
					$errors[] = sprintf(
						'PHPDoc tag @param for parameter $%s with type %s is not subtype of native type %s',
						$parameterName,
						$phpDocParamType->describe(),
						$nativeParamType->describe()
					);
				}
			}
		}

		if ($resolvedPhpDoc->getReturnTag() !== null) {
			$phpDocReturnType = $resolvedPhpDoc->getReturnTag()->getType();

			if ($phpDocReturnType instanceof \PHPStan\Type\ErrorType) {
				$errors[] = 'PHPDoc tag @return contains unresolvable type';

			} else {
				$isReturnSuperType = $nativeReturnType->isSuperTypeOf($phpDocReturnType);
				if ($isReturnSuperType->no()) {
					$errors[] = sprintf(
						'PHPDoc tag @return with type %s is incompatible with native type %s',
						$phpDocReturnType->describe(),
						$nativeReturnType->describe()
					);

				} elseif ($isReturnSuperType->maybe()) {
					$errors[] = sprintf(
						'PHPDoc tag @return with type %s is not subtype of native type %s',
						$phpDocReturnType->describe(),
						$nativeReturnType->describe()
					);
				}
			}
		}

		return $errors;
	}

	/**
	 * @param Node\FunctionLike $node
	 * @param Scope $scope
	 * @return Type[]
	 */
	private function getNativeParameterTypes(\PhpParser\Node\FunctionLike $node, \PHPStan\Analyser\Scope $scope): array
	{
		$nativeParameterTypes = [];
		foreach ($node->getParams() as $parameter) {
			$isNullable = $scope->isParameterValueNullable($parameter);
			$nativeParameterTypes[$parameter->name] = $scope->getFunctionType(
				$parameter->type,
				$isNullable,
				$parameter->variadic
			);
		}

		return $nativeParameterTypes;
	}

	private function getNativeReturnType(\PhpParser\Node\FunctionLike $node, \PHPStan\Analyser\Scope $scope): \PHPStan\Type\Type
	{
		return $scope->getFunctionType($node->getReturnType(), false, false);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\PhpDoc;
use PHPStan\Analyser\Scope;
use PHPStan\PhpDocParser\Ast\PhpDoc\InvalidTagValueNode;
use PHPStan\PhpDocParser\Lexer\Lexer;
use PHPStan\PhpDocParser\Parser\PhpDocParser;
use PHPStan\PhpDocParser\Parser\TokenIterator;

class InvalidPhpDocTagValueRule implements \PHPStan\Rules\Rule
{

	/** @var Lexer */
	private $phpDocLexer;

	/** @var PhpDocParser */
	private $phpDocParser;

	public function __construct(\PHPStan\PhpDocParser\Lexer\Lexer $phpDocLexer, \PHPStan\PhpDocParser\Parser\PhpDocParser $phpDocParser)
	{
		$this->phpDocLexer = $phpDocLexer;
		$this->phpDocParser = $phpDocParser;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node::class;
	}

	/**
	 * @param \PhpParser\Node $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (
			!$node instanceof \PhpParser\Node\Stmt\ClassLike
			&& !$node instanceof \PhpParser\Node\FunctionLike
			&& !$node instanceof \PhpParser\Node\Stmt\Foreach_
			&& !$node instanceof \PhpParser\Node\Stmt\Property
			&& !$node instanceof \PhpParser\Node\Expr\Assign
			&& !$node instanceof \PhpParser\Node\Expr\AssignRef
		) {
			return [];
		}

		$docComment = $node->getDocComment();
		if ($docComment === null) {
			return [];
		}

		$phpDocString = $docComment->getText();
		$tokens = new \PHPStan\PhpDocParser\Parser\TokenIterator($this->phpDocLexer->tokenize($phpDocString));
		$phpDocNode = $this->phpDocParser->parse($tokens);

		$errors = [];
		foreach ($phpDocNode->getTags() as $phpDocTag) {
			if ($phpDocTag->value instanceof \PHPStan\PhpDocParser\Ast\PhpDoc\InvalidTagValueNode) {
				$errors[] = sprintf(
					'PHPDoc tag %s has invalid value (%s): %s',
					$phpDocTag->name,
					$phpDocTag->value->value,
					$phpDocTag->value->exception->getMessage()
				);
			}
		}

		return $errors;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Properties;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\UnionType;

class AccessPropertiesOnPossiblyNullRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Rules\RuleLevelHelper
	 */
	private $ruleLevelHelper;

	/**
	 * @var bool
	 */
	private $checkThisOnly;

	public function __construct(
		\PHPStan\Rules\RuleLevelHelper $ruleLevelHelper,
		bool $checkThisOnly
	)
	{
		$this->ruleLevelHelper = $ruleLevelHelper;
		$this->checkThisOnly = $checkThisOnly;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\PropertyFetch::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\PropertyFetch $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (!is_string($node->name)) {
			return [];
		}

		if ($this->checkThisOnly && !$this->ruleLevelHelper->isThis($node->var)) {
			return [];
		}

		$type = $scope->getType($node->var);
		if (!$type instanceof \PHPStan\Type\UnionType) {
			return [];
		}

		if (\PHPStan\Type\TypeCombinator::containsNull($type)) {
			return [
				sprintf(
					'Accessing property $%s on possibly null value of type %s.',
					$node->name,
					$type->describe()
				),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Properties;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\ErrorType;

class AccessPropertiesRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	/**
	 * @var \PHPStan\Rules\RuleLevelHelper
	 */
	private $ruleLevelHelper;

	public function __construct(
		\PHPStan\Broker\Broker $broker,
		\PHPStan\Rules\RuleLevelHelper $ruleLevelHelper
	)
	{
		$this->broker = $broker;
		$this->ruleLevelHelper = $ruleLevelHelper;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\PropertyFetch::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\PropertyFetch $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (!is_string($node->name)) {
			return [];
		}

		$name = $node->name;
		$typeResult = $this->ruleLevelHelper->findTypeToCheck(
			$scope,
			$node->var,
			sprintf('Access to property $%s on an unknown class %%s.', $name)
		);
		$type = $typeResult->getType();
		if ($type instanceof \PHPStan\Type\ErrorType) {
			return $typeResult->getUnknownClassErrors();
		}
		if (!$type->canAccessProperties()) {
			return [
				sprintf('Cannot access property $%s on %s.', $name, $type->describe()),
			];
		}

		if (!$type->hasProperty($name)) {
			if ($scope->isSpecified($node)) {
				return [];
			}

			if (count($typeResult->getReferencedClasses()) === 1) {
				$referencedClass = $typeResult->getReferencedClasses()[0];
				$propertyClassReflection = $this->broker->getClass($referencedClass);
				$parentClassReflection = $propertyClassReflection->getParentClass();
				while ($parentClassReflection !== false) {
					if ($parentClassReflection->hasProperty($name)) {
						return [
							sprintf(
								'Access to private property $%s of parent class %s.',
								$name,
								$parentClassReflection->getDisplayName()
							),
						];
					}

					$parentClassReflection = $parentClassReflection->getParentClass();
				}
			}

			return [
				sprintf(
					'Access to an undefined property %s::$%s.',
					$type->describe(),
					$name
				),
			];
		}

		$propertyReflection = $type->getProperty($name, $scope);
		if (!$scope->canAccessProperty($propertyReflection)) {
			return [
				sprintf(
					'Access to %s property %s::$%s.',
					$propertyReflection->isPrivate() ? 'private' : 'protected',
					$type->describe(),
					$name
				),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Properties;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\Rules\ClassCaseSensitivityCheck;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\ErrorType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use PHPStan\Type\TypeCombinator;

class AccessStaticPropertiesRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	/**
	 * @var \PHPStan\Rules\RuleLevelHelper
	 */
	private $ruleLevelHelper;

	/**
	 * @var \PHPStan\Rules\ClassCaseSensitivityCheck
	 */
	private $classCaseSensitivityCheck;

	public function __construct(
		\PHPStan\Broker\Broker $broker,
		\PHPStan\Rules\RuleLevelHelper $ruleLevelHelper,
		\PHPStan\Rules\ClassCaseSensitivityCheck $classCaseSensitivityCheck
	)
	{
		$this->broker = $broker;
		$this->ruleLevelHelper = $ruleLevelHelper;
		$this->classCaseSensitivityCheck = $classCaseSensitivityCheck;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\StaticPropertyFetch::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\StaticPropertyFetch $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (!is_string($node->name)) {
			return [];
		}

		$name = $node->name;
		$messages = [];
		if ($node->class instanceof \PhpParser\Node\Name) {
			$class = (string) $node->class;
			if ($class === 'self' || $class === 'static') {
				if (!$scope->isInClass()) {
					return [
						sprintf(
							'Accessing %s::$%s outside of class scope.',
							$class,
							$name
						),
					];
				}
				$className = $scope->getClassReflection()->getName();
			} elseif ($class === 'parent') {
				if (!$scope->isInClass()) {
					return [
						sprintf(
							'Accessing %s::$%s outside of class scope.',
							$class,
							$name
						),
					];
				}
				if ($scope->getClassReflection()->getParentClass() === false) {
					return [
						sprintf(
							'%s::%s() accesses parent::$%s but %s does not extend any class.',
							$scope->getClassReflection()->getDisplayName(),
							$scope->getFunctionName(),
							$name,
							$scope->getClassReflection()->getDisplayName()
						),
					];
				}

				if ($scope->getFunctionName() === null) {
					throw new \PHPStan\ShouldNotHappenException();
				}

				$currentMethodReflection = $scope->getClassReflection()->getNativeMethod($scope->getFunctionName());
				if (!$currentMethodReflection->isStatic()) {
					// calling parent::method() from instance method
					return [];
				}

				$className = $scope->getClassReflection()->getParentClass()->getName();
			} else {
				if (!$this->broker->hasClass($class)) {
					return [
						sprintf(
							'Access to static property $%s on an unknown class %s.',
							$name,
							$class
						),
					];
				} else {
					$messages = $this->classCaseSensitivityCheck->checkClassNames([$class]);
				}
				$className = $this->broker->getClass($class)->getName();
			}

			$classType = new \PHPStan\Type\ObjectType($className);
		} else {
			$classTypeResult = $this->ruleLevelHelper->findTypeToCheck(
				$scope,
				$node->class,
				sprintf('Access to static property $%s on an unknown class %%s.', $name)
			);
			$classType = $classTypeResult->getType();
			if ($classType instanceof \PHPStan\Type\ErrorType) {
				return $classTypeResult->getUnknownClassErrors();
			}
		}

		if ($classType instanceof \PHPStan\Type\StringType) {
			return [];
		}

		$typeForDescribe = $classType;
		$classType = \PHPStan\Type\TypeCombinator::remove($classType, new \PHPStan\Type\StringType());

		if (!$classType->canAccessProperties()) {
			return array_merge($messages, [
				sprintf('Cannot access static property $%s on %s.', $name, $typeForDescribe->describe()),
			]);
		}

		if (!$classType->hasProperty($name)) {
			if ($scope->isSpecified($node)) {
				return $messages;
			}

			return array_merge($messages, [
				sprintf(
					'Access to an undefined static property %s::$%s.',
					$typeForDescribe->describe(),
					$name
				),
			]);
		}

		$property = $classType->getProperty($name, $scope);
		if (!$property->isStatic()) {
			return array_merge($messages, [
				sprintf(
					'Static access to instance property %s::$%s.',
					$property->getDeclaringClass()->getDisplayName(),
					$name
				),
			]);
		}

		if (!$scope->canAccessProperty($property)) {
			return array_merge($messages, [
				sprintf(
					'Access to %s property $%s of class %s.',
					$property->isPrivate() ? 'private' : 'protected',
					$name,
					$property->getDeclaringClass()->getDisplayName()
				),
			]);
		}

		return $messages;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Properties;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\RuleLevelHelper;

class DefaultValueTypesAssignedToPropertiesRule implements \PHPStan\Rules\Rule
{

	/** @var \PHPStan\Rules\RuleLevelHelper */
	private $ruleLevelHelper;

	public function __construct(\PHPStan\Rules\RuleLevelHelper $ruleLevelHelper)
	{
		$this->ruleLevelHelper = $ruleLevelHelper;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\Property::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\Property $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		$classReflection = $scope->getClassReflection();

		$errors = [];
		foreach ($node->props as $property) {
			if ($property->default === null) {
				continue;
			}

			if ($property->default instanceof \PhpParser\Node\Expr\ConstFetch && (string) $property->default->name === 'null') {
				continue;
			}

			$propertyReflection = $classReflection->getNativeProperty($property->name);
			$propertyType = $propertyReflection->getType();
			$defaultValueType = $scope->getType($property->default);
			if ($this->ruleLevelHelper->accepts($propertyType, $defaultValueType)) {
				continue;
			}

			$errors[] = sprintf(
				'%s %s::$%s (%s) does not accept default value of type %s.',
				$node->isStatic() ? 'Static property' : 'Property',
				$classReflection->getDisplayName(),
				$property->name,
				$propertyType->describe(),
				$defaultValueType->describe()
			);
		}

		return $errors;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Properties;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\Rules\ClassCaseSensitivityCheck;

class ExistingClassesInPropertiesRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	/**
	 * @var \PHPStan\Rules\ClassCaseSensitivityCheck
	 */
	private $classCaseSensitivityCheck;

	/**
	 * @var bool
	 */
	private $checkClassCaseSensitivity;

	public function __construct(
		\PHPStan\Broker\Broker $broker,
		\PHPStan\Rules\ClassCaseSensitivityCheck $classCaseSensitivityCheck,
		bool $checkClassCaseSensitivity
	)
	{
		$this->broker = $broker;
		$this->classCaseSensitivityCheck = $classCaseSensitivityCheck;
		$this->checkClassCaseSensitivity = $checkClassCaseSensitivity;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Stmt\PropertyProperty::class;
	}

	/**
	 * @param \PhpParser\Node\Stmt\PropertyProperty $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		$propertyReflection = $scope->getClassReflection()->getNativeProperty($node->name);
		$propertyType = $propertyReflection->getType();

		$errors = [];
		foreach ($propertyType->getReferencedClasses() as $referencedClass) {
			if ($this->broker->hasClass($referencedClass)) {
				continue;
			}

			$errors[] = sprintf(
				'Property %s::$%s has unknown class %s as its type.',
				$propertyReflection->getDeclaringClass()->getDisplayName(),
				$node->name,
				$referencedClass
			);
		}

		if ($this->checkClassCaseSensitivity) {
			$errors = array_merge(
				$errors,
				$this->classCaseSensitivityCheck->checkClassNames($propertyType->getReferencedClasses())
			);
		}

		return $errors;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Properties;

use PHPStan\Reflection\PropertyReflection;

class PropertyDescriptor
{

	/**
	 * @param \PHPStan\Reflection\PropertyReflection $property
	 * @param \PhpParser\Node\Expr\PropertyFetch|\PhpParser\Node\Expr\StaticPropertyFetch $propertyFetch
	 * @return string|null
	 */
	public function describeProperty(\PHPStan\Reflection\PropertyReflection $property, $propertyFetch)
	{
		if ($propertyFetch instanceof \PhpParser\Node\Expr\PropertyFetch) {
			return sprintf('Property %s::$%s', $property->getDeclaringClass()->getDisplayName(), $propertyFetch->name);
		} elseif ($propertyFetch instanceof \PhpParser\Node\Expr\StaticPropertyFetch) {
			return sprintf('Static property %s::$%s', $property->getDeclaringClass()->getDisplayName(), $propertyFetch->name);
		}

		return null;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Properties;

use PHPStan\Analyser\Scope;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;

class PropertyReflectionFinder
{

	/**
	 * @param \PhpParser\Node\Expr\PropertyFetch|\PhpParser\Node\Expr\StaticPropertyFetch $propertyFetch
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return \PHPStan\Reflection\PropertyReflection|null
	 */
	public function findPropertyReflectionFromNode($propertyFetch, \PHPStan\Analyser\Scope $scope)
	{
		if ($propertyFetch instanceof \PhpParser\Node\Expr\PropertyFetch) {
			if (!is_string($propertyFetch->name)) {
				return null;
			}
			$propertyHolderType = $scope->getType($propertyFetch->var);
			return $this->findPropertyReflection($propertyHolderType, $propertyFetch->name, $scope);
		} elseif ($propertyFetch instanceof \PhpParser\Node\Expr\StaticPropertyFetch) {
			if (!is_string($propertyFetch->name)) {
				return null;
			}
			if ($propertyFetch->class instanceof \PhpParser\Node\Name) {
				$propertyHolderType = new \PHPStan\Type\ObjectType($scope->resolveName($propertyFetch->class));
			} else {
				$propertyHolderType = $scope->getType($propertyFetch->class);
			}

			return $this->findPropertyReflection($propertyHolderType, $propertyFetch->name, $scope);
		}

		return null;
	}

	/**
	 * @param \PHPStan\Type\Type $propertyHolderType
	 * @param string $propertyName
	 * @param Scope $scope
	 * @return \PHPStan\Reflection\PropertyReflection|null
	 */
	private function findPropertyReflection(\PHPStan\Type\Type $propertyHolderType, string $propertyName, \PHPStan\Analyser\Scope $scope)
	{
		if (!$propertyHolderType->hasProperty($propertyName)) {
			return null;
		}

		return $propertyHolderType->getProperty($propertyName, $scope);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Properties;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\RuleLevelHelper;

class ReadingWriteOnlyPropertiesRule implements \PHPStan\Rules\Rule
{

	/** @var \PHPStan\Rules\Properties\PropertyDescriptor */
	private $propertyDescriptor;

	/** @var \PHPStan\Rules\Properties\PropertyReflectionFinder */
	private $propertyReflectionFinder;

	/** @var RuleLevelHelper */
	private $ruleLevelHelper;

	/** @var bool */
	private $checkThisOnly;

	public function __construct(
		\PHPStan\Rules\Properties\PropertyDescriptor $propertyDescriptor,
		\PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder,
		\PHPStan\Rules\RuleLevelHelper $ruleLevelHelper,
		bool $checkThisOnly
	)
	{
		$this->propertyDescriptor = $propertyDescriptor;
		$this->propertyReflectionFinder = $propertyReflectionFinder;
		$this->ruleLevelHelper = $ruleLevelHelper;
		$this->checkThisOnly = $checkThisOnly;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node::class;
	}

	/**
	 * @param \PhpParser\Node $node
	 * @param Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (
			!($node instanceof \PhpParser\Node\Expr\PropertyFetch)
			&& !($node instanceof \PhpParser\Node\Expr\StaticPropertyFetch)
		) {
			return [];
		}

		if (
			$node instanceof \PhpParser\Node\Expr\PropertyFetch
			&& $this->checkThisOnly
			&& !$this->ruleLevelHelper->isThis($node->var)
		) {
			return [];
		}

		if ($scope->isInExpressionAssign($node)) {
			return [];
		}

		$propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($node, $scope);
		if ($propertyReflection === null) {
			return [];
		}
		if (!$scope->canAccessProperty($propertyReflection)) {
			return [];
		}

		if (!$propertyReflection->isReadable()) {
			$propertyDescription = $this->propertyDescriptor->describeProperty($propertyReflection, $node);
			if ($propertyDescription === null) {
				return [];
			}

			return [
				sprintf(
					'%s is not readable.',
					$propertyDescription
				),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Properties;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\RuleLevelHelper;

class TypesAssignedToPropertiesRule implements \PHPStan\Rules\Rule
{

	/** @var \PHPStan\Rules\RuleLevelHelper */
	private $ruleLevelHelper;

	/** @var \PHPStan\Rules\Properties\PropertyDescriptor */
	private $propertyDescriptor;

	/** @var \PHPStan\Rules\Properties\PropertyReflectionFinder */
	private $propertyReflectionFinder;

	public function __construct(
		\PHPStan\Rules\RuleLevelHelper $ruleLevelHelper,
		\PHPStan\Rules\Properties\PropertyDescriptor $propertyDescriptor,
		\PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder
	)
	{
		$this->ruleLevelHelper = $ruleLevelHelper;
		$this->propertyDescriptor = $propertyDescriptor;
		$this->propertyReflectionFinder = $propertyReflectionFinder;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node::class;
	}

	/**
	 * @param \PhpParser\Node $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (
			!$node instanceof \PhpParser\Node\Expr\Assign
			&& !$node instanceof \PhpParser\Node\Expr\AssignOp
		) {
			return [];
		}

		if (
			!($node->var instanceof \PhpParser\Node\Expr\PropertyFetch)
			&& !($node->var instanceof \PhpParser\Node\Expr\StaticPropertyFetch)
		) {
			return [];
		}

		/** @var \PhpParser\Node\Expr\PropertyFetch|\PhpParser\Node\Expr\StaticPropertyFetch $propertyFetch */
		$propertyFetch = $node->var;
		$propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($propertyFetch, $scope);
		if ($propertyReflection === null) {
			return [];
		}

		$propertyType = $propertyReflection->getType();

		if ($node instanceof \PhpParser\Node\Expr\Assign) {
			$assignedValueType = $scope->getType($node->expr);
		} else {
			$assignedValueType = $scope->getType($node);
		}
		if (!$this->ruleLevelHelper->accepts($propertyType, $assignedValueType)) {
			$propertyDescription = $this->propertyDescriptor->describeProperty($propertyReflection, $propertyFetch);
			if ($propertyDescription === null) {
				return [];
			}

			return [
				sprintf(
					'%s (%s) does not accept %s.',
					$propertyDescription,
					$propertyType->describe(),
					$assignedValueType->describe()
				),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Properties;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\RuleLevelHelper;

class WritingToReadOnlyPropertiesRule implements \PHPStan\Rules\Rule
{

	/** @var \PHPStan\Rules\RuleLevelHelper */
	private $ruleLevelHelper;

	/** @var \PHPStan\Rules\Properties\PropertyDescriptor */
	private $propertyDescriptor;

	/** @var \PHPStan\Rules\Properties\PropertyReflectionFinder */
	private $propertyReflectionFinder;

	/** @var bool */
	private $checkThisOnly;

	public function __construct(
		\PHPStan\Rules\RuleLevelHelper $ruleLevelHelper,
		\PHPStan\Rules\Properties\PropertyDescriptor $propertyDescriptor,
		\PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder,
		bool $checkThisOnly
	)
	{
		$this->ruleLevelHelper = $ruleLevelHelper;
		$this->propertyDescriptor = $propertyDescriptor;
		$this->propertyReflectionFinder = $propertyReflectionFinder;
		$this->checkThisOnly = $checkThisOnly;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node::class;
	}

	/**
	 * @param \PhpParser\Node $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (
			!$node instanceof \PhpParser\Node\Expr\Assign
			&& !$node instanceof \PhpParser\Node\Expr\AssignOp
		) {
			return [];
		}

		if (
			!($node->var instanceof \PhpParser\Node\Expr\PropertyFetch)
			&& !($node->var instanceof \PhpParser\Node\Expr\StaticPropertyFetch)
		) {
			return [];
		}

		if (
			$node->var instanceof \PhpParser\Node\Expr\PropertyFetch
			&& $this->checkThisOnly
			&& !$this->ruleLevelHelper->isThis($node->var->var)
		) {
			return [];
		}

		/** @var \PhpParser\Node\Expr\PropertyFetch|\PhpParser\Node\Expr\StaticPropertyFetch $propertyFetch */
		$propertyFetch = $node->var;
		$propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($propertyFetch, $scope);
		if ($propertyReflection === null) {
			return [];
		}

		if (!$scope->canAccessProperty($propertyReflection)) {
			return [];
		}

		if (!$propertyReflection->isWritable()) {
			$propertyDescription = $this->propertyDescriptor->describeProperty($propertyReflection, $propertyFetch);
			if ($propertyDescription === null) {
				return [];
			}

			return [
				sprintf(
					'%s is not writable.',
					$propertyDescription
				),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules;

class Registry
{

	/**
	 * @var \PHPStan\Rules\Rule[][]
	 */
	private $rules = [];

	/**
	 * @var \PHPStan\Rules\Rule[][]
	 */
	private $cache = [];

	/**
	 * @param \PHPStan\Rules\Rule[] $rules
	 */
	public function __construct(array $rules)
	{
		foreach ($rules as $rule) {
			$this->rules[$rule->getNodeType()][] = $rule;
		}
	}

	/**
	 * @param string $nodeType
	 * @return \PHPStan\Rules\Rule[]
	 */
	public function getRules(string $nodeType): array
	{
		if (!isset($this->cache[$nodeType])) {
			$nodeTypes = [$nodeType] + class_parents($nodeType) + class_implements($nodeType);

			$rules = [];
			foreach ($nodeTypes as $nodeType) {
				foreach ($this->rules[$nodeType] ?? [] as $rule) {
					$rules[get_class($rule)] = $rule;
				}
			}

			$this->cache[$nodeType] = array_values($rules);
		}

		return $this->cache[$nodeType];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules;

class RegistryFactory
{

	const RULE_TAG = 'phpstan.rules.rule';

	/** @var \Nette\DI\Container */
	private $container;

	public function __construct(\PHPStanVendor\Nette\DI\Container $container)
	{
		$this->container = $container;
	}

	public function create(): \PHPStan\Rules\Registry
	{
		$tagToService = function (array $tags) {
			return array_map(function (string $serviceName) {
				return $this->container->getService($serviceName);
			}, array_keys($tags));
		};

		return new \PHPStan\Rules\Registry(
			$tagToService($this->container->findByTag(self::RULE_TAG))
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules;
use PHPStan\Analyser\Scope;

interface Rule
{

	/**
	 * @return string Class implementing \PhpParser\Node
	 */
	public function getNodeType(): string;

	/**
	 * @param \PhpParser\Node $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[] errors
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array;

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\Type\ArrayType;
use PHPStan\Type\ErrorType;
use PHPStan\Type\MixedType;
use PHPStan\Type\NeverType;
use PHPStan\Type\NullType;
use PHPStan\Type\StaticType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\UnionType;

class RuleLevelHelper
{

	/**
	 * @var \PHPStan\Broker\Broker
	 */
	private $broker;

	/**
	 * @var bool
	 */
	private $checkNullables;

	/**
	 * @var bool
	 */
	private $checkThisOnly;

	/**
	 * @var bool
	 */
	private $checkUnionTypes;

	public function __construct(
		\PHPStan\Broker\Broker $broker,
		bool $checkNullables,
		bool $checkThisOnly,
		bool $checkUnionTypes
	)
	{
		$this->broker = $broker;
		$this->checkNullables = $checkNullables;
		$this->checkThisOnly = $checkThisOnly;
		$this->checkUnionTypes = $checkUnionTypes;
	}

	public function isThis(\PhpParser\Node\Expr $expression): bool
	{
		if (!($expression instanceof \PhpParser\Node\Expr\Variable)) {
			return false;
		}

		if (!is_string($expression->name)) {
			return false;
		}

		return $expression->name === 'this';
	}

	public function accepts(\PHPStan\Type\Type $acceptingType, \PHPStan\Type\Type $acceptedType): bool
	{
		if (
			!$this->checkNullables
			&& !$acceptingType instanceof \PHPStan\Type\NullType
			&& !$acceptedType instanceof \PHPStan\Type\NullType
		) {
			$acceptedType = \PHPStan\Type\TypeCombinator::removeNull($acceptedType);
		}

		return $acceptingType->accepts($acceptedType);
	}

	public function findTypeToCheck(
		\PHPStan\Analyser\Scope $scope,
		\PhpParser\Node\Expr $var,
		string $unknownClassErrorPattern
	): \PHPStan\Rules\FoundTypeResult
	{
		if ($this->checkThisOnly && !$this->isThis($var)) {
			return new \PHPStan\Rules\FoundTypeResult(new \PHPStan\Type\ErrorType(), [], []);
		}
		$type = $scope->getType($var);
		if (!$type instanceof \PHPStan\Type\NullType) {
			$type = \PHPStan\Type\TypeCombinator::removeNull($type);
		}
		if ($type instanceof \PHPStan\Type\MixedType || $type instanceof \PHPStan\Type\NeverType) {
			return new \PHPStan\Rules\FoundTypeResult(new \PHPStan\Type\ErrorType(), [], []);
		}
		if ($type instanceof \PHPStan\Type\StaticType) {
			$type = $type->resolveStatic($type->getBaseClass());
		}
		if ($type instanceof \PHPStan\Type\ArrayType) {
			return new \PHPStan\Rules\FoundTypeResult($type, [], []);
		}

		$errors = [];
		$referencedClasses = $type->getReferencedClasses();
		foreach ($referencedClasses as $referencedClass) {
			if (!$this->broker->hasClass($referencedClass)) {
				$errors[] = sprintf($unknownClassErrorPattern, $referencedClass);
			}
		}

		if (count($errors) > 0) {
			return new \PHPStan\Rules\FoundTypeResult(new \PHPStan\Type\ErrorType(), [], $errors);
		}

		if (!$this->checkUnionTypes && $type instanceof \PHPStan\Type\UnionType) {
			return new \PHPStan\Rules\FoundTypeResult(new \PHPStan\Type\ErrorType(), [], []);
		}

		return new \PHPStan\Rules\FoundTypeResult($type, $referencedClasses, []);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules;

class UnusedFunctionParametersCheck
{

	/**
	 * @param string[] $parameterNames
	 * @param \PhpParser\Node[] $statements
	 * @param string $unusedParameterMessage
	 * @return string[]
	 */
	public function getUnusedParameters(
		array $parameterNames,
		array $statements,
		string $unusedParameterMessage
	): array
	{
		$unusedParameters = array_fill_keys($parameterNames, true);
		foreach ($this->getUsedVariables($statements) as $variableName) {
			if (isset($unusedParameters[$variableName])) {
				unset($unusedParameters[$variableName]);
			}
		}
		$errors = [];
		foreach ($unusedParameters as $name => $bool) {
			$errors[] = sprintf($unusedParameterMessage, $name);
		}

		return $errors;
	}

	/**
	 * @param \PhpParser\Node[]|\PhpParser\Node $node
	 * @return string[]
	 */
	private function getUsedVariables($node): array
	{
		$variableNames = [];
		if ($node instanceof \PhpParser\Node) {
			if ($node instanceof \PhpParser\Node\Expr\Variable && is_string($node->name) && $node->name !== 'this') {
				return [$node->name];
			}
			if ($node instanceof \PhpParser\Node\Expr\ClosureUse) {
				return [$node->var];
			}
			if (
				$node instanceof \PhpParser\Node\Expr\FuncCall
				&& $node->name instanceof \PhpParser\Node\Name
				&& (string) $node->name === 'compact'
			) {
				foreach ($node->args as $arg) {
					if ($arg->value instanceof \PhpParser\Node\Scalar\String_) {
						$variableNames[] = $arg->value->value;
					}
				}
			}
			foreach ($node->getSubNodeNames() as $subNodeName) {
				if ($node instanceof \PhpParser\Node\Expr\Closure && $subNodeName !== 'uses') {
					continue;
				}
				$subNode = $node->{$subNodeName};
				$variableNames = array_merge($variableNames, $this->getUsedVariables($subNode));
			}
		} elseif (is_array($node)) {
			foreach ($node as $subNode) {
				$variableNames = array_merge($variableNames, $this->getUsedVariables($subNode));
			}
		}

		return $variableNames;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Variables;
use PHPStan\Analyser\Scope;

class DefinedVariableInAnonymousFunctionUseRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var bool
	 */
	private $checkMaybeUndefinedVariables;

	public function __construct(
		bool $checkMaybeUndefinedVariables
	)
	{
		$this->checkMaybeUndefinedVariables = $checkMaybeUndefinedVariables;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\ClosureUse::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\ClosureUse $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if ($node->byRef) {
			return [];
		}

		if ($scope->hasVariableType($node->var)->no()) {
			return [
				sprintf('Undefined variable: $%s', $node->var),
			];
		} elseif (
			$this->checkMaybeUndefinedVariables
			&& !$scope->hasVariableType($node->var)->yes()
		) {
			return [
				sprintf('Variable $%s might not be defined.', $node->var),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Variables;
use PHPStan\Analyser\Scope;

class DefinedVariableRule implements \PHPStan\Rules\Rule
{

	/**
	 * @var bool
	 */
	private $cliArgumentsVariablesRegistered;

	/**
	 * @var bool
	 */
	private $checkMaybeUndefinedVariables;

	public function __construct(
		bool $cliArgumentsVariablesRegistered,
		bool $checkMaybeUndefinedVariables
	)
	{
		$this->cliArgumentsVariablesRegistered = $cliArgumentsVariablesRegistered;
		$this->checkMaybeUndefinedVariables = $checkMaybeUndefinedVariables;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\Variable::class;
	}

	public static function isGlobalVariable(string $variableName): bool
	{
		return in_array($variableName, [
			'GLOBALS',
			'_SERVER',
			'_GET',
			'_POST',
			'_FILES',
			'_COOKIE',
			'_SESSION',
			'_REQUEST',
			'_ENV',
		], true);
	}

	/**
	 * @param \PhpParser\Node\Expr\Variable $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (!is_string($node->name)) {
			return [];
		}

		if (self::isGlobalVariable($node->name)) {
			return [];
		}

		if ($this->cliArgumentsVariablesRegistered && in_array($node->name, [
			'argc',
			'argv',
		], true)) {
			$isInMain = !$scope->isInClass() && !$scope->isInAnonymousFunction() && $scope->getFunction() === null;
			if ($isInMain) {
				return [];
			}
		}

		if ($scope->isInExpressionAssign($node)) {
			return [];
		}

		if ($scope->hasVariableType($node->name)->no()) {
			return [
				sprintf('Undefined variable: $%s', $node->name),
			];
		} elseif (
			$this->checkMaybeUndefinedVariables
			&& !$scope->hasVariableType($node->name)->yes()
		) {
			return [
				sprintf('Variable $%s might not be defined.', $node->name),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Variables;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;

class ThisVariableRule implements \PHPStan\Rules\Rule
{

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\Variable::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\Variable $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		if (!is_string($node->name) || $node->name !== 'this') {
			return [];
		}

		if ($scope->isInClosureBind()) {
			return [];
		}

		if (!$scope->isInClass()) {
			return [
				'Using $this outside a class.',
			];
		}

		$function = $scope->getFunction();
		if (!$function instanceof \PHPStan\Reflection\MethodReflection) {
			throw new \PHPStan\ShouldNotHappenException();
		}

		if ($function->isStatic()) {
			return [
				sprintf(
					'Using $this in static method %s::%s().',
					$scope->getClassReflection()->getDisplayName(),
					$function->getName()
				),
			];
		}

		return [];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Variables;
use PHPStan\Analyser\Scope;
use PHPStan\Type\NullType;

class VariableCertaintyInIssetRule implements \PHPStan\Rules\Rule
{

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\Isset_::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\Isset_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		$messages = [];
		foreach ($node->vars as $var) {
			$isSubNode = false;
			while (
				$var instanceof \PhpParser\Node\Expr\ArrayDimFetch
				|| $var instanceof \PhpParser\Node\Expr\PropertyFetch
			) {
				$var = $var->var;
				$isSubNode = true;
			}

			while (
				$var instanceof \PhpParser\Node\Expr\StaticPropertyFetch
				&& $var->class instanceof \PhpParser\Node\Expr
			) {
				$var = $var->class;
				$isSubNode = true;
			}

			if (!$var instanceof \PhpParser\Node\Expr\Variable || !is_string($var->name)) {
				continue;
			}

			if (\PHPStan\Rules\Variables\DefinedVariableRule::isGlobalVariable($var->name)) {
				continue;
			}

			$certainty = $scope->hasVariableType($var->name);
			if ($certainty->no()) {
				if (
					$scope->getFunction() !== null
					|| $scope->isInAnonymousFunction()
				) {
					$messages[] = sprintf('Variable $%s in isset() is never defined.', $var->name);
				}
			} elseif ($certainty->yes() && !$isSubNode) {
				$variableType = $scope->getVariableType($var->name);
				if (!$variableType->accepts(new \PHPStan\Type\NullType())) {
					$messages[] = sprintf('Variable $%s in isset() always exists and is not nullable.', $var->name);
				}
			}
		}

		return $messages;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Variables;
use PHPStan\Analyser\Scope;
use PHPStan\Type\NullType;

class VariableCloningRule implements \PHPStan\Rules\Rule
{

	/** @var bool */
	private $checkNullables;

	public function __construct(bool $checkNullables)
	{
		$this->checkNullables = $checkNullables;
	}

	public function getNodeType(): string
	{
		return \PhpParser\Node\Expr\Clone_::class;
	}

	/**
	 * @param \PhpParser\Node\Expr\Clone_ $node
	 * @param \PHPStan\Analyser\Scope $scope
	 * @return string[]
	 */
	public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope): array
	{
		$type = $scope->getType($node->expr);

		if (!$this->checkNullables && !$type instanceof \PHPStan\Type\NullType) {
			$type = \PHPStan\Type\TypeCombinator::removeNull($type);
		}

		if ($type->isClonable()) {
			return [];
		}

		if ($node->expr instanceof \PhpParser\Node\Expr\Variable) {
			return [
				sprintf(
					'Cannot clone non-object variable $%s of type %s.',
					$node->expr->name,
					$type->describe()
				),
			];
		}

		return [
			sprintf('Cannot clone %s.', $type->describe()),
		];
	}

}
<?php declare(strict_types = 1);

namespace PHPStan;

final class ShouldNotHappenException extends \Exception
{

	public function __construct(string $message = 'Internal error.')
	{
		parent::__construct($message);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Testing;

use PHPStan\Analyser\Analyser;
use PHPStan\Analyser\Error;
use PHPStan\Analyser\NodeScopeResolver;
use PHPStan\Analyser\TypeSpecifier;
use PHPStan\Cache\Cache;
use PHPStan\PhpDoc\PhpDocStringResolver;
use PHPStan\Rules\Registry;
use PHPStan\Rules\Rule;
use PHPStan\Type\FileTypeMapper;

abstract class RuleTestCase extends \PHPStan\Testing\TestCase
{

	/** @var \PHPStan\Analyser\Analyser */
	private $analyser;

	abstract protected function getRule(): \PHPStan\Rules\Rule;

	private function getAnalyser(): \PHPStan\Analyser\Analyser
	{
		if ($this->analyser === null) {
			$registry = new \PHPStan\Rules\Registry([
				$this->getRule(),
			]);

			$broker = $this->createBroker();
			$printer = new \PhpParser\PrettyPrinter\Standard();
			$fileHelper = $this->getFileHelper();
			$typeSpecifier = new \PHPStan\Analyser\TypeSpecifier($printer);
			$this->analyser = new \PHPStan\Analyser\Analyser(
				$broker,
				$this->getParser(),
				$registry,
				new \PHPStan\Analyser\NodeScopeResolver(
					$broker,
					$this->getParser(),
					$printer,
					new \PHPStan\Type\FileTypeMapper($this->getParser(), $this->getContainer()->getByType(\PHPStan\PhpDoc\PhpDocStringResolver::class), $this->createMock(\PHPStan\Cache\Cache::class)),
					$fileHelper,
					$this->shouldPolluteScopeWithLoopInitialAssignments(),
					$this->shouldPolluteCatchScopeWithTryAssignments(),
					[]
				),
				$printer,
				$typeSpecifier,
				$fileHelper,
				[],
				null,
				true,
				50
			);
		}

		return $this->analyser;
	}

	public function analyse(array $files, array $expectedErrors)
	{
		$files = array_map([$this->getFileHelper(), 'normalizePath'], $files);
		$actualErrors = $this->getAnalyser()->analyse($files, false);
		$this->assertInternalType('array', $actualErrors);

		$strictlyTypedSprintf = function (int $line, string $message): string {
			return sprintf('%02d: %s', $line, $message);
		};

		$expectedErrors = array_map(
			function (array $error) use ($strictlyTypedSprintf): string {
				if (!isset($error[0])) {
					throw new \InvalidArgumentException('Missing expected error message.');
				}
				if (!isset($error[1])) {
					throw new \InvalidArgumentException('Missing expected file line.');
				}
				return $strictlyTypedSprintf($error[1], $error[0]);
			},
			$expectedErrors
		);

		$actualErrors = array_map(
			function (\PHPStan\Analyser\Error $error): string {
				return sprintf('%02d: %s', $error->getLine(), $error->getMessage());
			},
			$actualErrors
		);

		$this->assertSame(implode("\n", $expectedErrors), implode("\n", $actualErrors));
	}

	protected function shouldPolluteScopeWithLoopInitialAssignments(): bool
	{
		return false;
	}

	protected function shouldPolluteCatchScopeWithTryAssignments(): bool
	{
		return false;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Testing;

use PHPStan\Broker\Broker;
use PHPStan\Cache\Cache;
use PHPStan\Cache\MemoryCacheStorage;
use PHPStan\DependencyInjection\ContainerFactory;
use PHPStan\File\FileHelper;
use PHPStan\Parser\FunctionCallStatementFinder;
use PHPStan\Parser\Parser;
use PHPStan\PhpDoc\PhpDocStringResolver;
use PHPStan\PhpDoc\TypeStringResolver;
use PHPStan\Reflection\Annotations\AnnotationsMethodsClassReflectionExtension;
use PHPStan\Reflection\Annotations\AnnotationsPropertiesClassReflectionExtension;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Reflection\FunctionReflectionFactory;
use PHPStan\Reflection\Php\PhpClassReflectionExtension;
use PHPStan\Reflection\Php\PhpMethodReflection;
use PHPStan\Reflection\Php\PhpMethodReflectionFactory;
use PHPStan\Reflection\Php\UniversalObjectCratesClassReflectionExtension;
use PHPStan\Reflection\PhpDefect\PhpDefectClassReflectionExtension;
use PHPStan\Type\FileTypeMapper;
use PHPStan\Type\Php\AllArgumentBasedFunctionReturnTypeExtension;
use PHPStan\Type\Php\ArgumentBasedArrayFunctionReturnTypeExtension;
use PHPStan\Type\Php\ArgumentBasedFunctionReturnTypeExtension;
use PHPStan\Type\Php\ArrayFilterFunctionReturnTypeReturnTypeExtension;
use PHPStan\Type\Php\CallbackBasedArrayFunctionReturnTypeExtension;
use PHPStan\Type\Php\CallbackBasedFunctionReturnTypeExtension;
use PHPStan\Type\Type;

abstract class TestCase extends \PHPUnit\Framework\TestCase
{

	/**
	 * @var \Nette\DI\Container
	 */
	private static $container;

	public function getContainer(): \PHPStanVendor\Nette\DI\Container
	{
		if (self::$container === null) {
			$rootDir = __DIR__ . '/../..';
			$containerFactory = new \PHPStan\DependencyInjection\ContainerFactory($rootDir);
			self::$container = $containerFactory->create($rootDir . '/tmp', [
				$containerFactory->getConfigDirectory() . '/config.level7.neon',
			]);
		}

		return self::$container;
	}

	public function getParser(): \PHPStan\Parser\Parser
	{
		/** @var \PHPStan\Parser\Parser $parser */
		$parser = $this->getContainer()->getService('directParser');
		return $parser;
	}

	/**
	 * @param \PHPStan\Type\DynamicMethodReturnTypeExtension[] $dynamicMethodReturnTypeExtensions
	 * @param \PHPStan\Type\DynamicStaticMethodReturnTypeExtension[] $dynamicStaticMethodReturnTypeExtensions
	 * @return \PHPStan\Broker\Broker
	 */
	public function createBroker(
		array $dynamicMethodReturnTypeExtensions = [],
		array $dynamicStaticMethodReturnTypeExtensions = []
	): \PHPStan\Broker\Broker
	{
		$functionCallStatementFinder = new \PHPStan\Parser\FunctionCallStatementFinder();
		$parser = $this->getParser();
		$cache = new \PHPStan\Cache\Cache(new \PHPStan\Cache\MemoryCacheStorage());
		$methodReflectionFactory = new class($parser, $functionCallStatementFinder, $cache) implements \PHPStan\Reflection\Php\PhpMethodReflectionFactory {
			/** @var \PHPStan\Parser\Parser */
			private $parser;

			/** @var \PHPStan\Parser\FunctionCallStatementFinder */
			private $functionCallStatementFinder;

			/** @var \PHPStan\Cache\Cache */
			private $cache;

			/** @var \PHPStan\Broker\Broker */
			public $broker;

			public function __construct(
				\PHPStan\Parser\Parser $parser,
				\PHPStan\Parser\FunctionCallStatementFinder $functionCallStatementFinder,
				\PHPStan\Cache\Cache $cache
			)
			{
				$this->parser = $parser;
				$this->functionCallStatementFinder = $functionCallStatementFinder;
				$this->cache = $cache;
			}

			public function create(
				\PHPStan\Reflection\ClassReflection $declaringClass,
				\ReflectionMethod $reflection,
				array $phpDocParameterTypes,
				\PHPStan\Type\Type $phpDocReturnType = null
			): \PHPStan\Reflection\Php\PhpMethodReflection
			{
				return new \PHPStan\Reflection\Php\PhpMethodReflection(
					$declaringClass,
					$reflection,
					$this->broker,
					$this->parser,
					$this->functionCallStatementFinder,
					$this->cache,
					$phpDocParameterTypes,
					$phpDocReturnType
				);
			}
		};
		$phpDocStringResolver = $this->getContainer()->getByType(\PHPStan\PhpDoc\PhpDocStringResolver::class);
		$fileTypeMapper = new \PHPStan\Type\FileTypeMapper($parser, $phpDocStringResolver, $cache);
		$annotationsPropertiesClassReflectionExtension = new \PHPStan\Reflection\Annotations\AnnotationsPropertiesClassReflectionExtension($fileTypeMapper);
		$phpExtension = new \PHPStan\Reflection\Php\PhpClassReflectionExtension($methodReflectionFactory, $fileTypeMapper, new \PHPStan\Reflection\Annotations\AnnotationsMethodsClassReflectionExtension($fileTypeMapper), $annotationsPropertiesClassReflectionExtension);
		$functionReflectionFactory = new class($this->getParser(), $functionCallStatementFinder, $cache) implements \PHPStan\Reflection\FunctionReflectionFactory {
			/** @var \PHPStan\Parser\Parser */
			private $parser;

			/** @var \PHPStan\Parser\FunctionCallStatementFinder */
			private $functionCallStatementFinder;

			/** @var \PHPStan\Cache\Cache */
			private $cache;

			public function __construct(
				\PHPStan\Parser\Parser $parser,
				\PHPStan\Parser\FunctionCallStatementFinder $functionCallStatementFinder,
				\PHPStan\Cache\Cache $cache
			)
			{
				$this->parser = $parser;
				$this->functionCallStatementFinder = $functionCallStatementFinder;
				$this->cache = $cache;
			}

			public function create(
				\ReflectionFunction $function,
				array $phpDocParameterTypes,
				\PHPStan\Type\Type $phpDocReturnType = null
			): \PHPStan\Reflection\FunctionReflection
			{
				return new \PHPStan\Reflection\FunctionReflection(
					$function,
					$this->parser,
					$this->functionCallStatementFinder,
					$this->cache,
					$phpDocParameterTypes,
					$phpDocReturnType
				);
			}
		};
		$broker = new \PHPStan\Broker\Broker(
			[
				$phpExtension,
				$annotationsPropertiesClassReflectionExtension,
				new \PHPStan\Reflection\Php\UniversalObjectCratesClassReflectionExtension([\stdClass::class]),
				new \PHPStan\Reflection\PhpDefect\PhpDefectClassReflectionExtension($this->getContainer()->getByType(\PHPStan\PhpDoc\TypeStringResolver::class)),
			],
			[$phpExtension],
			$dynamicMethodReturnTypeExtensions,
			$dynamicStaticMethodReturnTypeExtensions,
			[
				new \PHPStan\Type\Php\AllArgumentBasedFunctionReturnTypeExtension(),
				new \PHPStan\Type\Php\ArgumentBasedArrayFunctionReturnTypeExtension(),
				new \PHPStan\Type\Php\ArgumentBasedFunctionReturnTypeExtension(),
				new \PHPStan\Type\Php\ArrayFilterFunctionReturnTypeReturnTypeExtension(),
				new \PHPStan\Type\Php\CallbackBasedArrayFunctionReturnTypeExtension(),
				new \PHPStan\Type\Php\CallbackBasedFunctionReturnTypeExtension(),
			],
			$functionReflectionFactory,
			new \PHPStan\Type\FileTypeMapper($this->getParser(), $phpDocStringResolver, $cache)
		);
		$methodReflectionFactory->broker = $broker;

		return $broker;
	}

	public function getFileHelper(): \PHPStan\File\FileHelper
	{
		return $this->getContainer()->getByType(\PHPStan\File\FileHelper::class);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan;

/**
 * @see https://en.wikipedia.org/wiki/Three-valued_logic
 */
class TrinaryLogic
{

	const YES = 1;
	const MAYBE = 0;
	const NO = -1;

	/**
	 * @var int
	 */
	private $value;

	private function __construct(int $value)
	{
		$this->value = $value;
	}

	public static function createYes(): self
	{
		return new self(self::YES);
	}

	public static function createNo(): self
	{
		return new self(self::NO);
	}

	public static function createMaybe(): self
	{
		return new self(self::MAYBE);
	}

	public function yes(): bool
	{
		return $this->value === self::YES;
	}

	public function maybe(): bool
	{
		return $this->value === self::MAYBE;
	}

	public function no(): bool
	{
		return $this->value === self::NO;
	}

	public function and(self ...$operands): self
	{
		$operandValues = array_map(function (self $trinaryLogic): int {
			return $trinaryLogic->value;
		}, $operands);
		$operandValues[] = $this->value;
		return new self(min($operandValues));
	}

	public function or(self ...$operands): self
	{
		$operandValues = array_map(function (self $trinaryLogic): int {
			return $trinaryLogic->value;
		}, $operands);
		$operandValues[] = $this->value;
		return new self(max($operandValues));
	}

	public static function extremeIdentity(self ...$operands): self
	{
		$operandValues = array_map(function (self $trinaryLogic): int {
			return $trinaryLogic->value;
		}, $operands);

		$min = min($operandValues);
		$max = max($operandValues);
		return new self($min === $max ? $min : self::MAYBE);
	}

	public static function maxMin(self ...$operands): self
	{
		$operandValues = array_map(function (self $trinaryLogic): int {
			return $trinaryLogic->value;
		}, $operands);

		return new self(max($operandValues) ?: min($operandValues));
	}

	public function negate(): self
	{
		return new self(-$this->value);
	}

	public function equals(self $other): bool
	{
		return $this->value === $other->value;
	}

	public function addMaybe(): self
	{
		$value = $this->value;
		if ($value === self::NO) {
			$value = self::MAYBE;
		}

		return new self($value);
	}

	public function describe(): string
	{
		$labels = [
			self::NO => 'No',
			self::MAYBE => 'Maybe',
			self::YES => 'Yes',
		];

		return $labels[$this->value];
	}

	public static function __set_state(array $properties): self
	{
		return new self($properties['value']);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\TrinaryLogic;

class ArrayType implements \PHPStan\Type\StaticResolvableType
{

	use \PHPStan\Type\IterableTypeTrait;

	/** @var \PHPStan\Type\Type */
	private $keyType;

	/** @var bool */
	private $itemTypeInferredFromLiteralArray;

	/** @var TrinaryLogic */
	private $callable;

	public function __construct(
		\PHPStan\Type\Type $keyType,
		\PHPStan\Type\Type $itemType,
		bool $itemTypeInferredFromLiteralArray = false,
		\PHPStan\TrinaryLogic $callable = null
	)
	{
		if ($itemType instanceof \PHPStan\Type\UnionType && !\PHPStan\Type\TypeCombinator::isUnionTypesEnabled()) {
			$itemType = new \PHPStan\Type\MixedType();
		}
		$this->keyType = $keyType;
		$this->itemType = $itemType;
		$this->itemTypeInferredFromLiteralArray = $itemTypeInferredFromLiteralArray;
		$this->callable = $callable ?? \PHPStan\TrinaryLogic::createMaybe()->and((new \PHPStan\Type\StringType)->isSuperTypeOf($itemType));
	}

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return array_merge(
			$this->keyType->getReferencedClasses(),
			$this->getItemType()->getReferencedClasses()
		);
	}

	public static function createDeepArrayType(\PHPStan\Type\NestedArrayItemType $nestedItemType, bool $nullable): self
	{
		$itemType = $nestedItemType->getItemType();
		for ($i = 0; $i < $nestedItemType->getDepth() - 1; $i++) {
			$itemType = new self(new \PHPStan\Type\MixedType(), $itemType, false);
		}

		return new self(new \PHPStan\Type\MixedType(), $itemType, $nullable);
	}

	public function isItemTypeInferredFromLiteralArray(): bool
	{
		return $this->itemTypeInferredFromLiteralArray;
	}

	public function accepts(\PHPStan\Type\Type $type): bool
	{
		if ($type instanceof self) {
			return $this->getItemType()->accepts($type->getItemType())
				&& $this->keyType->accepts($type->keyType);
		}

		if ($type instanceof \PHPStan\Type\CompoundType) {
			return \PHPStan\Type\CompoundTypeHelper::accepts($type, $this);
		}

		return false;
	}

	public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic
	{
		if ($type instanceof self) {
			return $this->getItemType()->isSuperTypeOf($type->getItemType())
				->and($this->keyType->isSuperTypeOf($type->keyType));
		}

		if ($type instanceof \PHPStan\Type\CompoundType) {
			return $type->isSubTypeOf($this);
		}

		return \PHPStan\TrinaryLogic::createNo();
	}

	public function describe(): string
	{
		if ($this->keyType instanceof \PHPStan\Type\MixedType) {
			if ($this->itemType instanceof \PHPStan\Type\MixedType) {
				return 'array';
			}

			return sprintf('array<%s>', $this->itemType->describe());
		}

		return sprintf('array<%s, %s>', $this->keyType->describe(), $this->itemType->describe());
	}

	public function isDocumentableNatively(): bool
	{
		return true;
	}

	public function resolveStatic(string $className): \PHPStan\Type\Type
	{
		if ($this->getItemType() instanceof \PHPStan\Type\StaticResolvableType) {
			return new self(
				$this->keyType,
				$this->getItemType()->resolveStatic($className),
				$this->isItemTypeInferredFromLiteralArray(),
				$this->callable
			);
		}

		return $this;
	}

	public function changeBaseClass(string $className): \PHPStan\Type\StaticResolvableType
	{
		if ($this->getItemType() instanceof \PHPStan\Type\StaticResolvableType) {
			return new self(
				$this->keyType,
				$this->getItemType()->changeBaseClass($className),
				$this->isItemTypeInferredFromLiteralArray(),
				$this->callable
			);
		}

		return $this;
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createYes();
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		return $this->keyType;
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		return $this->getItemType();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return $this->callable;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self(
			$properties['keyType'],
			$properties['itemType'],
			$properties['itemTypeInferredFromLiteralArray'],
			$properties['callable']
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

interface BooleanType extends \PHPStan\Type\Type
{

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class CallableType implements \PHPStan\Type\CompoundType
{

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return [];
	}

	public function accepts(\PHPStan\Type\Type $type): bool
	{
		if ($type instanceof \PHPStan\Type\CompoundType) {
			return \PHPStan\Type\CompoundTypeHelper::accepts($type, $this);
		}

		return $type->isCallable()->yes() || $type instanceof \PHPStan\Type\StringType;
	}

	public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic
	{
		return $type->isCallable();
	}

	public function isSubTypeOf(\PHPStan\Type\Type $otherType): \PHPStan\TrinaryLogic
	{
		if ($otherType instanceof \PHPStan\Type\IntersectionType || $otherType instanceof \PHPStan\Type\UnionType) {
			return $otherType->isSuperTypeOf($this);
		}

		return $otherType->isCallable()
			->and($otherType instanceof self ? \PHPStan\TrinaryLogic::createYes() : \PHPStan\TrinaryLogic::createMaybe());
	}

	public function describe(): string
	{
		return 'callable';
	}

	public function canAccessProperties(): bool
	{
		return false;
	}

	public function hasProperty(string $propertyName): bool
	{
		return false;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canCallMethods(): bool
	{
		return true;
	}

	public function hasMethod(string $methodName): bool
	{
		return false;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canAccessConstants(): bool
	{
		return false;
	}

	public function hasConstant(string $constantName): bool
	{
		return false;
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function isDocumentableNatively(): bool
	{
		return true;
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createMaybe();
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\MixedType();
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\MixedType();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createYes();
	}

	public function isClonable(): bool
	{
		return false;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

class CommentHelper
{

	/**
	 * @param \PhpParser\Node $node
	 * @return string|null
	 */
	public static function getDocComment(\PhpParser\Node $node)
	{
		$phpDoc = $node->getDocComment();
		if ($phpDoc !== null) {
			return $phpDoc->getText();
		}

		return null;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\TrinaryLogic;

interface CompoundType extends \PHPStan\Type\Type
{

	public function isSubTypeOf(\PHPStan\Type\Type $otherType): \PHPStan\TrinaryLogic;

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

class CompoundTypeHelper
{

	public static function accepts(\PHPStan\Type\CompoundType $compoundType, \PHPStan\Type\Type $otherType): bool
	{
		if ($compoundType instanceof \PHPStan\Type\MixedType) {
			return true;
		}

		return $compoundType->isSubTypeOf($otherType)->yes();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionReflection;

interface DynamicFunctionReturnTypeExtension
{

	public function isFunctionSupported(\PHPStan\Reflection\FunctionReflection $functionReflection): bool;

	public function getTypeFromFunctionCall(\PHPStan\Reflection\FunctionReflection $functionReflection, \PhpParser\Node\Expr\FuncCall $functionCall, \PHPStan\Analyser\Scope $scope): \PHPStan\Type\Type;

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;

interface DynamicMethodReturnTypeExtension
{

	public function getClass(): string;

	public function isMethodSupported(\PHPStan\Reflection\MethodReflection $methodReflection): bool;

	public function getTypeFromMethodCall(\PHPStan\Reflection\MethodReflection $methodReflection, \PhpParser\Node\Expr\MethodCall $methodCall, \PHPStan\Analyser\Scope $scope): \PHPStan\Type\Type;

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;

interface DynamicStaticMethodReturnTypeExtension
{

	public function getClass(): string;

	public function isStaticMethodSupported(\PHPStan\Reflection\MethodReflection $methodReflection): bool;

	public function getTypeFromStaticMethodCall(\PHPStan\Reflection\MethodReflection $methodReflection, \PhpParser\Node\Expr\StaticCall $methodCall, \PHPStan\Analyser\Scope $scope): \PHPStan\Type\Type;

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

class ErrorType extends \PHPStan\Type\MixedType
{

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class FalseBooleanType implements \PHPStan\Type\BooleanType
{

	public function describe(): string
	{
		return 'false';
	}

	public function canAccessProperties(): bool
	{
		return false;
	}

	public function hasProperty(string $propertyName): bool
	{
		return false;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canCallMethods(): bool
	{
		return false;
	}

	public function hasMethod(string $methodName): bool
	{
		return false;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canAccessConstants(): bool
	{
		return false;
	}

	public function hasConstant(string $constantName): bool
	{
		return false;
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return [];
	}

	public function accepts(\PHPStan\Type\Type $type): bool
	{
		if ($type instanceof self) {
			return true;
		}

		if ($type instanceof \PHPStan\Type\CompoundType) {
			return \PHPStan\Type\CompoundTypeHelper::accepts($type, $this);
		}

		return false;
	}

	public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic
	{
		if ($type instanceof self) {
			return \PHPStan\TrinaryLogic::createYes();
		}

		if ($type instanceof \PHPStan\Type\TrueOrFalseBooleanType) {
			return \PHPStan\TrinaryLogic::createMaybe();
		}

		if ($type instanceof \PHPStan\Type\CompoundType) {
			return $type->isSubTypeOf($this);
		}

		return \PHPStan\TrinaryLogic::createNo();
	}

	public function isDocumentableNatively(): bool
	{
		return true;
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createNo();
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createNo();
	}

	public function isClonable(): bool
	{
		return false;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;
use PHPStan\Analyser\NameScope;
use PHPStan\Cache\Cache;
use PHPStan\Parser\Parser;
use PHPStan\PhpDoc\PhpDocStringResolver;
use PHPStan\PhpDoc\ResolvedPhpDocBlock;

class FileTypeMapper
{

	/** @var \PHPStan\Parser\Parser */
	private $phpParser;

	/** @var \PHPStan\PhpDoc\PhpDocStringResolver */
	private $phpDocStringResolver;

	/** @var \PHPStan\Cache\Cache */
	private $cache;

	/** @var \PHPStan\PhpDoc\ResolvedPhpDocBlock[][][] */
	private $memoryCache = [];

	/** @var (false|callable|ResolvedPhpDocBlock)[][][]  */
	private $inProcess = [];

	public function __construct(
		\PHPStan\Parser\Parser $phpParser,
		\PHPStan\PhpDoc\PhpDocStringResolver $phpDocStringResolver,
		\PHPStan\Cache\Cache $cache
	)
	{
		$this->phpParser = $phpParser;
		$this->phpDocStringResolver = $phpDocStringResolver;
		$this->cache = $cache;
	}

	public function getResolvedPhpDoc(string $filename, string $className = null, string $docComment): \PHPStan\PhpDoc\ResolvedPhpDocBlock
	{
		$key = md5($docComment);

		if (isset($this->inProcess[$filename])) {
			if (isset($this->inProcess[$filename][$className][$key])) {
				$data = $this->inProcess[$filename][$className][$key];
				if (is_callable($data)) {
					$this->inProcess[$filename][$className][$key] = false;
					$this->inProcess[$filename][$className][$key] = $data();

				} elseif ($data === false) { // PHPDoc has cyclic dependency
					return $this->phpDocStringResolver->resolve('/** nothing */', new \PHPStan\Analyser\NameScope(null, []));
				}

				assert($this->inProcess[$filename][$className][$key] instanceof \PHPStan\PhpDoc\ResolvedPhpDocBlock);
				return $this->inProcess[$filename][$className][$key];
			}
		}

		$map = $this->getResolvedPhpDocMap($filename, $className);
		if (!isset($map[$key])) { // most likely wrong $fileName due to traits
			return $this->phpDocStringResolver->resolve('/** nothing */', new \PHPStan\Analyser\NameScope(null, []));
		}

		return $map[$key];
	}

	/**
	 * @param string $fileName
	 * @param string|null $className
	 * @return \PHPStan\PhpDoc\ResolvedPhpDocBlock[]
	 */
	private function getResolvedPhpDocMap(string $fileName, string $className = null): array
	{
		if (!isset($this->memoryCache[$fileName])) {
			$cacheKey = sprintf('%s-%d-v27', $fileName, filemtime($fileName));
			$map = $this->cache->load($cacheKey);

			if ($map === null) {
				$map = $this->createResolvedPhpDocMap($fileName);
				$this->cache->save($cacheKey, $map);
			}

			$this->memoryCache[$fileName] = $map;
		}

		if (!array_key_exists($className, $this->memoryCache[$fileName])) {
			// class with traits - class has no phpDocs but trait has some
			return [];
		}

		return $this->memoryCache[$fileName][$className];
	}

	/**
	 * @param string $fileName
	 * @return \PHPStan\PhpDoc\ResolvedPhpDocBlock[][]
	 */
	private function createResolvedPhpDocMap(string $fileName): array
	{
		$phpDocMap = [];

		/** @var \PhpParser\Node\Stmt\ClassLike[] $classStack */
		$classStack = [];
		$namespace = null;
		$uses = [];

		$this->processNodes(
			$this->phpParser->parseFile($fileName),
			function (\PhpParser\Node $node) use (&$phpDocMap, &$classStack, &$namespace, &$uses) {
				if ($node instanceof \PhpParser\Node\Stmt\ClassLike) {
					$classStack[] = $node;
				} elseif ($node instanceof \PhpParser\Node\Stmt\Namespace_) {
					$namespace = (string) $node->name;
				} elseif ($node instanceof \PhpParser\Node\Stmt\Use_ && $node->type === \PhpParser\Node\Stmt\Use_::TYPE_NORMAL) {
					foreach ($node->uses as $use) {
						$uses[$use->alias] = (string) $use->name;
					}
				} elseif ($node instanceof \PhpParser\Node\Stmt\GroupUse) {
					$prefix = (string) $node->prefix;
					foreach ($node->uses as $use) {
						if ($node->type === \PhpParser\Node\Stmt\Use_::TYPE_NORMAL || $use->type === \PhpParser\Node\Stmt\Use_::TYPE_NORMAL) {
							$uses[$use->alias] = sprintf('%s\\%s', $prefix, $use->name);
						}
					}
				} elseif (!in_array(get_class($node), [
					\PhpParser\Node\Stmt\Property::class,
					\PhpParser\Node\Stmt\ClassMethod::class,
					\PhpParser\Node\Stmt\Function_::class,
					\PhpParser\Node\Stmt\Foreach_::class,
					\PhpParser\Node\Expr\Assign::class,
					\PhpParser\Node\Expr\AssignRef::class,
					\PhpParser\Node\Stmt\Class_::class,
				], true)) {
					return;
				}

				$phpDocString = \PHPStan\Type\CommentHelper::getDocComment($node);
				if ($phpDocString === null) {
					return;
				}

				$className = count($classStack) > 0 ? $classStack[count($classStack) - 1]->name : null;
				if ($className !== null && $namespace !== null) {
					$className = sprintf('%s\\%s', $namespace, $className);
				}

				$nameScope = new \PHPStan\Analyser\NameScope($namespace, $uses, $className);
				$phpDocMap[$className][md5($phpDocString)] = function () use ($phpDocString, $nameScope): \PHPStan\PhpDoc\ResolvedPhpDocBlock {
					return $this->phpDocStringResolver->resolve($phpDocString, $nameScope);
				};
			},
			function (\PhpParser\Node $node) use (&$namespace, &$classStack, &$uses) {
				if ($node instanceof \PhpParser\Node\Stmt\ClassLike) {
					if (count($classStack) === 0) {
						throw new \PHPStan\ShouldNotHappenException();
					}
					array_pop($classStack);
				} elseif ($node instanceof \PhpParser\Node\Stmt\Namespace_) {
					$namespace = null;
					$uses = [];
				}
			}
		);

		try {
			$this->inProcess[$fileName] = $phpDocMap;

			foreach ($phpDocMap as $className => $classMap) {
				foreach ($classMap as $phpDocKey => $resolveCallback) {
					$this->inProcess[$fileName][$className][$phpDocKey] = false;
					$this->inProcess[$fileName][$className][$phpDocKey] = $resolveCallback();
					$phpDocMap[$className][$phpDocKey] = $this->inProcess[$fileName][$className][$phpDocKey];
				}
			}

		} finally {
			unset($this->inProcess[$fileName]);
		}

		return $phpDocMap;
	}

	/**
	 * @param \PhpParser\Node[]|\PhpParser\Node $node
	 * @param \Closure $nodeCallback
	 * @param \Closure $endNodeCallback
	 */
	private function processNodes($node, \Closure $nodeCallback, \Closure $endNodeCallback)
	{
		if ($node instanceof \PhpParser\Node) {
			$nodeCallback($node);
			foreach ($node->getSubNodeNames() as $subNodeName) {
				$subNode = $node->{$subNodeName};
				$this->processNodes($subNode, $nodeCallback, $endNodeCallback);
			}
			$endNodeCallback($node);
		} elseif (is_array($node)) {
			foreach ($node as $subNode) {
				$this->processNodes($subNode, $nodeCallback, $endNodeCallback);
			}
		}
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class FloatType implements \PHPStan\Type\Type
{

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return [];
	}

	public function accepts(\PHPStan\Type\Type $type): bool
	{
		if ($type instanceof self || $type instanceof \PHPStan\Type\IntegerType) {
			return true;
		}

		if ($type instanceof \PHPStan\Type\CompoundType) {
			return \PHPStan\Type\CompoundTypeHelper::accepts($type, new \PHPStan\Type\UnionType([
				$this,
				new \PHPStan\Type\IntegerType(),
			]));
		}

		return false;
	}

	public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic
	{
		if ($type instanceof self) {
			return \PHPStan\TrinaryLogic::createYes();
		}

		if ($type instanceof \PHPStan\Type\CompoundType) {
			return $type->isSubTypeOf($this);
		}

		return \PHPStan\TrinaryLogic::createNo();
	}

	public function describe(): string
	{
		return 'float';
	}

	public function canAccessProperties(): bool
	{
		return false;
	}

	public function hasProperty(string $propertyName): bool
	{
		return false;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canCallMethods(): bool
	{
		return false;
	}

	public function hasMethod(string $methodName): bool
	{
		return false;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canAccessConstants(): bool
	{
		return false;
	}

	public function hasConstant(string $constantName): bool
	{
		return false;
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function isDocumentableNatively(): bool
	{
		return true;
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createNo();
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createNo();
	}

	public function isClonable(): bool
	{
		return false;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class IntegerType implements \PHPStan\Type\Type
{

	use \PHPStan\Type\JustNullableTypeTrait;

	public function describe(): string
	{
		return 'int';
	}

	public function canAccessProperties(): bool
	{
		return false;
	}

	public function hasProperty(string $propertyName): bool
	{
		return false;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canCallMethods(): bool
	{
		return false;
	}

	public function hasMethod(string $methodName): bool
	{
		return false;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canAccessConstants(): bool
	{
		return false;
	}

	public function hasConstant(string $constantName): bool
	{
		return false;
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createNo();
	}

	public function isClonable(): bool
	{
		return false;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class IntersectionType implements \PHPStan\Type\CompoundType, \PHPStan\Type\StaticResolvableType
{

	/** @var \PHPStan\Type\Type[] */
	private $types;

	/**
	 * @param Type[] $types
	 */
	public function __construct(array $types)
	{
		$this->types = \PHPStan\Type\UnionTypeHelper::sortTypes($types);
	}

	/**
	 * @return Type[]
	 */
	public function getTypes(): array
	{
		return $this->types;
	}

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return \PHPStan\Type\UnionTypeHelper::getReferencedClasses($this->types);
	}

	public function accepts(\PHPStan\Type\Type $otherType): bool
	{
		foreach ($this->types as $type) {
			if (!$type->accepts($otherType)) {
				return false;
			}
		}

		return true;
	}

	public function isSuperTypeOf(\PHPStan\Type\Type $otherType): \PHPStan\TrinaryLogic
	{
		$results = [];
		foreach ($this->getTypes() as $innerType) {
			$results[] = $innerType->isSuperTypeOf($otherType);
		}

		return \PHPStan\TrinaryLogic::createYes()->and(...$results);
	}

	public function isSubTypeOf(\PHPStan\Type\Type $otherType): \PHPStan\TrinaryLogic
	{
		if ($otherType instanceof self || $otherType instanceof \PHPStan\Type\UnionType) {
			return $otherType->isSuperTypeOf($this);
		}

		$results = [];
		foreach ($this->getTypes() as $innerType) {
			$results[] = $otherType->isSuperTypeOf($innerType);
		}

		return \PHPStan\TrinaryLogic::maxMin(...$results);
	}

	public function describe(): string
	{
		$typeNames = [];

		foreach ($this->types as $type) {
			$typeNames[] = $type->describe();
		}

		return implode('&', $typeNames);
	}

	public function canAccessProperties(): bool
	{
		$result = $this->intersectResults(function (\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic {
			return $type->canAccessProperties() ? \PHPStan\TrinaryLogic::createYes() : \PHPStan\TrinaryLogic::createNo();
		});

		return $result->yes();
	}

	public function hasProperty(string $propertyName): bool
	{
		foreach ($this->types as $type) {
			if ($type->hasProperty($propertyName)) {
				return true;
			}
		}

		return false;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		foreach ($this->types as $type) {
			if ($type->hasProperty($propertyName)) {
				return $type->getProperty($propertyName, $scope);
			}
		}

		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canCallMethods(): bool
	{
		$result = $this->intersectResults(function (\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic {
			return $type->canCallMethods() ? \PHPStan\TrinaryLogic::createYes() : \PHPStan\TrinaryLogic::createNo();
		});

		return $result->yes();
	}

	public function hasMethod(string $methodName): bool
	{
		foreach ($this->types as $type) {
			if ($type->hasMethod($methodName)) {
				return true;
			}
		}

		return false;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		foreach ($this->types as $type) {
			if ($type->hasMethod($methodName)) {
				return $type->getMethod($methodName, $scope);
			}
		}

		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canAccessConstants(): bool
	{
		$result = $this->intersectResults(function (\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic {
			return $type->canAccessConstants() ? \PHPStan\TrinaryLogic::createYes() : \PHPStan\TrinaryLogic::createNo();
		});

		return $result->yes();
	}

	public function hasConstant(string $constantName): bool
	{
		foreach ($this->types as $type) {
			if ($type->hasConstant($constantName)) {
				return true;
			}
		}

		return false;
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		foreach ($this->types as $type) {
			if ($type->hasConstant($constantName)) {
				return $type->getConstant($constantName);
			}
		}

		throw new \PHPStan\ShouldNotHappenException();
	}

	public function isDocumentableNatively(): bool
	{
		return false;
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		return $this->intersectResults(function (\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic {
			return $type->isIterable();
		});
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		return $this->intersectTypes(function (\PHPStan\Type\Type $type): \PHPStan\Type\Type {
			return $type->getIterableKeyType();
		});
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		return $this->intersectTypes(function (\PHPStan\Type\Type $type): \PHPStan\Type\Type {
			return $type->getIterableValueType();
		});
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return $this->intersectResults(function (\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic {
			return $type->isCallable();
		});
	}

	public function isClonable(): bool
	{
		foreach ($this->types as $type) {
			if ($type->isClonable()) {
				return true;
			}
		}

		return false;
	}

	public function resolveStatic(string $className): \PHPStan\Type\Type
	{
		return new self(\PHPStan\Type\UnionTypeHelper::resolveStatic($className, $this->getTypes()));
	}

	public function changeBaseClass(string $className): \PHPStan\Type\StaticResolvableType
	{
		return new self(\PHPStan\Type\UnionTypeHelper::changeBaseClass($className, $this->getTypes()));
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self($properties['types']);
	}

	private function intersectResults(callable $getResult): \PHPStan\TrinaryLogic
	{
		$operands = array_map($getResult, $this->types);
		return \PHPStan\TrinaryLogic::maxMin(...$operands);
	}

	private function intersectTypes(callable $getType): \PHPStan\Type\Type
	{
		$operands = array_map($getType, $this->types);
		return \PHPStan\Type\TypeCombinator::intersect(...$operands);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\TrinaryLogic;

class IterableIterableType implements \PHPStan\Type\StaticResolvableType, \PHPStan\Type\CompoundType
{

	use \PHPStan\Type\IterableTypeTrait;

	/**
	 * @var \PHPStan\Type\Type
	 */
	private $keyType;

	public function __construct(
		\PHPStan\Type\Type $keyType,
		\PHPStan\Type\Type $itemType
	)
	{
		$this->keyType = $keyType;
		$this->itemType = $itemType;
	}

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return array_merge(
			$this->keyType->getReferencedClasses(),
			$this->getItemType()->getReferencedClasses()
		);
	}

	public function accepts(\PHPStan\Type\Type $type): bool
	{
		if ($type instanceof \PHPStan\Type\CompoundType) {
			return \PHPStan\Type\CompoundTypeHelper::accepts($type, $this);
		}

		if ($type->isIterable()->yes()) {
			return $this->getIterableValueType()->accepts($type->getIterableValueType())
				&& $this->getIterableKeyType()->accepts($type->getIterableKeyType());
		}

		return false;
	}

	public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic
	{
		return $type->isIterable()
			->and($this->getIterableValueType()->isSuperTypeOf($type->getIterableValueType()))
			->and($this->getIterableKeyType()->isSuperTypeOf($type->getIterableKeyType()));
	}

	public function isSubTypeOf(\PHPStan\Type\Type $otherType): \PHPStan\TrinaryLogic
	{
		if ($otherType instanceof \PHPStan\Type\IntersectionType || $otherType instanceof \PHPStan\Type\UnionType) {
			return $otherType->isSuperTypeOf(new \PHPStan\Type\UnionType([
				new \PHPStan\Type\ArrayType($this->keyType, $this->itemType),
				new \PHPStan\Type\IntersectionType([
					new \PHPStan\Type\ObjectType(\Traversable::class),
					$this,
				]),
			]));
		}

		if ($otherType instanceof self) {
			$limit = \PHPStan\TrinaryLogic::createYes();
		} else {
			$limit = \PHPStan\TrinaryLogic::createMaybe();
		}

		return $limit->and(
			$otherType->isIterable(),
			$otherType->getIterableValueType()->isSuperTypeOf($this->itemType),
			$otherType->getIterableKeyType()->isSuperTypeOf($this->keyType)
		);
	}

	public function describe(): string
	{
		if ($this->keyType instanceof \PHPStan\Type\MixedType) {
			if ($this->itemType instanceof \PHPStan\Type\MixedType) {
				return 'iterable';
			}

			return sprintf('iterable<%s>', $this->itemType->describe());
		}

		return sprintf('iterable<%s, %s>', $this->keyType->describe(), $this->itemType->describe());
	}

	public function isDocumentableNatively(): bool
	{
		return true;
	}

	public function resolveStatic(string $className): \PHPStan\Type\Type
	{
		if ($this->getItemType() instanceof \PHPStan\Type\StaticResolvableType) {
			return new self(
				$this->keyType,
				$this->getItemType()->resolveStatic($className)
			);
		}

		return $this;
	}

	public function changeBaseClass(string $className): \PHPStan\Type\StaticResolvableType
	{
		if ($this->getItemType() instanceof \PHPStan\Type\StaticResolvableType) {
			return new self(
				$this->keyType,
				$this->getItemType()->changeBaseClass($className)
			);
		}

		return $this;
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createYes();
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		return $this->keyType;
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		return $this->getItemType();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createMaybe();
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self($properties['keyType'], $properties['itemType']);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;

trait IterableTypeTrait
{

	/** @var \PHPStan\Type\Type */
	private $itemType;

	public function getItemType(): \PHPStan\Type\Type
	{
		return $this->itemType;
	}

	public function canAccessProperties(): bool
	{
		return false;
	}

	public function hasProperty(string $propertyName): bool
	{
		return false;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canCallMethods(): bool
	{
		return false;
	}

	public function hasMethod(string $methodName): bool
	{
		return false;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canAccessConstants(): bool
	{
		return false;
	}

	public function hasConstant(string $constantName): bool
	{
		return false;
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function isClonable(): bool
	{
		return false;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\TrinaryLogic;

trait JustNullableTypeTrait
{

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return [];
	}

	public function accepts(\PHPStan\Type\Type $type): bool
	{
		if ($type instanceof $this) {
			return true;
		}

		if ($type instanceof \PHPStan\Type\CompoundType) {
			return \PHPStan\Type\CompoundTypeHelper::accepts($type, $this);
		}

		return false;
	}

	public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic
	{
		if ($type instanceof self) {
			return \PHPStan\TrinaryLogic::createYes();
		}

		if ($type instanceof \PHPStan\Type\CompoundType) {
			return $type->isSubTypeOf($this);
		}

		return \PHPStan\TrinaryLogic::createNo();
	}

	public function isDocumentableNatively(): bool
	{
		return true;
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createNo();
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class MixedType implements \PHPStan\Type\CompoundType
{

	/**
	 * @var bool
	 */
	private $isExplicitMixed;

	public function __construct(bool $isExplicitMixed = false)
	{
		$this->isExplicitMixed = $isExplicitMixed;
	}

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return [];
	}

	public function accepts(\PHPStan\Type\Type $type): bool
	{
		return true;
	}

	public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createYes();
	}

	public function isSubTypeOf(\PHPStan\Type\Type $otherType): \PHPStan\TrinaryLogic
	{
		if ($otherType instanceof self) {
			return \PHPStan\TrinaryLogic::createYes();
		}

		return \PHPStan\TrinaryLogic::createMaybe();
	}

	public function describe(): string
	{
		return 'mixed';
	}

	public function canAccessProperties(): bool
	{
		return true;
	}

	public function hasProperty(string $propertyName): bool
	{
		return false;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canCallMethods(): bool
	{
		return true;
	}

	public function hasMethod(string $methodName): bool
	{
		return false;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canAccessConstants(): bool
	{
		return true;
	}

	public function hasConstant(string $constantName): bool
	{
		return false;
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function isDocumentableNatively(): bool
	{
		return true;
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createMaybe();
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\MixedType();
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\MixedType();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createMaybe();
	}

	public function isClonable(): bool
	{
		return true;
	}

	public function isExplicitMixed(): bool
	{
		return $this->isExplicitMixed;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self($properties['isExplicitMixed']);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

class NestedArrayItemType
{

	/** @var \PHPStan\Type\Type */
	private $itemType;

	/** @var int */
	private $depth;

	public function __construct(\PHPStan\Type\Type $itemType, int $depth)
	{
		$this->itemType = $itemType;
		$this->depth = $depth;
	}

	public function getItemType(): \PHPStan\Type\Type
	{
		return $this->itemType;
	}

	public function getDepth(): int
	{
		return $this->depth;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class NeverType implements \PHPStan\Type\CompoundType
{

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return [];
	}

	public function accepts(\PHPStan\Type\Type $type): bool
	{
		return true;
	}

	public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic
	{
		if ($type instanceof self) {
			return \PHPStan\TrinaryLogic::createYes();
		}

		return \PHPStan\TrinaryLogic::createNo();
	}

	public function isSubTypeOf(\PHPStan\Type\Type $otherType): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createYes();
	}

	public function describe(): string
	{
		return '*NEVER*';
	}

	public function canAccessProperties(): bool
	{
		return false;
	}

	public function hasProperty(string $propertyName): bool
	{
		return false;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canCallMethods(): bool
	{
		return false;
	}

	public function hasMethod(string $methodName): bool
	{
		return false;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canAccessConstants(): bool
	{
		return false;
	}

	public function hasConstant(string $constantName): bool
	{
		return false;
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function isDocumentableNatively(): bool
	{
		return true;
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createYes();
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\NeverType();
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\NeverType();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createYes();
	}

	public function isClonable(): bool
	{
		return false;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class NonexistentParentClassType implements \PHPStan\Type\Type
{

	use \PHPStan\Type\JustNullableTypeTrait;

	public function describe(): string
	{
		return 'parent';
	}

	public function canAccessProperties(): bool
	{
		return false;
	}

	public function hasProperty(string $propertyName): bool
	{
		return false;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canCallMethods(): bool
	{
		return false;
	}

	public function hasMethod(string $methodName): bool
	{
		return false;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canAccessConstants(): bool
	{
		return false;
	}

	public function hasConstant(string $constantName): bool
	{
		return false;
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createNo();
	}

	public function isClonable(): bool
	{
		return false;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class NullType implements \PHPStan\Type\Type
{

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return [];
	}

	public function accepts(\PHPStan\Type\Type $type): bool
	{
		if ($type instanceof self) {
			return true;
		}

		if ($type instanceof \PHPStan\Type\CompoundType) {
			return \PHPStan\Type\CompoundTypeHelper::accepts($type, $this);
		}

		return false;
	}

	public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic
	{
		if ($type instanceof self) {
			return \PHPStan\TrinaryLogic::createYes();
		}

		if ($type instanceof \PHPStan\Type\CompoundType) {
			return $type->isSubTypeOf($this);
		}

		return \PHPStan\TrinaryLogic::createNo();
	}

	public function describe(): string
	{
		return 'null';
	}

	public function canAccessProperties(): bool
	{
		return false;
	}

	public function hasProperty(string $propertyName): bool
	{
		return false;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canCallMethods(): bool
	{
		return false;
	}

	public function hasMethod(string $methodName): bool
	{
		return false;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canAccessConstants(): bool
	{
		return false;
	}

	public function hasConstant(string $constantName): bool
	{
		return false;
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function isDocumentableNatively(): bool
	{
		return true;
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createNo();
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createNo();
	}

	public function isClonable(): bool
	{
		return false;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class ObjectType implements \PHPStan\Type\TypeWithClassName
{

	/** @var string */
	private $className;

	public function __construct(string $className)
	{
		$this->className = $className;
	}

	public function getClassName(): string
	{
		return $this->className;
	}

	public function hasProperty(string $propertyName): bool
	{
		$broker = \PHPStan\Broker\Broker::getInstance();
		if (!$broker->hasClass($this->className)) {
			return false;
		}

		return $broker->getClass($this->className)->hasProperty($propertyName);
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		$broker = \PHPStan\Broker\Broker::getInstance();
		return $broker->getClass($this->className)->getProperty($propertyName, $scope);
	}

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return [$this->className];
	}

	public function accepts(\PHPStan\Type\Type $type): bool
	{
		if ($type instanceof \PHPStan\Type\StaticType) {
			return $this->checkSubclassAcceptability($type->getBaseClass());
		}

		if ($type instanceof \PHPStan\Type\CompoundType) {
			return \PHPStan\Type\CompoundTypeHelper::accepts($type, $this);
		}

		if (!$type instanceof \PHPStan\Type\TypeWithClassName) {
			return false;
		}

		return $this->checkSubclassAcceptability($type->getClassName());
	}

	public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic
	{
		if ($type instanceof \PHPStan\Type\CompoundType) {
			return $type->isSubTypeOf($this);
		}

		if ($type instanceof \PHPStan\Type\ObjectWithoutClassType) {
			return \PHPStan\TrinaryLogic::createMaybe();
		}

		if (!$type instanceof \PHPStan\Type\TypeWithClassName) {
			return \PHPStan\TrinaryLogic::createNo();
		}

		$thisClassName = $this->className;
		$thatClassName = $type->getClassName();

		if ($thatClassName === $thisClassName) {
			return \PHPStan\TrinaryLogic::createYes();
		}

		$broker = \PHPStan\Broker\Broker::getInstance();

		if (!$broker->hasClass($thisClassName) || !$broker->hasClass($thatClassName)) {
			return \PHPStan\TrinaryLogic::createMaybe();
		}

		$thisClassReflection = $broker->getClass($thisClassName);
		$thatClassReflection = $broker->getClass($thatClassName);

		if ($thisClassReflection->getName() === $thatClassReflection->getName()) {
			return \PHPStan\TrinaryLogic::createYes();
		}

		if ($thatClassReflection->isSubclassOf($thisClassName)) {
			return \PHPStan\TrinaryLogic::createYes();
		}

		if ($thisClassReflection->isSubclassOf($thatClassName)) {
			return \PHPStan\TrinaryLogic::createMaybe();
		}

		if ($thisClassReflection->isInterface() && !$thatClassReflection->getNativeReflection()->isFinal()) {
			return \PHPStan\TrinaryLogic::createMaybe();
		}

		if ($thatClassReflection->isInterface() && !$thisClassReflection->getNativeReflection()->isFinal()) {
			return \PHPStan\TrinaryLogic::createMaybe();
		}

		return \PHPStan\TrinaryLogic::createNo();
	}

	private function checkSubclassAcceptability(string $thatClass): bool
	{
		if ($this->className === $thatClass) {
			return true;
		}

		$broker = \PHPStan\Broker\Broker::getInstance();

		if (!$broker->hasClass($this->className) || !$broker->hasClass($thatClass)) {
			return false;
		}

		$thisReflection = $broker->getClass($this->className);
		$thatReflection = $broker->getClass($thatClass);

		if ($thisReflection->getName() === $thatReflection->getName()) {
			// class alias
			return true;
		}

		if ($thisReflection->isInterface() && $thatReflection->isInterface()) {
			return $thatReflection->getNativeReflection()->implementsInterface($this->className);
		}

		return $thatReflection->isSubclassOf($this->className);
	}

	public function describe(): string
	{
		return $this->className;
	}

	public function canAccessProperties(): bool
	{
		return true;
	}

	public function canCallMethods(): bool
	{
		return strtolower($this->className) !== 'stdclass';
	}

	public function hasMethod(string $methodName): bool
	{
		$broker = \PHPStan\Broker\Broker::getInstance();
		if (!$broker->hasClass($this->className)) {
			return false;
		}

		return $broker->getClass($this->className)->hasMethod($methodName);
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		$broker = \PHPStan\Broker\Broker::getInstance();
		return $broker->getClass($this->className)->getMethod($methodName, $scope);
	}

	public function canAccessConstants(): bool
	{
		return true;
	}

	public function hasConstant(string $constantName): bool
	{
		$broker = \PHPStan\Broker\Broker::getInstance();
		if (!$broker->hasClass($this->className)) {
			return false;
		}

		return $broker->getClass($this->className)->hasConstant($constantName);
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		$broker = \PHPStan\Broker\Broker::getInstance();
		return $broker->getClass($this->className)->getConstant($constantName);
	}

	public function isDocumentableNatively(): bool
	{
		return true;
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		$broker = \PHPStan\Broker\Broker::getInstance();

		if (!$broker->hasClass($this->className)) {
			return \PHPStan\TrinaryLogic::createMaybe();
		}

		$classReflection = $broker->getClass($this->className);
		if ($classReflection->isSubclassOf(\Traversable::class) || $classReflection->getName() === \Traversable::class) {
			return \PHPStan\TrinaryLogic::createYes();
		}

		if ($classReflection->isInterface()) {
			return \PHPStan\TrinaryLogic::createMaybe();
		}

		return \PHPStan\TrinaryLogic::createNo();
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		$broker = \PHPStan\Broker\Broker::getInstance();

		if (!$broker->hasClass($this->className)) {
			return new \PHPStan\Type\ErrorType();
		}

		$classReflection = $broker->getClass($this->className);

		if ($classReflection->isSubclassOf(\Iterator::class) && $classReflection->hasNativeMethod('key')) {
			return $classReflection->getNativeMethod('key')->getReturnType();
		}

		if ($classReflection->isSubclassOf(\IteratorAggregate::class) && $classReflection->hasNativeMethod('getIterator')) {
			return \PHPStan\Type\RecursionGuard::run($this, function () use ($classReflection) {
				return $classReflection->getNativeMethod('getIterator')->getReturnType()->getIterableKeyType();
			});
		}

		if ($classReflection->isSubclassOf(\Traversable::class)) {
			return new \PHPStan\Type\MixedType();
		}

		return new \PHPStan\Type\ErrorType();
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		$broker = \PHPStan\Broker\Broker::getInstance();

		if (!$broker->hasClass($this->className)) {
			return new \PHPStan\Type\ErrorType();
		}

		$classReflection = $broker->getClass($this->className);

		if ($classReflection->isSubclassOf(\Iterator::class) && $classReflection->hasNativeMethod('current')) {
			return $classReflection->getNativeMethod('current')->getReturnType();
		}

		if ($classReflection->isSubclassOf(\IteratorAggregate::class) && $classReflection->hasNativeMethod('getIterator')) {
			return \PHPStan\Type\RecursionGuard::run($this, function () use ($classReflection) {
				return $classReflection->getNativeMethod('getIterator')->getReturnType()->getIterableValueType();
			});
		}

		if ($classReflection->isSubclassOf(\Traversable::class)) {
			return new \PHPStan\Type\MixedType();
		}

		return new \PHPStan\Type\ErrorType();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		$broker = \PHPStan\Broker\Broker::getInstance();

		if (!$broker->hasClass($this->className)) {
			return \PHPStan\TrinaryLogic::createMaybe();
		}

		$classReflection = $broker->getClass($this->className);
		if ($classReflection->hasNativeMethod('__invoke')) {
			return \PHPStan\TrinaryLogic::createYes();
		}

		if (!$classReflection->getNativeReflection()->isFinal()) {
			return \PHPStan\TrinaryLogic::createMaybe();
		}

		return \PHPStan\TrinaryLogic::createNo();
	}

	public function isClonable(): bool
	{
		return true;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self($properties['className']);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class ObjectWithoutClassType implements \PHPStan\Type\Type
{

	public function hasProperty(string $propertyName): bool
	{
		return false;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return [];
	}

	public function accepts(\PHPStan\Type\Type $type): bool
	{
		if ($type instanceof \PHPStan\Type\CompoundType) {
			return \PHPStan\Type\CompoundTypeHelper::accepts($type, $this);
		}

		return $type instanceof self || $type instanceof \PHPStan\Type\TypeWithClassName;
	}

	public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic
	{
		if ($type instanceof \PHPStan\Type\CompoundType) {
			return $type->isSubTypeOf($this);
		}

		if ($type instanceof self || $type instanceof \PHPStan\Type\TypeWithClassName) {
			return \PHPStan\TrinaryLogic::createYes();
		}

		return \PHPStan\TrinaryLogic::createNo();
	}

	public function describe(): string
	{
		return 'object';
	}

	public function canAccessProperties(): bool
	{
		return true;
	}

	public function canCallMethods(): bool
	{
		return true;
	}

	public function hasMethod(string $methodName): bool
	{
		return false;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canAccessConstants(): bool
	{
		return true;
	}

	public function hasConstant(string $constantName): bool
	{
		return false;
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function isDocumentableNatively(): bool
	{
		return true;
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createMaybe();
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\MixedType();
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\MixedType();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createMaybe();
	}

	public function isClonable(): bool
	{
		return true;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type\Php;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Type\ArrayType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;

class AllArgumentBasedFunctionReturnTypeExtension implements \PHPStan\Type\DynamicFunctionReturnTypeExtension
{

	/** @var string[] */
	private $functionNames = [
		'min' => '',
		'max' => '',
	];

	public function isFunctionSupported(\PHPStan\Reflection\FunctionReflection $functionReflection): bool
	{
		return isset($this->functionNames[strtolower($functionReflection->getName())]);
	}

	public function getTypeFromFunctionCall(\PHPStan\Reflection\FunctionReflection $functionReflection, \PhpParser\Node\Expr\FuncCall $functionCall, \PHPStan\Analyser\Scope $scope): \PHPStan\Type\Type
	{
		if (!isset($functionCall->args[0])) {
			return $functionReflection->getReturnType();
		}

		if ($functionCall->args[0]->unpack) {
			$argumentType = $scope->getType($functionCall->args[0]->value);
			if ($argumentType instanceof \PHPStan\Type\ArrayType) {
				return $argumentType->getItemType();
			}
		}

		if (count($functionCall->args) === 1) {
			$argumentType = $scope->getType($functionCall->args[0]->value);
			if ($argumentType instanceof \PHPStan\Type\ArrayType) {
				return $argumentType->getItemType();
			}
		}

		$argumentTypes = [];
		foreach ($functionCall->args as $arg) {
			$argumentTypes[] = $scope->getType($arg->value);
		}

		return \PHPStan\Type\TypeCombinator::union(...$argumentTypes);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type\Php;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Type\ArrayType;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;

class ArgumentBasedArrayFunctionReturnTypeExtension implements \PHPStan\Type\DynamicFunctionReturnTypeExtension
{

	/** @var int[] */
	private $functionNames = [
		'array_fill' => 2,
		'array_fill_keys' => 1,
	];

	public function isFunctionSupported(\PHPStan\Reflection\FunctionReflection $functionReflection): bool
	{
		return isset($this->functionNames[strtolower($functionReflection->getName())]);
	}

	public function getTypeFromFunctionCall(\PHPStan\Reflection\FunctionReflection $functionReflection, \PhpParser\Node\Expr\FuncCall $functionCall, \PHPStan\Analyser\Scope $scope): \PHPStan\Type\Type
	{
		$argumentPosition = $this->functionNames[strtolower($functionReflection->getName())];

		if (!isset($functionCall->args[$argumentPosition])) {
			return $functionReflection->getReturnType();
		}

		$argumentValue = $functionCall->args[$argumentPosition]->value;
		return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), $scope->getType($argumentValue), true);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type\Php;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Type\Type;

class ArgumentBasedFunctionReturnTypeExtension implements \PHPStan\Type\DynamicFunctionReturnTypeExtension
{

	/** @var int[] */
	private $functionNames = [
		'array_unique' => 0,
		'array_reverse' => 0,
	];

	public function isFunctionSupported(\PHPStan\Reflection\FunctionReflection $functionReflection): bool
	{
		return isset($this->functionNames[strtolower($functionReflection->getName())]);
	}

	public function getTypeFromFunctionCall(\PHPStan\Reflection\FunctionReflection $functionReflection, \PhpParser\Node\Expr\FuncCall $functionCall, \PHPStan\Analyser\Scope $scope): \PHPStan\Type\Type
	{
		$argumentPosition = $this->functionNames[strtolower($functionReflection->getName())];

		if (!isset($functionCall->args[$argumentPosition])) {
			return $functionReflection->getReturnType();
		}

		$argumentValue = $functionCall->args[$argumentPosition]->value;
		return $scope->getType($argumentValue);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type\Php;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\TrinaryLogic;
use PHPStan\Type\ArrayType;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;

class ArrayFilterFunctionReturnTypeReturnTypeExtension implements \PHPStan\Type\DynamicFunctionReturnTypeExtension
{

	public function isFunctionSupported(\PHPStan\Reflection\FunctionReflection $functionReflection): bool
	{
		return strcasecmp($functionReflection->getName(), 'array_filter') === 0;
	}

	public function getTypeFromFunctionCall(\PHPStan\Reflection\FunctionReflection $functionReflection, \PhpParser\Node\Expr\FuncCall $functionCall, \PHPStan\Analyser\Scope $scope): \PHPStan\Type\Type
	{
		$arrayArg = $functionCall->args[0]->value ?? null;
		$callbackArg = $functionCall->args[1]->value ?? null;
		$flagArg = $functionCall->args[2]->value ?? null;

		if ($arrayArg !== null) {
			$arrayArgType = $scope->getType($arrayArg);
			$keyType = $arrayArgType->getIterableKeyType();
			$itemType = $arrayArgType->getIterableValueType();

			if ($flagArg === null && $callbackArg instanceof \PhpParser\Node\Expr\Closure && count($callbackArg->stmts) === 1) {
				$statement = $callbackArg->stmts[0];
				if ($statement instanceof \PhpParser\Node\Stmt\Return_ && $statement->expr !== null && count($callbackArg->params) > 0) {
					$itemVariableName = $callbackArg->params[0]->name;
					$scope = $scope->assignVariable($itemVariableName, $itemType, \PHPStan\TrinaryLogic::createYes());
					$scope = $scope->filterByTruthyValue($statement->expr);
					$itemType = $scope->getVariableType($itemVariableName);
				}
			}

		} else {
			$keyType = new \PHPStan\Type\MixedType();
			$itemType = new \PHPStan\Type\MixedType();
		}

		return new \PHPStan\Type\ArrayType($keyType, $itemType);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type\Php;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Type\ArrayType;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;

class CallbackBasedArrayFunctionReturnTypeExtension implements \PHPStan\Type\DynamicFunctionReturnTypeExtension
{

	/** @var int[] */
	private $functionNames = [
		'array_map' => 0,
	];

	public function isFunctionSupported(\PHPStan\Reflection\FunctionReflection $functionReflection): bool
	{
		return isset($this->functionNames[strtolower($functionReflection->getName())]);
	}

	public function getTypeFromFunctionCall(\PHPStan\Reflection\FunctionReflection $functionReflection, \PhpParser\Node\Expr\FuncCall $functionCall, \PHPStan\Analyser\Scope $scope): \PHPStan\Type\Type
	{
		$argumentPosition = $this->functionNames[strtolower($functionReflection->getName())];

		if (!isset($functionCall->args[$argumentPosition])) {
			return $functionReflection->getReturnType();
		}

		$argumentValue = $functionCall->args[$argumentPosition]->value;
		if (!$argumentValue instanceof \PhpParser\Node\Expr\Closure) {
			return $functionReflection->getReturnType();
		}

		$anonymousFunctionType = $scope->getFunctionType($argumentValue->returnType, $argumentValue->returnType === null, false);

		return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), $anonymousFunctionType, true);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type\Php;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Type\Type;

class CallbackBasedFunctionReturnTypeExtension implements \PHPStan\Type\DynamicFunctionReturnTypeExtension
{

	/** @var int[] */
	private $functionNames = [
		'array_reduce' => 1,
	];

	public function isFunctionSupported(\PHPStan\Reflection\FunctionReflection $functionReflection): bool
	{
		return isset($this->functionNames[strtolower($functionReflection->getName())]);
	}

	public function getTypeFromFunctionCall(\PHPStan\Reflection\FunctionReflection $functionReflection, \PhpParser\Node\Expr\FuncCall $functionCall, \PHPStan\Analyser\Scope $scope): \PHPStan\Type\Type
	{
		$argumentPosition = $this->functionNames[strtolower($functionReflection->getName())];

		if (!isset($functionCall->args[$argumentPosition])) {
			return $functionReflection->getReturnType();
		}

		$argumentValue = $functionCall->args[$argumentPosition]->value;
		if (!$argumentValue instanceof \PhpParser\Node\Expr\Closure) {
			return $functionReflection->getReturnType();
		}

		return $scope->getFunctionType($argumentValue->returnType, $argumentValue->returnType === null, false);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

class RecursionGuard
{

	/** @var true[] */
	private static $context = [];

	public static function run(\PHPStan\Type\Type $type, callable $callback): \PHPStan\Type\Type
	{
		$key = $type->describe();
		if (isset(self::$context[$key])) {
			return new \PHPStan\Type\ErrorType();
		}

		try {
			self::$context[$key] = true;
			return $callback();
		} finally {
			unset(self::$context[$key]);
		}
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class ResourceType implements \PHPStan\Type\Type
{

	use \PHPStan\Type\JustNullableTypeTrait;

	public function describe(): string
	{
		return 'resource';
	}

	public function canAccessProperties(): bool
	{
		return false;
	}

	public function hasProperty(string $propertyName): bool
	{
		return false;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canCallMethods(): bool
	{
		return false;
	}

	public function hasMethod(string $methodName): bool
	{
		return false;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canAccessConstants(): bool
	{
		return false;
	}

	public function hasConstant(string $constantName): bool
	{
		return false;
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createNo();
	}

	public function isClonable(): bool
	{
		return false;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

interface StaticResolvableType extends \PHPStan\Type\Type
{

	public function resolveStatic(string $className): \PHPStan\Type\Type;

	public function changeBaseClass(string $className): self;

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class StaticType implements \PHPStan\Type\StaticResolvableType, \PHPStan\Type\TypeWithClassName
{

	/** @var string */
	private $baseClass;

	/** @var \PHPStan\Type\ObjectType */
	private $staticObjectType;

	public function __construct(string $baseClass)
	{
		$this->baseClass = $baseClass;
		$this->staticObjectType = new \PHPStan\Type\ObjectType($baseClass);
	}

	public function getClassName(): string
	{
		return $this->baseClass;
	}

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return $this->staticObjectType->getReferencedClasses();
	}

	public function getBaseClass(): string
	{
		return $this->baseClass;
	}

	public function accepts(\PHPStan\Type\Type $type): bool
	{
		return $this->staticObjectType->accepts($type);
	}

	public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic
	{
		if ($type instanceof self) {
			return $this->staticObjectType->isSuperTypeOf($type);
		}

		if ($type instanceof \PHPStan\Type\ObjectType) {
			return \PHPStan\TrinaryLogic::createMaybe()->and($this->staticObjectType->isSuperTypeOf($type));
		}

		if ($type instanceof \PHPStan\Type\CompoundType) {
			return $type->isSubTypeOf($this);
		}

		return \PHPStan\TrinaryLogic::createNo();
	}

	public function describe(): string
	{
		return sprintf('static(%s)', $this->baseClass);
	}

	public function canAccessProperties(): bool
	{
		return $this->staticObjectType->canAccessProperties();
	}

	public function hasProperty(string $propertyName): bool
	{
		return $this->staticObjectType->hasProperty($propertyName);
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		return $this->staticObjectType->getProperty($propertyName, $scope);
	}

	public function canCallMethods(): bool
	{
		return $this->staticObjectType->canCallMethods();
	}

	public function hasMethod(string $methodName): bool
	{
		return $this->staticObjectType->hasMethod($methodName);
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		return $this->staticObjectType->getMethod($methodName, $scope);
	}

	public function canAccessConstants(): bool
	{
		return $this->staticObjectType->canAccessConstants();
	}

	public function hasConstant(string $constantName): bool
	{
		return $this->staticObjectType->hasConstant($constantName);
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		return $this->staticObjectType->getConstant($constantName);
	}

	public function isDocumentableNatively(): bool
	{
		return $this->staticObjectType->isDocumentableNatively();
	}

	public function resolveStatic(string $className): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ObjectType($className);
	}

	public function changeBaseClass(string $className): \PHPStan\Type\StaticResolvableType
	{
		$thisClass = get_class($this);
		return new $thisClass($className);
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		$broker = \PHPStan\Broker\Broker::getInstance();

		if (!$broker->hasClass($this->baseClass)) {
			return \PHPStan\TrinaryLogic::createMaybe();
		}

		$classReflection = $broker->getClass($this->baseClass);
		if ($classReflection->isSubclassOf(\Traversable::class) || $classReflection->getName() === \Traversable::class) {
			return \PHPStan\TrinaryLogic::createYes();
		}

		return \PHPStan\TrinaryLogic::createNo();
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		$broker = \PHPStan\Broker\Broker::getInstance();

		if (!$broker->hasClass($this->baseClass)) {
			return new \PHPStan\Type\ErrorType();
		}

		$classReflection = $broker->getClass($this->baseClass);

		if ($classReflection->isSubclassOf(\Iterator::class) && $classReflection->hasNativeMethod('key')) {
			return $classReflection->getNativeMethod('key')->getReturnType();
		}

		if ($classReflection->isSubclassOf(\IteratorAggregate::class) && $classReflection->hasNativeMethod('getIterator')) {
			return \PHPStan\Type\RecursionGuard::run($this, function () use ($classReflection) {
				return $classReflection->getNativeMethod('getIterator')->getReturnType()->getIterableKeyType();
			});
		}

		if ($classReflection->isSubclassOf(\Traversable::class)) {
			return new \PHPStan\Type\MixedType();
		}

		return new \PHPStan\Type\ErrorType();
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		$broker = \PHPStan\Broker\Broker::getInstance();

		if (!$broker->hasClass($this->baseClass)) {
			return new \PHPStan\Type\ErrorType();
		}

		$classReflection = $broker->getClass($this->baseClass);

		if ($classReflection->isSubclassOf(\Iterator::class) && $classReflection->hasNativeMethod('current')) {
			return $classReflection->getNativeMethod('current')->getReturnType();
		}

		if ($classReflection->isSubclassOf(\IteratorAggregate::class) && $classReflection->hasNativeMethod('getIterator')) {
			return \PHPStan\Type\RecursionGuard::run($this, function () use ($classReflection) {
				return $classReflection->getNativeMethod('getIterator')->getReturnType()->getIterableValueType();
			});
		}

		if ($classReflection->isSubclassOf(\Traversable::class)) {
			return new \PHPStan\Type\MixedType();
		}

		return new \PHPStan\Type\ErrorType();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		$broker = \PHPStan\Broker\Broker::getInstance();

		if (!$broker->hasClass($this->baseClass)) {
			return \PHPStan\TrinaryLogic::createMaybe();
		}

		if ($broker->getClass($this->baseClass)->hasMethod('__invoke')) {
			return \PHPStan\TrinaryLogic::createYes();
		}

		return \PHPStan\TrinaryLogic::createNo();
	}

	public function isClonable(): bool
	{
		return true;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new static($properties['baseClass']);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class StringType implements \PHPStan\Type\Type
{

	use \PHPStan\Type\JustNullableTypeTrait;

	public function describe(): string
	{
		return 'string';
	}

	public function canAccessProperties(): bool
	{
		return false;
	}

	public function hasProperty(string $propertyName): bool
	{
		return false;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canCallMethods(): bool
	{
		return false;
	}

	public function hasMethod(string $methodName): bool
	{
		return false;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canAccessConstants(): bool
	{
		return false;
	}

	public function hasConstant(string $constantName): bool
	{
		return false;
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createNo();
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createMaybe();
	}

	public function isClonable(): bool
	{
		return false;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

class ThisType extends \PHPStan\Type\StaticType
{

	public function describe(): string
	{
		return sprintf('$this(%s)', $this->getBaseClass());
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class TrueBooleanType implements \PHPStan\Type\BooleanType
{

	public function describe(): string
	{
		return 'true';
	}

	public function canAccessProperties(): bool
	{
		return false;
	}

	public function hasProperty(string $propertyName): bool
	{
		return false;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canCallMethods(): bool
	{
		return false;
	}

	public function hasMethod(string $methodName): bool
	{
		return false;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canAccessConstants(): bool
	{
		return false;
	}

	public function hasConstant(string $constantName): bool
	{
		return false;
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return [];
	}

	public function accepts(\PHPStan\Type\Type $type): bool
	{
		if ($type instanceof self) {
			return true;
		}

		if ($type instanceof \PHPStan\Type\CompoundType) {
			return \PHPStan\Type\CompoundTypeHelper::accepts($type, $this);
		}

		return false;
	}

	public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic
	{
		if ($type instanceof self) {
			return \PHPStan\TrinaryLogic::createYes();
		}

		if ($type instanceof \PHPStan\Type\TrueOrFalseBooleanType) {
			return \PHPStan\TrinaryLogic::createMaybe();
		}

		if ($type instanceof \PHPStan\Type\CompoundType) {
			return $type->isSubTypeOf($this);
		}

		return \PHPStan\TrinaryLogic::createNo();
	}

	public function isDocumentableNatively(): bool
	{
		return true;
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createNo();
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createNo();
	}

	public function isClonable(): bool
	{
		return false;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class TrueOrFalseBooleanType implements \PHPStan\Type\BooleanType
{

	public function describe(): string
	{
		return 'bool';
	}

	public function canAccessProperties(): bool
	{
		return false;
	}

	public function hasProperty(string $propertyName): bool
	{
		return false;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canCallMethods(): bool
	{
		return false;
	}

	public function hasMethod(string $methodName): bool
	{
		return false;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canAccessConstants(): bool
	{
		return false;
	}

	public function hasConstant(string $constantName): bool
	{
		return false;
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return [];
	}

	public function accepts(\PHPStan\Type\Type $type): bool
	{
		if ($type instanceof \PHPStan\Type\BooleanType) {
			return true;
		}

		if ($type instanceof \PHPStan\Type\CompoundType) {
			return \PHPStan\Type\CompoundTypeHelper::accepts($type, $this);
		}

		return false;
	}

	public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic
	{
		if ($type instanceof \PHPStan\Type\BooleanType) {
			return \PHPStan\TrinaryLogic::createYes();
		}

		if ($type instanceof \PHPStan\Type\CompoundType) {
			return $type->isSubTypeOf($this);
		}

		return \PHPStan\TrinaryLogic::createNo();
	}

	public function isDocumentableNatively(): bool
	{
		return true;
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createNo();
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createNo();
	}

	public function isClonable(): bool
	{
		return false;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self();
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

interface Type
{

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array;

	public function accepts(\PHPStan\Type\Type $type): bool;

	public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic;

	public function describe(): string;

	public function canAccessProperties(): bool;

	public function hasProperty(string $propertyName): bool;

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection;

	public function canCallMethods(): bool;

	public function hasMethod(string $methodName): bool;

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection;

	public function canAccessConstants(): bool;

	public function hasConstant(string $constantName): bool;

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection;

	public function isDocumentableNatively(): bool;

	public function isIterable(): \PHPStan\TrinaryLogic;

	public function getIterableKeyType(): \PHPStan\Type\Type;

	public function getIterableValueType(): \PHPStan\Type\Type;

	public function isCallable(): \PHPStan\TrinaryLogic;

	public function isClonable(): bool;

	public static function __set_state(array $properties): self;

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

class TypeCombinator
{

	/** @var bool|null */
	private static $unionTypesEnabled;

	public static function setUnionTypesEnabled(bool $enabled)
	{
		if (self::$unionTypesEnabled !== null) {
			throw new \PHPStan\ShouldNotHappenException();
		}

		self::$unionTypesEnabled = $enabled;
	}

	public static function isUnionTypesEnabled(): bool
	{
		if (self::$unionTypesEnabled === null) {
			throw new \PHPStan\ShouldNotHappenException();
		}

		return self::$unionTypesEnabled;
	}

	public static function addNull(\PHPStan\Type\Type $type): \PHPStan\Type\Type
	{
		return self::union($type, new \PHPStan\Type\NullType());
	}

	public static function remove(\PHPStan\Type\Type $fromType, \PHPStan\Type\Type $typeToRemove): \PHPStan\Type\Type
	{
		if ($typeToRemove instanceof \PHPStan\Type\UnionType) {
			foreach ($typeToRemove->getTypes() as $unionTypeToRemove) {
				$fromType = self::remove($fromType, $unionTypeToRemove);
			}
			return $fromType;
		}

		if ($fromType instanceof \PHPStan\Type\TrueOrFalseBooleanType) {
			if ($typeToRemove instanceof \PHPStan\Type\TrueBooleanType) {
				return new \PHPStan\Type\FalseBooleanType();
			} elseif ($typeToRemove instanceof \PHPStan\Type\FalseBooleanType) {
				return new \PHPStan\Type\TrueBooleanType();
			}
		} elseif ($fromType instanceof \PHPStan\Type\UnionType) {
			$innerTypes = [];
			foreach ($fromType->getTypes() as $innerType) {
				$innerTypes[] = self::remove($innerType, $typeToRemove);
			}

			return self::union(...$innerTypes);
		}

		if ($typeToRemove->isSuperTypeOf($fromType)->yes()) {
			return new \PHPStan\Type\NeverType();
		}

		return $fromType;
	}

	public static function removeNull(\PHPStan\Type\Type $type): \PHPStan\Type\Type
	{
		return self::remove($type, new \PHPStan\Type\NullType());
	}

	public static function containsNull(\PHPStan\Type\Type $type): bool
	{
		if ($type instanceof \PHPStan\Type\UnionType) {
			foreach ($type->getTypes() as $innerType) {
				if ($innerType instanceof \PHPStan\Type\NullType) {
					return true;
				}
			}

			return false;
		}

		return $type instanceof \PHPStan\Type\NullType;
	}

	public static function union(\PHPStan\Type\Type ...$types): \PHPStan\Type\Type
	{
		// transform A | (B | C) to A | B | C
		for ($i = 0; $i < count($types); $i++) {
			if ($types[$i] instanceof \PHPStan\Type\UnionType) {
				array_splice($types, $i, 1, $types[$i]->getTypes());
			}
		}

		// simplify true | false to bool
		// simplify string[] | int[] to (string|int)[]
		for ($i = 0; $i < count($types); $i++) {
			for ($j = $i + 1; $j < count($types); $j++) {
				if ($types[$i] instanceof \PHPStan\Type\TrueBooleanType && $types[$j] instanceof \PHPStan\Type\FalseBooleanType) {
					$types[$i] = new \PHPStan\Type\TrueOrFalseBooleanType();
					array_splice($types, $j, 1);
					continue 2;
				} elseif ($types[$i] instanceof \PHPStan\Type\FalseBooleanType && $types[$j] instanceof \PHPStan\Type\TrueBooleanType) {
					$types[$i] = new \PHPStan\Type\TrueOrFalseBooleanType();
					array_splice($types, $j, 1);
					continue 2;
				} elseif ($types[$i] instanceof \PHPStan\Type\ArrayType && $types[$j] instanceof \PHPStan\Type\ArrayType) {
					$types[$i] = new \PHPStan\Type\ArrayType(
						self::union($types[$i]->getIterableKeyType(), $types[$j]->getIterableKeyType()),
						self::union($types[$i]->getIterableValueType(), $types[$j]->getIterableValueType()),
						$types[$i]->isItemTypeInferredFromLiteralArray() || $types[$j]->isItemTypeInferredFromLiteralArray(),
						$types[$i]->isCallable()->and($types[$j]->isCallable())
					);
					array_splice($types, $j, 1);
					continue 2;
				} elseif ($types[$i] instanceof \PHPStan\Type\IterableIterableType && $types[$j] instanceof \PHPStan\Type\IterableIterableType) {
					$types[$i] = new \PHPStan\Type\IterableIterableType(
						self::union($types[$i]->getIterableKeyType(), $types[$j]->getIterableKeyType()),
						self::union($types[$i]->getIterableValueType(), $types[$j]->getIterableValueType())
					);
					array_splice($types, $j, 1);
					continue 2;
				}
			}
		}

		// transform A | A to A
		// transform A | never to A
		// transform true | bool to bool
		for ($i = 0; $i < count($types); $i++) {
			for ($j = $i + 1; $j < count($types); $j++) {
				if ($types[$j]->isSuperTypeOf($types[$i])->yes()) {
					array_splice($types, $i--, 1);
					continue 2;

				} elseif ($types[$i]->isSuperTypeOf($types[$j])->yes()) {
					array_splice($types, $j--, 1);
					continue 1;
				}
			}
		}

		if (count($types) === 0) {
			return new \PHPStan\Type\NeverType();

		} elseif (count($types) === 1) {
			return $types[0];
		}

		return new \PHPStan\Type\UnionType($types);
	}

	public static function intersect(\PHPStan\Type\Type ...$types): \PHPStan\Type\Type
	{
		// transform A & (B | C) to (A & B) | (A & C)
		foreach ($types as $i => $type) {
			if ($type instanceof \PHPStan\Type\UnionType) {
				$topLevelUnionSubTypes = [];
				foreach ($type->getTypes() as $innerUnionSubType) {
					$topLevelUnionSubTypes[] = self::intersect(
						$innerUnionSubType,
						...array_slice($types, 0, $i),
						...array_slice($types, $i + 1)
					);
				}

				return self::union(...$topLevelUnionSubTypes);
			}
		}

		// transform A & (B & C) to A & B & C
		foreach ($types as $i => &$type) {
			if ($type instanceof \PHPStan\Type\IntersectionType) {
				array_splice($types, $i, 1, $type->getTypes());
			}
		}

		// transform IntegerType & ConstantIntegerType to ConstantIntegerType
		// transform Child & Parent to Child
		// transform Object & ~null to Object
		// transform A & A to A
		// transform int[] & string to never
		// transform callable & int to never
		// transform A & ~A to never
		// transform int & string to never
		for ($i = 0; $i < count($types); $i++) {
			for ($j = $i + 1; $j < count($types); $j++) {
				$isSuperTypeA = $types[$j]->isSuperTypeOf($types[$i]);
				if ($isSuperTypeA->no()) {
					return new \PHPStan\Type\NeverType();

				} elseif ($isSuperTypeA->yes()) {
					array_splice($types, $j--, 1);
					continue;
				}

				$isSuperTypeB = $types[$i]->isSuperTypeOf($types[$j]);
				if ($isSuperTypeB->maybe()) {
					continue;

				} elseif ($isSuperTypeB->yes()) {
					array_splice($types, $i--, 1);
					continue 2;
				}
			}
		}

		if (count($types) === 1) {
			return $types[0];

		} else {
			return new \PHPStan\Type\IntersectionType($types);
		}
	}

	public static function shouldSkipUnionTypeAccepts(\PHPStan\Type\UnionType $unionType): bool
	{
		$typesLimit = self::containsNull($unionType) ? 2 : 1;
		return !self::isUnionTypesEnabled() && count($unionType->getTypes()) > $typesLimit;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

interface TypeWithClassName extends \PHPStan\Type\Type
{

	public function getClassName(): string;

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Broker\Broker;

class TypehintHelper
{

	private static function getTypeObjectFromTypehint(string $typeString, string $selfClass = null): \PHPStan\Type\Type
	{
		switch (strtolower($typeString)) {
			case 'int':
				return new \PHPStan\Type\IntegerType();
			case 'bool':
				return new \PHPStan\Type\TrueOrFalseBooleanType();
			case 'string':
				return new \PHPStan\Type\StringType();
			case 'float':
				return new \PHPStan\Type\FloatType();
			case 'array':
				return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType());
			case 'iterable':
				return new \PHPStan\Type\IterableIterableType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType());
			case 'callable':
				return new \PHPStan\Type\CallableType();
			case 'void':
				return new \PHPStan\Type\VoidType();
			case 'object':
				return new \PHPStan\Type\ObjectWithoutClassType();
			case 'self':
				return $selfClass !== null ? new \PHPStan\Type\ObjectType($selfClass) : new \PHPStan\Type\ErrorType();
			case 'parent':
				$broker = \PHPStan\Broker\Broker::getInstance();
				if ($selfClass !== null && $broker->hasClass($selfClass)) {
					$classReflection = $broker->getClass($selfClass);
					if ($classReflection->getParentClass() !== false) {
						return new \PHPStan\Type\ObjectType($classReflection->getParentClass()->getName());
					}
				}
				return new \PHPStan\Type\NonexistentParentClassType();
			default:
				return new \PHPStan\Type\ObjectType($typeString);
		}
	}

	public static function decideTypeFromReflection(
		\ReflectionType $reflectionType = null,
		\PHPStan\Type\Type $phpDocType = null,
		string $selfClass = null,
		bool $isVariadic = false
	): \PHPStan\Type\Type
	{
		if ($reflectionType === null) {
			return $phpDocType ?? new \PHPStan\Type\MixedType();
		}

		$reflectionTypeString = (string) $reflectionType;
		if (\PHPStanVendor\Nette\Utils\Strings::endsWith(strtolower($reflectionTypeString), '\\object')) {
			$reflectionTypeString = 'object';
		}
		$type = self::getTypeObjectFromTypehint($reflectionTypeString, $selfClass);
		if ($reflectionType->allowsNull()) {
			$type = \PHPStan\Type\TypeCombinator::addNull($type);
		}

		if ($isVariadic) {
			$type = new \PHPStan\Type\ArrayType(new \PHPStan\Type\IntegerType(), $type);
		}

		return self::decideType($type, $phpDocType);
	}

	public static function decideType(
		\PHPStan\Type\Type $type,
		\PHPStan\Type\Type $phpDocType = null
	): \PHPStan\Type\Type
	{
		if ($phpDocType !== null && !$phpDocType instanceof \PHPStan\Type\ErrorType) {
			if ($type instanceof \PHPStan\Type\VoidType || $phpDocType instanceof \PHPStan\Type\VoidType) {
				return new \PHPStan\Type\VoidType();
			}

			if (\PHPStan\Type\TypeCombinator::removeNull($type) instanceof \PHPStan\Type\IterableIterableType) {
				if ($phpDocType instanceof \PHPStan\Type\UnionType) {
					$innerTypes = [];
					foreach ($phpDocType->getTypes() as $innerType) {
						if ($innerType instanceof \PHPStan\Type\ArrayType) {
							$innerTypes[] = new \PHPStan\Type\IterableIterableType(
								$innerType->getIterableKeyType(),
								$innerType->getIterableValueType()
							);
						} else {
							$innerTypes[] = $innerType;
						}
					}
					$phpDocType = new \PHPStan\Type\UnionType($innerTypes);
				} elseif ($phpDocType instanceof \PHPStan\Type\ArrayType) {
					$phpDocType = new \PHPStan\Type\IterableIterableType(
						$phpDocType->getIterableKeyType(),
						$phpDocType->getIterableValueType()
					);
				}
			}

			return $type->isSuperTypeOf($phpDocType)->yes() ? $phpDocType : $type;
		}

		return $type;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class UnionType implements \PHPStan\Type\CompoundType, \PHPStan\Type\StaticResolvableType
{

	/** @var \PHPStan\Type\Type[] */
	private $types;

	/**
	 * @param Type[] $types
	 */
	public function __construct(array $types)
	{
		$throwException = function () use ($types) {
			throw new \PHPStan\ShouldNotHappenException(sprintf(
				'Cannot create %s with: %s',
				self::class,
				implode(', ', array_map(function (\PHPStan\Type\Type $type): string {
					return $type->describe();
				}, $types))
			));
		};
		if (count($types) < 2) {
			$throwException();
		}
		foreach ($types as $type) {
			if ($type instanceof \PHPStan\Type\UnionType) {
				$throwException();
			}
		}
		$this->types = \PHPStan\Type\UnionTypeHelper::sortTypes($types);
	}

	/**
	 * @return \PHPStan\Type\Type[]
	 */
	public function getTypes(): array
	{
		return $this->types;
	}

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return \PHPStan\Type\UnionTypeHelper::getReferencedClasses($this->getTypes());
	}

	public function accepts(\PHPStan\Type\Type $type): bool
	{
		if ($type instanceof \PHPStan\Type\CompoundType) {
			return \PHPStan\Type\CompoundTypeHelper::accepts($type, $this);
		}

		if (\PHPStan\Type\TypeCombinator::shouldSkipUnionTypeAccepts($this)) {
			return true;
		}

		foreach ($this->getTypes() as $otherType) {
			if ($otherType->accepts($type)) {
				return true;
			}
		}

		return false;
	}

	public function isSuperTypeOf(\PHPStan\Type\Type $otherType): \PHPStan\TrinaryLogic
	{
		if ($otherType instanceof self || $otherType instanceof \PHPStan\Type\IterableIterableType) {
			return $otherType->isSubTypeOf($this);
		}

		$results = [];
		foreach ($this->getTypes() as $innerType) {
			$results[] = $innerType->isSuperTypeOf($otherType);
		}

		return \PHPStan\TrinaryLogic::createNo()->or(...$results);
	}

	public function isSubTypeOf(\PHPStan\Type\Type $otherType): \PHPStan\TrinaryLogic
	{
		$results = [];
		foreach ($this->getTypes() as $innerType) {
			$results[] = $otherType->isSuperTypeOf($innerType);
		}

		return \PHPStan\TrinaryLogic::extremeIdentity(...$results);
	}

	public function describe(): string
	{
		$typeNames = [];

		foreach ($this->types as $type) {
			if ($type instanceof \PHPStan\Type\IntersectionType) {
				$typeNames[] = sprintf('(%s)', $type->describe());
			} else {
				$typeNames[] = $type->describe();
			}
		}

		return implode('|', $typeNames);
	}

	public function canAccessProperties(): bool
	{
		foreach ($this->types as $type) {
			if (!$type->canAccessProperties()) {
				return false;
			}
		}

		return true;
	}

	public function hasProperty(string $propertyName): bool
	{
		foreach ($this->types as $type) {
			if ($type instanceof \PHPStan\Type\NullType) {
				continue;
			}
			if (!$type->hasProperty($propertyName)) {
				return false;
			}
		}

		return true;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		foreach ($this->types as $type) {
			if ($type instanceof \PHPStan\Type\NullType) {
				continue;
			}
			return $type->getProperty($propertyName, $scope);
		}

		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canCallMethods(): bool
	{
		foreach ($this->types as $type) {
			if (!$type->canCallMethods()) {
				return false;
			}
		}

		return true;
	}

	public function hasMethod(string $methodName): bool
	{
		foreach ($this->types as $type) {
			if ($type instanceof \PHPStan\Type\NullType) {
				continue;
			}
			if (!$type->hasMethod($methodName)) {
				return false;
			}
		}

		return true;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		foreach ($this->types as $type) {
			if ($type instanceof \PHPStan\Type\NullType) {
				continue;
			}
			return $type->getMethod($methodName, $scope);
		}

		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canAccessConstants(): bool
	{
		foreach ($this->types as $type) {
			if (!$type->canAccessConstants()) {
				return false;
			}
		}

		return true;
	}

	public function hasConstant(string $constantName): bool
	{
		foreach ($this->types as $type) {
			if ($type instanceof \PHPStan\Type\NullType) {
				continue;
			}
			if (!$type->hasConstant($constantName)) {
				return false;
			}
		}

		return true;
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		foreach ($this->types as $type) {
			if ($type instanceof \PHPStan\Type\NullType) {
				continue;
			}
			return $type->getConstant($constantName);
		}

		throw new \PHPStan\ShouldNotHappenException();
	}

	public function isDocumentableNatively(): bool
	{
		return false;
	}

	public function resolveStatic(string $className): \PHPStan\Type\Type
	{
		return new self(\PHPStan\Type\UnionTypeHelper::resolveStatic($className, $this->getTypes()));
	}

	public function changeBaseClass(string $className): \PHPStan\Type\StaticResolvableType
	{
		return new self(\PHPStan\Type\UnionTypeHelper::changeBaseClass($className, $this->getTypes()));
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		return $this->unionResults(function (\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic {
			return $type->isIterable();
		});
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		return $this->unionTypes(function (\PHPStan\Type\Type $type): \PHPStan\Type\Type {
			return $type->getIterableKeyType();
		});
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		return $this->unionTypes(function (\PHPStan\Type\Type $type): \PHPStan\Type\Type {
			return $type->getIterableValueType();
		});
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return $this->unionResults(function (\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic {
			return $type->isCallable();
		});
	}

	public function isClonable(): bool
	{
		foreach ($this->types as $type) {
			if (!$type->isClonable()) {
				return false;
			}
		}

		return true;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self($properties['types']);
	}

	private function unionResults(callable $getResult): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::extremeIdentity(...array_map($getResult, $this->types));
	}

	private function unionTypes(callable $getType): \PHPStan\Type\Type
	{
		return \PHPStan\Type\TypeCombinator::union(...array_map($getType, $this->types));
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

class UnionTypeHelper
{

	/**
	 * @param string $className
	 * @param \PHPStan\Type\Type[] $types
	 * @return \PHPStan\Type\Type[]
	 */
	public static function resolveStatic(string $className, array $types): array
	{
		foreach ($types as $i => $type) {
			if ($type instanceof \PHPStan\Type\StaticResolvableType) {
				$types[$i] = $type->resolveStatic($className);
			}
		}

		return $types;
	}

	/**
	 * @param string $className
	 * @param \PHPStan\Type\Type[] $types
	 * @return \PHPStan\Type\Type[]
	 */
	public static function changeBaseClass(string $className, array $types): array
	{
		foreach ($types as $i => $type) {
			if ($type instanceof \PHPStan\Type\StaticResolvableType) {
				$types[$i] = $type->changeBaseClass($className);
			}
		}

		return $types;
	}

	/**
	 * @param \PHPStan\Type\Type[] $types
	 * @return string[]
	 */
	public static function getReferencedClasses(array $types): array
	{
		$subTypeClasses = [];
		foreach ($types as $type) {
			$subTypeClasses[] = $type->getReferencedClasses();
		}

		return array_merge(...$subTypeClasses);
	}

	/**
	 * @param \PHPStan\Type\Type[] $types
	 * @return \PHPStan\Type\Type[]
	 */
	public static function sortTypes(array $types): array
	{
		usort($types, function (\PHPStan\Type\Type $a, \PHPStan\Type\Type $b): int {
			if ($a instanceof \PHPStan\Type\NullType) {
				return 1;
			} elseif ($b instanceof \PHPStan\Type\NullType) {
				return -1;
			}

			return strcasecmp($a->describe(), $b->describe());
		});
		return $types;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;

class VoidType implements \PHPStan\Type\Type
{

	/**
	 * @return string[]
	 */
	public function getReferencedClasses(): array
	{
		return [];
	}

	public function accepts(\PHPStan\Type\Type $type): bool
	{
		return $type instanceof self;
	}

	public function isSuperTypeOf(\PHPStan\Type\Type $type): \PHPStan\TrinaryLogic
	{
		if ($type instanceof self) {
			return \PHPStan\TrinaryLogic::createYes();
		}

		if ($type instanceof \PHPStan\Type\CompoundType) {
			return $type->isSubTypeOf($this);
		}

		return \PHPStan\TrinaryLogic::createNo();
	}

	public function describe(): string
	{
		return 'void';
	}

	public function canAccessProperties(): bool
	{
		return false;
	}

	public function hasProperty(string $propertyName): bool
	{
		return false;
	}

	public function getProperty(string $propertyName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\PropertyReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canCallMethods(): bool
	{
		return false;
	}

	public function hasMethod(string $methodName): bool
	{
		return false;
	}

	public function getMethod(string $methodName, \PHPStan\Analyser\Scope $scope): \PHPStan\Reflection\MethodReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function canAccessConstants(): bool
	{
		return false;
	}

	public function hasConstant(string $constantName): bool
	{
		return false;
	}

	public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection
	{
		throw new \PHPStan\ShouldNotHappenException();
	}

	public function isDocumentableNatively(): bool
	{
		return true;
	}

	public function isIterable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createNo();
	}

	public function getIterableKeyType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

	public function getIterableValueType(): \PHPStan\Type\Type
	{
		return new \PHPStan\Type\ErrorType();
	}

	public function isCallable(): \PHPStan\TrinaryLogic
	{
		return \PHPStan\TrinaryLogic::createNo();
	}

	public function isClonable(): bool
	{
		return false;
	}

	public static function __set_state(array $properties): \PHPStan\Type\Type
	{
		return new self();
	}

}
<?php

// autoload.php @generated by Composer

require_once __DIR__ . '/composer/autoload_real.php';

return ComposerAutoloaderInit125b023f43356e6992e24cd9f1067aeb::getLoader();
<?php
<?php

/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Composer\Autoload;

/**
 * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
 *
 *     $loader = new \Composer\Autoload\ClassLoader();
 *
 *     // register classes with namespaces
 *     $loader->add('Symfony\Component', __DIR__.'/component');
 *     $loader->add('Symfony',           __DIR__.'/framework');
 *
 *     // activate the autoloader
 *     $loader->register();
 *
 *     // to enable searching the include path (eg. for PEAR packages)
 *     $loader->setUseIncludePath(true);
 *
 * In this example, if you try to use a class in the Symfony\Component
 * namespace or one of its children (Symfony\Component\Console for instance),
 * the autoloader will first look for the class under the component/
 * directory, and it will then fallback to the framework/ directory if not
 * found before giving up.
 *
 * This class is loosely based on the Symfony UniversalClassLoader.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @see    http://www.php-fig.org/psr/psr-0/
 * @see    http://www.php-fig.org/psr/psr-4/
 */
class ClassLoader
{
    // PSR-4
    private $prefixLengthsPsr4 = array();
    private $prefixDirsPsr4 = array();
    private $fallbackDirsPsr4 = array();

    // PSR-0
    private $prefixesPsr0 = array();
    private $fallbackDirsPsr0 = array();

    private $useIncludePath = false;
    private $classMap = array();
    private $classMapAuthoritative = false;
    private $missingClasses = array();
    private $apcuPrefix;

    public function getPrefixes()
    {
        if (!empty($this->prefixesPsr0)) {
            return call_user_func_array('array_merge', $this->prefixesPsr0);
        }

        return array();
    }

    public function getPrefixesPsr4()
    {
        return $this->prefixDirsPsr4;
    }

    public function getFallbackDirs()
    {
        return $this->fallbackDirsPsr0;
    }

    public function getFallbackDirsPsr4()
    {
        return $this->fallbackDirsPsr4;
    }

    public function getClassMap()
    {
        return $this->classMap;
    }

    /**
     * @param array $classMap Class to filename map
     */
    public function addClassMap(array $classMap)
    {
        if ($this->classMap) {
            $this->classMap = array_merge($this->classMap, $classMap);
        } else {
            $this->classMap = $classMap;
        }
    }

    /**
     * Registers a set of PSR-0 directories for a given prefix, either
     * appending or prepending to the ones previously set for this prefix.
     *
     * @param string       $prefix  The prefix
     * @param array|string $paths   The PSR-0 root directories
     * @param bool         $prepend Whether to prepend the directories
     */
    public function add($prefix, $paths, $prepend = false)
    {
        if (!$prefix) {
            if ($prepend) {
                $this->fallbackDirsPsr0 = array_merge(
                    (array) $paths,
                    $this->fallbackDirsPsr0
                );
            } else {
                $this->fallbackDirsPsr0 = array_merge(
                    $this->fallbackDirsPsr0,
                    (array) $paths
                );
            }

            return;
        }

        $first = $prefix[0];
        if (!isset($this->prefixesPsr0[$first][$prefix])) {
            $this->prefixesPsr0[$first][$prefix] = (array) $paths;

            return;
        }
        if ($prepend) {
            $this->prefixesPsr0[$first][$prefix] = array_merge(
                (array) $paths,
                $this->prefixesPsr0[$first][$prefix]
            );
        } else {
            $this->prefixesPsr0[$first][$prefix] = array_merge(
                $this->prefixesPsr0[$first][$prefix],
                (array) $paths
            );
        }
    }

    /**
     * Registers a set of PSR-4 directories for a given namespace, either
     * appending or prepending to the ones previously set for this namespace.
     *
     * @param string       $prefix  The prefix/namespace, with trailing '\\'
     * @param array|string $paths   The PSR-4 base directories
     * @param bool         $prepend Whether to prepend the directories
     *
     * @throws \InvalidArgumentException
     */
    public function addPsr4($prefix, $paths, $prepend = false)
    {
        if (!$prefix) {
            // Register directories for the root namespace.
            if ($prepend) {
                $this->fallbackDirsPsr4 = array_merge(
                    (array) $paths,
                    $this->fallbackDirsPsr4
                );
            } else {
                $this->fallbackDirsPsr4 = array_merge(
                    $this->fallbackDirsPsr4,
                    (array) $paths
                );
            }
        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
            // Register directories for a new namespace.
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
        } elseif ($prepend) {
            // Prepend directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge(
                (array) $paths,
                $this->prefixDirsPsr4[$prefix]
            );
        } else {
            // Append directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge(
                $this->prefixDirsPsr4[$prefix],
                (array) $paths
            );
        }
    }

    /**
     * Registers a set of PSR-0 directories for a given prefix,
     * replacing any others previously set for this prefix.
     *
     * @param string       $prefix The prefix
     * @param array|string $paths  The PSR-0 base directories
     */
    public function set($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr0 = (array) $paths;
        } else {
            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
        }
    }

    /**
     * Registers a set of PSR-4 directories for a given namespace,
     * replacing any others previously set for this namespace.
     *
     * @param string       $prefix The prefix/namespace, with trailing '\\'
     * @param array|string $paths  The PSR-4 base directories
     *
     * @throws \InvalidArgumentException
     */
    public function setPsr4($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr4 = (array) $paths;
        } else {
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
        }
    }

    /**
     * Turns on searching the include path for class files.
     *
     * @param bool $useIncludePath
     */
    public function setUseIncludePath($useIncludePath)
    {
        $this->useIncludePath = $useIncludePath;
    }

    /**
     * Can be used to check if the autoloader uses the include path to check
     * for classes.
     *
     * @return bool
     */
    public function getUseIncludePath()
    {
        return $this->useIncludePath;
    }

    /**
     * Turns off searching the prefix and fallback directories for classes
     * that have not been registered with the class map.
     *
     * @param bool $classMapAuthoritative
     */
    public function setClassMapAuthoritative($classMapAuthoritative)
    {
        $this->classMapAuthoritative = $classMapAuthoritative;
    }

    /**
     * Should class lookup fail if not found in the current class map?
     *
     * @return bool
     */
    public function isClassMapAuthoritative()
    {
        return $this->classMapAuthoritative;
    }

    /**
     * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
     *
     * @param string|null $apcuPrefix
     */
    public function setApcuPrefix($apcuPrefix)
    {
        $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
    }

    /**
     * The APCu prefix in use, or null if APCu caching is not enabled.
     *
     * @return string|null
     */
    public function getApcuPrefix()
    {
        return $this->apcuPrefix;
    }

    /**
     * Registers this instance as an autoloader.
     *
     * @param bool $prepend Whether to prepend the autoloader or not
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
    }

    /**
     * Unregisters this instance as an autoloader.
     */
    public function unregister()
    {
        spl_autoload_unregister(array($this, 'loadClass'));
    }

    /**
     * Loads the given class or interface.
     *
     * @param  string    $class The name of the class
     * @return bool|null True if loaded, null otherwise
     */
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            includeFile($file);

            return true;
        }
    }

    /**
     * Finds the path to the file where the class is defined.
     *
     * @param string $class The name of the class
     *
     * @return string|false The path if found, false otherwise
     */
    public function findFile($class)
    {
        // class map lookup
        if (isset($this->classMap[$class])) {
            return $this->classMap[$class];
        }
        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
            return false;
        }
        if (null !== $this->apcuPrefix) {
            $file = apcu_fetch($this->apcuPrefix.$class, $hit);
            if ($hit) {
                return $file;
            }
        }

        $file = $this->findFileWithExtension($class, '.php');

        // Search for Hack files if we are running on HHVM
        if (false === $file && defined('HHVM_VERSION')) {
            $file = $this->findFileWithExtension($class, '.hh');
        }

        if (null !== $this->apcuPrefix) {
            apcu_add($this->apcuPrefix.$class, $file);
        }

        if (false === $file) {
            // Remember that this class does not exist.
            $this->missingClasses[$class] = true;
        }

        return $file;
    }

    private function findFileWithExtension($class, $ext)
    {
        // PSR-4 lookup
        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;

        $first = $class[0];
        if (isset($this->prefixLengthsPsr4[$first])) {
            $subPath = $class;
            while (false !== $lastPos = strrpos($subPath, '\\')) {
                $subPath = substr($subPath, 0, $lastPos);
                $search = $subPath.'\\';
                if (isset($this->prefixDirsPsr4[$search])) {
                    foreach ($this->prefixDirsPsr4[$search] as $dir) {
                        $length = $this->prefixLengthsPsr4[$first][$search];
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-4 fallback dirs
        foreach ($this->fallbackDirsPsr4 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
                return $file;
            }
        }

        // PSR-0 lookup
        if (false !== $pos = strrpos($class, '\\')) {
            // namespaced class name
            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
        } else {
            // PEAR-like class name
            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
        }

        if (isset($this->prefixesPsr0[$first])) {
            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
                if (0 === strpos($class, $prefix)) {
                    foreach ($dirs as $dir) {
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-0 fallback dirs
        foreach ($this->fallbackDirsPsr0 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                return $file;
            }
        }

        // PSR-0 include paths.
        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
            return $file;
        }

        return false;
    }
}

/**
 * Scope isolated include.
 *
 * Prevents access to $this/self from included files.
 */
function includeFile($file)
{
    include $file;
}


Copyright (c) Nils Adermann, Jordi Boggiano

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


<?php

// autoload_classmap.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'ComposerAutoloaderInit125b023f43356e6992e24cd9f1067aeb' => $vendorDir . '/composer/autoload_real.php',
    'Composer\\Autoload\\ClassLoader' => $vendorDir . '/composer/ClassLoader.php',
    'Composer\\Autoload\\ComposerStaticInit125b023f43356e6992e24cd9f1067aeb' => $vendorDir . '/composer/autoload_static.php',
    'PHPStanVendor\\Jean85\\PrettyVersions' => $vendorDir . '/jean85/pretty-package-versions/src/PrettyVersions.php',
    'PHPStanVendor\\Jean85\\Version' => $vendorDir . '/jean85/pretty-package-versions/src/Version.php',
    'PHPStanVendor\\Nette\\ArgumentOutOfRangeException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\Bridges\\DITracy\\ContainerPanel' => $vendorDir . '/nette/di/src/Bridges/DITracy/ContainerPanel.php',
    'PHPStanVendor\\Nette\\Bridges\\Framework\\TracyBridge' => $vendorDir . '/nette/bootstrap/src/Bridges/Framework/TracyBridge.php',
    'PHPStanVendor\\Nette\\Configurator' => $vendorDir . '/nette/bootstrap/src/Bootstrap/Configurator.php',
    'PHPStanVendor\\Nette\\DI\\Compiler' => $vendorDir . '/nette/di/src/DI/Compiler.php',
    'PHPStanVendor\\Nette\\DI\\CompilerExtension' => $vendorDir . '/nette/di/src/DI/CompilerExtension.php',
    'PHPStanVendor\\Nette\\DI\\Config\\Adapters\\IniAdapter' => $vendorDir . '/nette/di/src/DI/Config/Adapters/IniAdapter.php',
    'PHPStanVendor\\Nette\\DI\\Config\\Adapters\\NeonAdapter' => $vendorDir . '/nette/di/src/DI/Config/Adapters/NeonAdapter.php',
    'PHPStanVendor\\Nette\\DI\\Config\\Adapters\\PhpAdapter' => $vendorDir . '/nette/di/src/DI/Config/Adapters/PhpAdapter.php',
    'PHPStanVendor\\Nette\\DI\\Config\\Helpers' => $vendorDir . '/nette/di/src/DI/Config/Helpers.php',
    'PHPStanVendor\\Nette\\DI\\Config\\IAdapter' => $vendorDir . '/nette/di/src/DI/Config/IAdapter.php',
    'PHPStanVendor\\Nette\\DI\\Config\\Loader' => $vendorDir . '/nette/di/src/DI/Config/Loader.php',
    'PHPStanVendor\\Nette\\DI\\Container' => $vendorDir . '/nette/di/src/DI/Container.php',
    'PHPStanVendor\\Nette\\DI\\ContainerBuilder' => $vendorDir . '/nette/di/src/DI/ContainerBuilder.php',
    'PHPStanVendor\\Nette\\DI\\ContainerLoader' => $vendorDir . '/nette/di/src/DI/ContainerLoader.php',
    'PHPStanVendor\\Nette\\DI\\DependencyChecker' => $vendorDir . '/nette/di/src/DI/DependencyChecker.php',
    'PHPStanVendor\\Nette\\DI\\Extensions\\ConstantsExtension' => $vendorDir . '/nette/di/src/DI/Extensions/ConstantsExtension.php',
    'PHPStanVendor\\Nette\\DI\\Extensions\\DIExtension' => $vendorDir . '/nette/di/src/DI/Extensions/DIExtension.php',
    'PHPStanVendor\\Nette\\DI\\Extensions\\DecoratorExtension' => $vendorDir . '/nette/di/src/DI/Extensions/DecoratorExtension.php',
    'PHPStanVendor\\Nette\\DI\\Extensions\\ExtensionsExtension' => $vendorDir . '/nette/di/src/DI/Extensions/ExtensionsExtension.php',
    'PHPStanVendor\\Nette\\DI\\Extensions\\InjectExtension' => $vendorDir . '/nette/di/src/DI/Extensions/InjectExtension.php',
    'PHPStanVendor\\Nette\\DI\\Extensions\\PhpExtension' => $vendorDir . '/nette/di/src/DI/Extensions/PhpExtension.php',
    'PHPStanVendor\\Nette\\DI\\Helpers' => $vendorDir . '/nette/di/src/DI/Helpers.php',
    'PHPStanVendor\\Nette\\DI\\MissingServiceException' => $vendorDir . '/nette/di/src/DI/exceptions.php',
    'PHPStanVendor\\Nette\\DI\\PhpGenerator' => $vendorDir . '/nette/di/src/DI/PhpGenerator.php',
    'PHPStanVendor\\Nette\\DI\\PhpReflection' => $vendorDir . '/nette/di/src/DI/PhpReflection.php',
    'PHPStanVendor\\Nette\\DI\\ServiceCreationException' => $vendorDir . '/nette/di/src/DI/exceptions.php',
    'PHPStanVendor\\Nette\\DI\\ServiceDefinition' => $vendorDir . '/nette/di/src/DI/ServiceDefinition.php',
    'PHPStanVendor\\Nette\\DI\\Statement' => $vendorDir . '/nette/di/src/DI/Statement.php',
    'PHPStanVendor\\Nette\\DeprecatedException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\DirectoryNotFoundException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\FileNotFoundException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\IOException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\InvalidArgumentException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\InvalidStateException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\Iterators\\CachingIterator' => $vendorDir . '/nette/utils/src/Iterators/CachingIterator.php',
    'PHPStanVendor\\Nette\\Iterators\\Filter' => $vendorDir . '/nette/utils/src/Iterators/Filter.php',
    'PHPStanVendor\\Nette\\Iterators\\Mapper' => $vendorDir . '/nette/utils/src/Iterators/Mapper.php',
    'PHPStanVendor\\Nette\\Iterators\\RecursiveFilter' => $vendorDir . '/nette/utils/src/Iterators/RecursiveFilter.php',
    'PHPStanVendor\\Nette\\Loaders\\RobotLoader' => $vendorDir . '/nette/robot-loader/src/RobotLoader/RobotLoader.php',
    'PHPStanVendor\\Nette\\Localization\\ITranslator' => $vendorDir . '/nette/utils/src/Utils/ITranslator.php',
    'PHPStanVendor\\Nette\\MemberAccessException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\Neon\\Decoder' => $vendorDir . '/nette/neon/src/Neon/Decoder.php',
    'PHPStanVendor\\Nette\\Neon\\Encoder' => $vendorDir . '/nette/neon/src/Neon/Encoder.php',
    'PHPStanVendor\\Nette\\Neon\\Entity' => $vendorDir . '/nette/neon/src/Neon/Entity.php',
    'PHPStanVendor\\Nette\\Neon\\Exception' => $vendorDir . '/nette/neon/src/Neon/Exception.php',
    'PHPStanVendor\\Nette\\Neon\\Neon' => $vendorDir . '/nette/neon/src/Neon/Neon.php',
    'PHPStanVendor\\Nette\\NotImplementedException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\NotSupportedException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\Object' => $vendorDir . '/nette/utils/src/Utils/Object.php',
    'PHPStanVendor\\Nette\\OutOfRangeException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\PhpGenerator\\ClassType' => $vendorDir . '/nette/php-generator/src/PhpGenerator/ClassType.php',
    'PHPStanVendor\\Nette\\PhpGenerator\\Closure' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Closure.php',
    'PHPStanVendor\\Nette\\PhpGenerator\\Constant' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Constant.php',
    'PHPStanVendor\\Nette\\PhpGenerator\\Factory' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Factory.php',
    'PHPStanVendor\\Nette\\PhpGenerator\\GlobalFunction' => $vendorDir . '/nette/php-generator/src/PhpGenerator/GlobalFunction.php',
    'PHPStanVendor\\Nette\\PhpGenerator\\Helpers' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Helpers.php',
    'PHPStanVendor\\Nette\\PhpGenerator\\Method' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Method.php',
    'PHPStanVendor\\Nette\\PhpGenerator\\Parameter' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Parameter.php',
    'PHPStanVendor\\Nette\\PhpGenerator\\PhpFile' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PhpFile.php',
    'PHPStanVendor\\Nette\\PhpGenerator\\PhpLiteral' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PhpLiteral.php',
    'PHPStanVendor\\Nette\\PhpGenerator\\PhpNamespace' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PhpNamespace.php',
    'PHPStanVendor\\Nette\\PhpGenerator\\Property' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Property.php',
    'PHPStanVendor\\Nette\\PhpGenerator\\Traits\\CommentAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/CommentAware.php',
    'PHPStanVendor\\Nette\\PhpGenerator\\Traits\\FunctionLike' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/FunctionLike.php',
    'PHPStanVendor\\Nette\\PhpGenerator\\Traits\\NameAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/NameAware.php',
    'PHPStanVendor\\Nette\\PhpGenerator\\Traits\\VisibilityAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/VisibilityAware.php',
    'PHPStanVendor\\Nette\\SmartObject' => $vendorDir . '/nette/utils/src/Utils/SmartObject.php',
    'PHPStanVendor\\Nette\\StaticClass' => $vendorDir . '/nette/utils/src/Utils/StaticClass.php',
    'PHPStanVendor\\Nette\\StaticClassException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\UnexpectedValueException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\Utils\\ArrayHash' => $vendorDir . '/nette/utils/src/Utils/ArrayHash.php',
    'PHPStanVendor\\Nette\\Utils\\ArrayList' => $vendorDir . '/nette/utils/src/Utils/ArrayList.php',
    'PHPStanVendor\\Nette\\Utils\\Arrays' => $vendorDir . '/nette/utils/src/Utils/Arrays.php',
    'PHPStanVendor\\Nette\\Utils\\AssertionException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\Utils\\Callback' => $vendorDir . '/nette/utils/src/Utils/Callback.php',
    'PHPStanVendor\\Nette\\Utils\\DateTime' => $vendorDir . '/nette/utils/src/Utils/DateTime.php',
    'PHPStanVendor\\Nette\\Utils\\FileSystem' => $vendorDir . '/nette/utils/src/Utils/FileSystem.php',
    'PHPStanVendor\\Nette\\Utils\\Finder' => $vendorDir . '/nette/finder/src/Utils/Finder.php',
    'PHPStanVendor\\Nette\\Utils\\Html' => $vendorDir . '/nette/utils/src/Utils/Html.php',
    'PHPStanVendor\\Nette\\Utils\\IHtmlString' => $vendorDir . '/nette/utils/src/Utils/IHtmlString.php',
    'PHPStanVendor\\Nette\\Utils\\Image' => $vendorDir . '/nette/utils/src/Utils/Image.php',
    'PHPStanVendor\\Nette\\Utils\\ImageException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\Utils\\Json' => $vendorDir . '/nette/utils/src/Utils/Json.php',
    'PHPStanVendor\\Nette\\Utils\\JsonException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\Utils\\ObjectMixin' => $vendorDir . '/nette/utils/src/Utils/ObjectMixin.php',
    'PHPStanVendor\\Nette\\Utils\\Paginator' => $vendorDir . '/nette/utils/src/Utils/Paginator.php',
    'PHPStanVendor\\Nette\\Utils\\Random' => $vendorDir . '/nette/utils/src/Utils/Random.php',
    'PHPStanVendor\\Nette\\Utils\\Reflection' => $vendorDir . '/nette/utils/src/Utils/Reflection.php',
    'PHPStanVendor\\Nette\\Utils\\RegexpException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\Utils\\Strings' => $vendorDir . '/nette/utils/src/Utils/Strings.php',
    'PHPStanVendor\\Nette\\Utils\\UnknownImageFileException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
    'PHPStanVendor\\Nette\\Utils\\Validators' => $vendorDir . '/nette/utils/src/Utils/Validators.php',
    'PHPStanVendor\\PackageVersions\\FallbackVersions' => $vendorDir . '/ocramius/package-versions/src/PackageVersions/FallbackVersions.php',
    'PHPStanVendor\\PackageVersions\\Installer' => $vendorDir . '/ocramius/package-versions/src/PackageVersions/Installer.php',
    'PHPStanVendor\\PackageVersions\\Versions' => $vendorDir . '/ocramius/package-versions/src/PackageVersions/Versions.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Application' => $vendorDir . '/symfony/console/Application.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => $vendorDir . '/symfony/console/CommandLoader/CommandLoaderInterface.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/ContainerCommandLoader.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/FactoryCommandLoader.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Command\\Command' => $vendorDir . '/symfony/console/Command/Command.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Command\\HelpCommand' => $vendorDir . '/symfony/console/Command/HelpCommand.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Command\\ListCommand' => $vendorDir . '/symfony/console/Command/ListCommand.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Command\\LockableTrait' => $vendorDir . '/symfony/console/Command/LockableTrait.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\ConsoleEvents' => $vendorDir . '/symfony/console/ConsoleEvents.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => $vendorDir . '/symfony/console/DependencyInjection/AddConsoleCommandPass.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => $vendorDir . '/symfony/console/Descriptor/ApplicationDescription.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Descriptor\\Descriptor' => $vendorDir . '/symfony/console/Descriptor/Descriptor.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => $vendorDir . '/symfony/console/Descriptor/DescriptorInterface.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => $vendorDir . '/symfony/console/Descriptor/JsonDescriptor.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => $vendorDir . '/symfony/console/Descriptor/MarkdownDescriptor.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => $vendorDir . '/symfony/console/Descriptor/TextDescriptor.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => $vendorDir . '/symfony/console/Descriptor/XmlDescriptor.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\EventListener\\ErrorListener' => $vendorDir . '/symfony/console/EventListener/ErrorListener.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => $vendorDir . '/symfony/console/Event/ConsoleCommandEvent.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => $vendorDir . '/symfony/console/Event/ConsoleErrorEvent.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Event\\ConsoleEvent' => $vendorDir . '/symfony/console/Event/ConsoleEvent.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Event\\ConsoleExceptionEvent' => $vendorDir . '/symfony/console/Event/ConsoleExceptionEvent.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => $vendorDir . '/symfony/console/Event/ConsoleTerminateEvent.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => $vendorDir . '/symfony/console/Exception/CommandNotFoundException.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/console/Exception/ExceptionInterface.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/console/Exception/InvalidArgumentException.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Exception\\InvalidOptionException' => $vendorDir . '/symfony/console/Exception/InvalidOptionException.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Exception\\LogicException' => $vendorDir . '/symfony/console/Exception/LogicException.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Exception\\RuntimeException' => $vendorDir . '/symfony/console/Exception/RuntimeException.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatter' => $vendorDir . '/symfony/console/Formatter/OutputFormatter.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => $vendorDir . '/symfony/console/Formatter/OutputFormatterInterface.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyle.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyleInterface.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyleStack.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => $vendorDir . '/symfony/console/Helper/DebugFormatterHelper.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\DescriptorHelper' => $vendorDir . '/symfony/console/Helper/DescriptorHelper.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\FormatterHelper' => $vendorDir . '/symfony/console/Helper/FormatterHelper.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\Helper' => $vendorDir . '/symfony/console/Helper/Helper.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\HelperInterface' => $vendorDir . '/symfony/console/Helper/HelperInterface.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\HelperSet' => $vendorDir . '/symfony/console/Helper/HelperSet.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\InputAwareHelper' => $vendorDir . '/symfony/console/Helper/InputAwareHelper.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\ProcessHelper' => $vendorDir . '/symfony/console/Helper/ProcessHelper.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\ProgressBar' => $vendorDir . '/symfony/console/Helper/ProgressBar.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\ProgressIndicator' => $vendorDir . '/symfony/console/Helper/ProgressIndicator.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\QuestionHelper' => $vendorDir . '/symfony/console/Helper/QuestionHelper.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => $vendorDir . '/symfony/console/Helper/SymfonyQuestionHelper.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\Table' => $vendorDir . '/symfony/console/Helper/Table.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\TableCell' => $vendorDir . '/symfony/console/Helper/TableCell.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\TableSeparator' => $vendorDir . '/symfony/console/Helper/TableSeparator.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\TableStyle' => $vendorDir . '/symfony/console/Helper/TableStyle.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Input\\ArgvInput' => $vendorDir . '/symfony/console/Input/ArgvInput.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Input\\ArrayInput' => $vendorDir . '/symfony/console/Input/ArrayInput.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Input\\Input' => $vendorDir . '/symfony/console/Input/Input.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Input\\InputArgument' => $vendorDir . '/symfony/console/Input/InputArgument.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Input\\InputAwareInterface' => $vendorDir . '/symfony/console/Input/InputAwareInterface.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Input\\InputDefinition' => $vendorDir . '/symfony/console/Input/InputDefinition.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Input\\InputInterface' => $vendorDir . '/symfony/console/Input/InputInterface.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Input\\InputOption' => $vendorDir . '/symfony/console/Input/InputOption.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Input\\StreamableInputInterface' => $vendorDir . '/symfony/console/Input/StreamableInputInterface.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Input\\StringInput' => $vendorDir . '/symfony/console/Input/StringInput.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Logger\\ConsoleLogger' => $vendorDir . '/symfony/console/Logger/ConsoleLogger.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Output\\BufferedOutput' => $vendorDir . '/symfony/console/Output/BufferedOutput.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Output\\ConsoleOutput' => $vendorDir . '/symfony/console/Output/ConsoleOutput.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => $vendorDir . '/symfony/console/Output/ConsoleOutputInterface.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Output\\NullOutput' => $vendorDir . '/symfony/console/Output/NullOutput.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Output\\Output' => $vendorDir . '/symfony/console/Output/Output.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Output\\OutputInterface' => $vendorDir . '/symfony/console/Output/OutputInterface.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Output\\StreamOutput' => $vendorDir . '/symfony/console/Output/StreamOutput.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Question\\ChoiceQuestion' => $vendorDir . '/symfony/console/Question/ChoiceQuestion.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => $vendorDir . '/symfony/console/Question/ConfirmationQuestion.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Question\\Question' => $vendorDir . '/symfony/console/Question/Question.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Style\\OutputStyle' => $vendorDir . '/symfony/console/Style/OutputStyle.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Style\\StyleInterface' => $vendorDir . '/symfony/console/Style/StyleInterface.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Style\\SymfonyStyle' => $vendorDir . '/symfony/console/Style/SymfonyStyle.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Terminal' => $vendorDir . '/symfony/console/Terminal.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Tester\\ApplicationTester' => $vendorDir . '/symfony/console/Tester/ApplicationTester.php',
    'PHPStanVendor\\Symfony\\Component\\Console\\Tester\\CommandTester' => $vendorDir . '/symfony/console/Tester/CommandTester.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Comparator\\Comparator' => $vendorDir . '/symfony/finder/Comparator/Comparator.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Comparator\\DateComparator' => $vendorDir . '/symfony/finder/Comparator/DateComparator.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Comparator\\NumberComparator' => $vendorDir . '/symfony/finder/Comparator/NumberComparator.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Exception\\AccessDeniedException' => $vendorDir . '/symfony/finder/Exception/AccessDeniedException.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/finder/Exception/ExceptionInterface.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Finder' => $vendorDir . '/symfony/finder/Finder.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Glob' => $vendorDir . '/symfony/finder/Glob.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\CustomFilterIterator' => $vendorDir . '/symfony/finder/Iterator/CustomFilterIterator.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\DateRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/DateRangeFilterIterator.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\DepthRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/DepthRangeFilterIterator.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\ExcludeDirectoryFilterIterator' => $vendorDir . '/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FileTypeFilterIterator.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilecontentFilterIterator.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilenameFilterIterator.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\FilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilterIterator.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => $vendorDir . '/symfony/finder/Iterator/MultiplePcreFilterIterator.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => $vendorDir . '/symfony/finder/Iterator/PathFilterIterator.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => $vendorDir . '/symfony/finder/Iterator/RecursiveDirectoryIterator.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/SizeRangeFilterIterator.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\SortableIterator' => $vendorDir . '/symfony/finder/Iterator/SortableIterator.php',
    'PHPStanVendor\\Symfony\\Component\\Finder\\SplFileInfo' => $vendorDir . '/symfony/finder/SplFileInfo.php',
    'PHPStanVendor\\Symfony\\Polyfill\\Mbstring\\Mbstring' => $vendorDir . '/symfony/polyfill-mbstring/Mbstring.php',
    'PHPStan\\AnalysedCodeException' => $baseDir . '/src/AnalysedCodeException.php',
    'PHPStan\\Analyser\\Analyser' => $baseDir . '/src/Analyser/Analyser.php',
    'PHPStan\\Analyser\\Error' => $baseDir . '/src/Analyser/Error.php',
    'PHPStan\\Analyser\\LookForAssignsSettings' => $baseDir . '/src/Analyser/LookForAssignsSettings.php',
    'PHPStan\\Analyser\\NameScope' => $baseDir . '/src/Analyser/NameScope.php',
    'PHPStan\\Analyser\\NodeScopeResolver' => $baseDir . '/src/Analyser/NodeScopeResolver.php',
    'PHPStan\\Analyser\\Scope' => $baseDir . '/src/Analyser/Scope.php',
    'PHPStan\\Analyser\\SpecifiedTypes' => $baseDir . '/src/Analyser/SpecifiedTypes.php',
    'PHPStan\\Analyser\\StatementList' => $baseDir . '/src/Analyser/StatementList.php',
    'PHPStan\\Analyser\\TypeSpecifier' => $baseDir . '/src/Analyser/TypeSpecifier.php',
    'PHPStan\\Analyser\\UndefinedVariableException' => $baseDir . '/src/Analyser/UndefinedVariableException.php',
    'PHPStan\\Analyser\\VariableTypeHolder' => $baseDir . '/src/Analyser/VariableTypeHolder.php',
    'PHPStan\\Broker\\Broker' => $baseDir . '/src/Broker/Broker.php',
    'PHPStan\\Broker\\BrokerFactory' => $baseDir . '/src/Broker/BrokerFactory.php',
    'PHPStan\\Broker\\ClassAutoloadingException' => $baseDir . '/src/Broker/ClassAutoloadingException.php',
    'PHPStan\\Broker\\ClassNotFoundException' => $baseDir . '/src/Broker/ClassNotFoundException.php',
    'PHPStan\\Broker\\FunctionNotFoundException' => $baseDir . '/src/Broker/FunctionNotFoundException.php',
    'PHPStan\\Cache\\Cache' => $baseDir . '/src/Cache/Cache.php',
    'PHPStan\\Cache\\CacheStorage' => $baseDir . '/src/Cache/CacheStorage.php',
    'PHPStan\\Cache\\FileCacheStorage' => $baseDir . '/src/Cache/FileCacheStorage.php',
    'PHPStan\\Cache\\MemoryCacheStorage' => $baseDir . '/src/Cache/MemoryCacheStorage.php',
    'PHPStan\\Command\\AnalyseApplication' => $baseDir . '/src/Command/AnalyseApplication.php',
    'PHPStan\\Command\\AnalyseCommand' => $baseDir . '/src/Command/AnalyseCommand.php',
    'PHPStan\\Command\\AnalysisResult' => $baseDir . '/src/Command/AnalysisResult.php',
    'PHPStan\\Command\\ErrorFormatter\\CheckstyleErrorFormatter' => $baseDir . '/src/Command/ErrorFormatter/CheckstyleErrorFormatter.php',
    'PHPStan\\Command\\ErrorFormatter\\ErrorFormatter' => $baseDir . '/src/Command/ErrorFormatter/ErrorFormatter.php',
    'PHPStan\\Command\\ErrorFormatter\\RawErrorFormatter' => $baseDir . '/src/Command/ErrorFormatter/RawErrorFormatter.php',
    'PHPStan\\Command\\ErrorFormatter\\TableErrorFormatter' => $baseDir . '/src/Command/ErrorFormatter/TableErrorFormatter.php',
    'PHPStan\\Command\\ErrorsConsoleStyle' => $baseDir . '/src/Command/ErrorsConsoleStyle.php',
    'PHPStan\\DependencyInjection\\ContainerFactory' => $baseDir . '/src/DependencyInjection/ContainerFactory.php',
    'PHPStan\\File\\FileExcluder' => $baseDir . '/src/File/FileExcluder.php',
    'PHPStan\\File\\FileHelper' => $baseDir . '/src/File/FileHelper.php',
    'PHPStan\\Parser\\CachedParser' => $baseDir . '/src/Parser/CachedParser.php',
    'PHPStan\\Parser\\DirectParser' => $baseDir . '/src/Parser/DirectParser.php',
    'PHPStan\\Parser\\FunctionCallStatementFinder' => $baseDir . '/src/Parser/FunctionCallStatementFinder.php',
    'PHPStan\\Parser\\Parser' => $baseDir . '/src/Parser/Parser.php',
    'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayItemNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php',
    'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php',
    'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFalseNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php',
    'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFloatNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php',
    'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprIntegerNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php',
    'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php',
    'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNullNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php',
    'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprStringNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php',
    'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprTrueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php',
    'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstFetchNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php',
    'PHPStan\\PhpDocParser\\Ast\\Node' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Node.php',
    'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\GenericTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php',
    'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\InvalidTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php',
    'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php',
    'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueParameterNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php',
    'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php',
    'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocChildNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php',
    'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php',
    'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php',
    'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php',
    'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTextNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php',
    'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PropertyTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php',
    'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ReturnTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php',
    'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ThrowsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php',
    'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\VarTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php',
    'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php',
    'PHPStan\\PhpDocParser\\Ast\\Type\\GenericTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php',
    'PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php',
    'PHPStan\\PhpDocParser\\Ast\\Type\\IntersectionTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php',
    'PHPStan\\PhpDocParser\\Ast\\Type\\NullableTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php',
    'PHPStan\\PhpDocParser\\Ast\\Type\\ThisTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php',
    'PHPStan\\PhpDocParser\\Ast\\Type\\TypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php',
    'PHPStan\\PhpDocParser\\Ast\\Type\\UnionTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php',
    'PHPStan\\PhpDocParser\\Lexer\\Lexer' => $vendorDir . '/phpstan/phpdoc-parser/src/Lexer/Lexer.php',
    'PHPStan\\PhpDocParser\\Parser\\ConstExprParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php',
    'PHPStan\\PhpDocParser\\Parser\\ParserException' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/ParserException.php',
    'PHPStan\\PhpDocParser\\Parser\\PhpDocParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php',
    'PHPStan\\PhpDocParser\\Parser\\TokenIterator' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/TokenIterator.php',
    'PHPStan\\PhpDocParser\\Parser\\TypeParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/TypeParser.php',
    'PHPStan\\PhpDoc\\PhpDocBlock' => $baseDir . '/src/PhpDoc/PhpDocBlock.php',
    'PHPStan\\PhpDoc\\PhpDocNodeResolver' => $baseDir . '/src/PhpDoc/PhpDocNodeResolver.php',
    'PHPStan\\PhpDoc\\PhpDocStringResolver' => $baseDir . '/src/PhpDoc/PhpDocStringResolver.php',
    'PHPStan\\PhpDoc\\ResolvedPhpDocBlock' => $baseDir . '/src/PhpDoc/ResolvedPhpDocBlock.php',
    'PHPStan\\PhpDoc\\Tag\\MethodTag' => $baseDir . '/src/PhpDoc/Tag/MethodTag.php',
    'PHPStan\\PhpDoc\\Tag\\MethodTagParameter' => $baseDir . '/src/PhpDoc/Tag/MethodTagParameter.php',
    'PHPStan\\PhpDoc\\Tag\\ParamTag' => $baseDir . '/src/PhpDoc/Tag/ParamTag.php',
    'PHPStan\\PhpDoc\\Tag\\PropertyTag' => $baseDir . '/src/PhpDoc/Tag/PropertyTag.php',
    'PHPStan\\PhpDoc\\Tag\\ReturnTag' => $baseDir . '/src/PhpDoc/Tag/ReturnTag.php',
    'PHPStan\\PhpDoc\\Tag\\VarTag' => $baseDir . '/src/PhpDoc/Tag/VarTag.php',
    'PHPStan\\PhpDoc\\TypeNodeResolver' => $baseDir . '/src/PhpDoc/TypeNodeResolver.php',
    'PHPStan\\PhpDoc\\TypeStringResolver' => $baseDir . '/src/PhpDoc/TypeStringResolver.php',
    'PHPStan\\Reflection\\Annotations\\AnnotationMethodReflection' => $baseDir . '/src/Reflection/Annotations/AnnotationMethodReflection.php',
    'PHPStan\\Reflection\\Annotations\\AnnotationPropertyReflection' => $baseDir . '/src/Reflection/Annotations/AnnotationPropertyReflection.php',
    'PHPStan\\Reflection\\Annotations\\AnnotationsMethodParameterReflection' => $baseDir . '/src/Reflection/Annotations/AnnotationsMethodParameterReflection.php',
    'PHPStan\\Reflection\\Annotations\\AnnotationsMethodsClassReflectionExtension' => $baseDir . '/src/Reflection/Annotations/AnnotationsMethodsClassReflectionExtension.php',
    'PHPStan\\Reflection\\Annotations\\AnnotationsPropertiesClassReflectionExtension' => $baseDir . '/src/Reflection/Annotations/AnnotationsPropertiesClassReflectionExtension.php',
    'PHPStan\\Reflection\\BrokerAwareClassReflectionExtension' => $baseDir . '/src/Reflection/BrokerAwareClassReflectionExtension.php',
    'PHPStan\\Reflection\\BrokerAwareExtension' => $baseDir . '/src/Reflection/BrokerAwareExtension.php',
    'PHPStan\\Reflection\\ClassConstantReflection' => $baseDir . '/src/Reflection/ClassConstantReflection.php',
    'PHPStan\\Reflection\\ClassConstantWithVisibilityReflection' => $baseDir . '/src/Reflection/ClassConstantWithVisibilityReflection.php',
    'PHPStan\\Reflection\\ClassMemberReflection' => $baseDir . '/src/Reflection/ClassMemberReflection.php',
    'PHPStan\\Reflection\\ClassReflection' => $baseDir . '/src/Reflection/ClassReflection.php',
    'PHPStan\\Reflection\\FunctionReflection' => $baseDir . '/src/Reflection/FunctionReflection.php',
    'PHPStan\\Reflection\\FunctionReflectionFactory' => $baseDir . '/src/Reflection/FunctionReflectionFactory.php',
    'PHPStan\\Reflection\\MethodReflection' => $baseDir . '/src/Reflection/MethodReflection.php',
    'PHPStan\\Reflection\\MethodsClassReflectionExtension' => $baseDir . '/src/Reflection/MethodsClassReflectionExtension.php',
    'PHPStan\\Reflection\\MissingMethodFromReflectionException' => $baseDir . '/src/Reflection/MissingMethodFromReflectionException.php',
    'PHPStan\\Reflection\\MissingPropertyFromReflectionException' => $baseDir . '/src/Reflection/MissingPropertyFromReflectionException.php',
    'PHPStan\\Reflection\\ObsoleteClassConstantReflection' => $baseDir . '/src/Reflection/ObsoleteClassConstantReflection.php',
    'PHPStan\\Reflection\\ParameterReflection' => $baseDir . '/src/Reflection/ParameterReflection.php',
    'PHPStan\\Reflection\\ParametersAcceptor' => $baseDir . '/src/Reflection/ParametersAcceptor.php',
    'PHPStan\\Reflection\\ParametersAcceptorWithPhpDocs' => $baseDir . '/src/Reflection/ParametersAcceptorWithPhpDocs.php',
    'PHPStan\\Reflection\\PhpDefect\\PhpDefectClassReflectionExtension' => $baseDir . '/src/Reflection/PhpDefect/PhpDefectClassReflectionExtension.php',
    'PHPStan\\Reflection\\PhpDefect\\PhpDefectPropertyReflection' => $baseDir . '/src/Reflection/PhpDefect/PhpDefectPropertyReflection.php',
    'PHPStan\\Reflection\\Php\\DummyParameter' => $baseDir . '/src/Reflection/Php/DummyParameter.php',
    'PHPStan\\Reflection\\Php\\PhpClassReflectionExtension' => $baseDir . '/src/Reflection/Php/PhpClassReflectionExtension.php',
    'PHPStan\\Reflection\\Php\\PhpFunctionFromParserNodeReflection' => $baseDir . '/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php',
    'PHPStan\\Reflection\\Php\\PhpMethodFromParserNodeReflection' => $baseDir . '/src/Reflection/Php/PhpMethodFromParserNodeReflection.php',
    'PHPStan\\Reflection\\Php\\PhpMethodReflection' => $baseDir . '/src/Reflection/Php/PhpMethodReflection.php',
    'PHPStan\\Reflection\\Php\\PhpMethodReflectionFactory' => $baseDir . '/src/Reflection/Php/PhpMethodReflectionFactory.php',
    'PHPStan\\Reflection\\Php\\PhpParameterFromParserNodeReflection' => $baseDir . '/src/Reflection/Php/PhpParameterFromParserNodeReflection.php',
    'PHPStan\\Reflection\\Php\\PhpParameterReflection' => $baseDir . '/src/Reflection/Php/PhpParameterReflection.php',
    'PHPStan\\Reflection\\Php\\PhpPropertyReflection' => $baseDir . '/src/Reflection/Php/PhpPropertyReflection.php',
    'PHPStan\\Reflection\\Php\\UniversalObjectCrateProperty' => $baseDir . '/src/Reflection/Php/UniversalObjectCrateProperty.php',
    'PHPStan\\Reflection\\Php\\UniversalObjectCratesClassReflectionExtension' => $baseDir . '/src/Reflection/Php/UniversalObjectCratesClassReflectionExtension.php',
    'PHPStan\\Reflection\\PropertiesClassReflectionExtension' => $baseDir . '/src/Reflection/PropertiesClassReflectionExtension.php',
    'PHPStan\\Reflection\\PropertyReflection' => $baseDir . '/src/Reflection/PropertyReflection.php',
    'PHPStan\\Rules\\Arrays\\AllowedArrayKeysTypes' => $baseDir . '/src/Rules/Arrays/AllowedArrayKeysTypes.php',
    'PHPStan\\Rules\\Arrays\\AppendedArrayItemTypeRule' => $baseDir . '/src/Rules/Arrays/AppendedArrayItemTypeRule.php',
    'PHPStan\\Rules\\Arrays\\DuplicateKeysInLiteralArraysRule' => $baseDir . '/src/Rules/Arrays/DuplicateKeysInLiteralArraysRule.php',
    'PHPStan\\Rules\\Arrays\\InvalidKeyInArrayDimFetchRule' => $baseDir . '/src/Rules/Arrays/InvalidKeyInArrayDimFetchRule.php',
    'PHPStan\\Rules\\Arrays\\InvalidKeyInArrayItemRule' => $baseDir . '/src/Rules/Arrays/InvalidKeyInArrayItemRule.php',
    'PHPStan\\Rules\\Arrays\\IterableInForeachRule' => $baseDir . '/src/Rules/Arrays/IterableInForeachRule.php',
    'PHPStan\\Rules\\Cast\\UselessCastRule' => $baseDir . '/src/Rules/Cast/UselessCastRule.php',
    'PHPStan\\Rules\\ClassCaseSensitivityCheck' => $baseDir . '/src/Rules/ClassCaseSensitivityCheck.php',
    'PHPStan\\Rules\\Classes\\ClassConstantRule' => $baseDir . '/src/Rules/Classes/ClassConstantRule.php',
    'PHPStan\\Rules\\Classes\\ExistingClassInClassExtendsRule' => $baseDir . '/src/Rules/Classes/ExistingClassInClassExtendsRule.php',
    'PHPStan\\Rules\\Classes\\ExistingClassInInstanceOfRule' => $baseDir . '/src/Rules/Classes/ExistingClassInInstanceOfRule.php',
    'PHPStan\\Rules\\Classes\\ExistingClassInTraitUseRule' => $baseDir . '/src/Rules/Classes/ExistingClassInTraitUseRule.php',
    'PHPStan\\Rules\\Classes\\ExistingClassesInClassImplementsRule' => $baseDir . '/src/Rules/Classes/ExistingClassesInClassImplementsRule.php',
    'PHPStan\\Rules\\Classes\\ExistingClassesInInterfaceExtendsRule' => $baseDir . '/src/Rules/Classes/ExistingClassesInInterfaceExtendsRule.php',
    'PHPStan\\Rules\\Classes\\ImpossibleInstanceOfRule' => $baseDir . '/src/Rules/Classes/ImpossibleInstanceOfRule.php',
    'PHPStan\\Rules\\Classes\\InstantiationRule' => $baseDir . '/src/Rules/Classes/InstantiationRule.php',
    'PHPStan\\Rules\\Classes\\RequireParentConstructCallRule' => $baseDir . '/src/Rules/Classes/RequireParentConstructCallRule.php',
    'PHPStan\\Rules\\Classes\\UnusedConstructorParametersRule' => $baseDir . '/src/Rules/Classes/UnusedConstructorParametersRule.php',
    'PHPStan\\Rules\\Comparison\\ImpossibleCheckTypeFunctionCallRule' => $baseDir . '/src/Rules/Comparison/ImpossibleCheckTypeFunctionCallRule.php',
    'PHPStan\\Rules\\Comparison\\StrictComparisonOfDifferentTypesRule' => $baseDir . '/src/Rules/Comparison/StrictComparisonOfDifferentTypesRule.php',
    'PHPStan\\Rules\\Constants\\ConstantRule' => $baseDir . '/src/Rules/Constants/ConstantRule.php',
    'PHPStan\\Rules\\Exceptions\\CaughtExceptionExistenceRule' => $baseDir . '/src/Rules/Exceptions/CaughtExceptionExistenceRule.php',
    'PHPStan\\Rules\\FoundTypeResult' => $baseDir . '/src/Rules/FoundTypeResult.php',
    'PHPStan\\Rules\\FunctionCallParametersCheck' => $baseDir . '/src/Rules/FunctionCallParametersCheck.php',
    'PHPStan\\Rules\\FunctionDefinitionCheck' => $baseDir . '/src/Rules/FunctionDefinitionCheck.php',
    'PHPStan\\Rules\\FunctionReturnTypeCheck' => $baseDir . '/src/Rules/FunctionReturnTypeCheck.php',
    'PHPStan\\Rules\\Functions\\CallToCountOnlyWithArrayOrCountableRule' => $baseDir . '/src/Rules/Functions/CallToCountOnlyWithArrayOrCountableRule.php',
    'PHPStan\\Rules\\Functions\\CallToFunctionParametersRule' => $baseDir . '/src/Rules/Functions/CallToFunctionParametersRule.php',
    'PHPStan\\Rules\\Functions\\CallToNonExistentFunctionRule' => $baseDir . '/src/Rules/Functions/CallToNonExistentFunctionRule.php',
    'PHPStan\\Rules\\Functions\\ClosureReturnTypeRule' => $baseDir . '/src/Rules/Functions/ClosureReturnTypeRule.php',
    'PHPStan\\Rules\\Functions\\ExistingClassesInClosureTypehintsRule' => $baseDir . '/src/Rules/Functions/ExistingClassesInClosureTypehintsRule.php',
    'PHPStan\\Rules\\Functions\\ExistingClassesInTypehintsRule' => $baseDir . '/src/Rules/Functions/ExistingClassesInTypehintsRule.php',
    'PHPStan\\Rules\\Functions\\InnerFunctionRule' => $baseDir . '/src/Rules/Functions/InnerFunctionRule.php',
    'PHPStan\\Rules\\Functions\\NonExistentDefinedFunctionRule' => $baseDir . '/src/Rules/Functions/NonExistentDefinedFunctionRule.php',
    'PHPStan\\Rules\\Functions\\PrintfParametersRule' => $baseDir . '/src/Rules/Functions/PrintfParametersRule.php',
    'PHPStan\\Rules\\Functions\\ReturnTypeRule' => $baseDir . '/src/Rules/Functions/ReturnTypeRule.php',
    'PHPStan\\Rules\\Functions\\UnusedClosureUsesRule' => $baseDir . '/src/Rules/Functions/UnusedClosureUsesRule.php',
    'PHPStan\\Rules\\Methods\\CallMethodsOnPossiblyNullRule' => $baseDir . '/src/Rules/Methods/CallMethodsOnPossiblyNullRule.php',
    'PHPStan\\Rules\\Methods\\CallMethodsRule' => $baseDir . '/src/Rules/Methods/CallMethodsRule.php',
    'PHPStan\\Rules\\Methods\\CallStaticMethodsRule' => $baseDir . '/src/Rules/Methods/CallStaticMethodsRule.php',
    'PHPStan\\Rules\\Methods\\ExistingClassesInTypehintsRule' => $baseDir . '/src/Rules/Methods/ExistingClassesInTypehintsRule.php',
    'PHPStan\\Rules\\Methods\\ReturnTypeRule' => $baseDir . '/src/Rules/Methods/ReturnTypeRule.php',
    'PHPStan\\Rules\\Namespaces\\ExistingNamesInGroupUseRule' => $baseDir . '/src/Rules/Namespaces/ExistingNamesInGroupUseRule.php',
    'PHPStan\\Rules\\Namespaces\\ExistingNamesInUseRule' => $baseDir . '/src/Rules/Namespaces/ExistingNamesInUseRule.php',
    'PHPStan\\Rules\\PhpDoc\\IncompatiblePhpDocTypeRule' => $baseDir . '/src/Rules/PhpDoc/IncompatiblePhpDocTypeRule.php',
    'PHPStan\\Rules\\PhpDoc\\InvalidPhpDocTagValueRule' => $baseDir . '/src/Rules/PhpDoc/InvalidPhpDocTagValueRule.php',
    'PHPStan\\Rules\\Properties\\AccessPropertiesOnPossiblyNullRule' => $baseDir . '/src/Rules/Properties/AccessPropertiesOnPossiblyNullRule.php',
    'PHPStan\\Rules\\Properties\\AccessPropertiesRule' => $baseDir . '/src/Rules/Properties/AccessPropertiesRule.php',
    'PHPStan\\Rules\\Properties\\AccessStaticPropertiesRule' => $baseDir . '/src/Rules/Properties/AccessStaticPropertiesRule.php',
    'PHPStan\\Rules\\Properties\\DefaultValueTypesAssignedToPropertiesRule' => $baseDir . '/src/Rules/Properties/DefaultValueTypesAssignedToPropertiesRule.php',
    'PHPStan\\Rules\\Properties\\ExistingClassesInPropertiesRule' => $baseDir . '/src/Rules/Properties/ExistingClassesInPropertiesRule.php',
    'PHPStan\\Rules\\Properties\\PropertyDescriptor' => $baseDir . '/src/Rules/Properties/PropertyDescriptor.php',
    'PHPStan\\Rules\\Properties\\PropertyReflectionFinder' => $baseDir . '/src/Rules/Properties/PropertyReflectionFinder.php',
    'PHPStan\\Rules\\Properties\\ReadingWriteOnlyPropertiesRule' => $baseDir . '/src/Rules/Properties/ReadingWriteOnlyPropertiesRule.php',
    'PHPStan\\Rules\\Properties\\TypesAssignedToPropertiesRule' => $baseDir . '/src/Rules/Properties/TypesAssignedToPropertiesRule.php',
    'PHPStan\\Rules\\Properties\\WritingToReadOnlyPropertiesRule' => $baseDir . '/src/Rules/Properties/WritingToReadOnlyPropertiesRule.php',
    'PHPStan\\Rules\\Registry' => $baseDir . '/src/Rules/Registry.php',
    'PHPStan\\Rules\\RegistryFactory' => $baseDir . '/src/Rules/RegistryFactory.php',
    'PHPStan\\Rules\\Rule' => $baseDir . '/src/Rules/Rule.php',
    'PHPStan\\Rules\\RuleLevelHelper' => $baseDir . '/src/Rules/RuleLevelHelper.php',
    'PHPStan\\Rules\\UnusedFunctionParametersCheck' => $baseDir . '/src/Rules/UnusedFunctionParametersCheck.php',
    'PHPStan\\Rules\\Variables\\DefinedVariableInAnonymousFunctionUseRule' => $baseDir . '/src/Rules/Variables/DefinedVariableInAnonymousFunctionUseRule.php',
    'PHPStan\\Rules\\Variables\\DefinedVariableRule' => $baseDir . '/src/Rules/Variables/DefinedVariableRule.php',
    'PHPStan\\Rules\\Variables\\ThisVariableRule' => $baseDir . '/src/Rules/Variables/ThisVariableRule.php',
    'PHPStan\\Rules\\Variables\\VariableCertaintyInIssetRule' => $baseDir . '/src/Rules/Variables/VariableCertaintyInIssetRule.php',
    'PHPStan\\Rules\\Variables\\VariableCloningRule' => $baseDir . '/src/Rules/Variables/VariableCloningRule.php',
    'PHPStan\\ShouldNotHappenException' => $baseDir . '/src/ShouldNotHappenException.php',
    'PHPStan\\Testing\\RuleTestCase' => $baseDir . '/src/Testing/RuleTestCase.php',
    'PHPStan\\Testing\\TestCase' => $baseDir . '/src/Testing/TestCase.php',
    'PHPStan\\TrinaryLogic' => $baseDir . '/src/TrinaryLogic.php',
    'PHPStan\\Type\\ArrayType' => $baseDir . '/src/Type/ArrayType.php',
    'PHPStan\\Type\\BooleanType' => $baseDir . '/src/Type/BooleanType.php',
    'PHPStan\\Type\\CallableType' => $baseDir . '/src/Type/CallableType.php',
    'PHPStan\\Type\\CommentHelper' => $baseDir . '/src/Type/CommentHelper.php',
    'PHPStan\\Type\\CompoundType' => $baseDir . '/src/Type/CompoundType.php',
    'PHPStan\\Type\\CompoundTypeHelper' => $baseDir . '/src/Type/CompoundTypeHelper.php',
    'PHPStan\\Type\\DynamicFunctionReturnTypeExtension' => $baseDir . '/src/Type/DynamicFunctionReturnTypeExtension.php',
    'PHPStan\\Type\\DynamicMethodReturnTypeExtension' => $baseDir . '/src/Type/DynamicMethodReturnTypeExtension.php',
    'PHPStan\\Type\\DynamicStaticMethodReturnTypeExtension' => $baseDir . '/src/Type/DynamicStaticMethodReturnTypeExtension.php',
    'PHPStan\\Type\\ErrorType' => $baseDir . '/src/Type/ErrorType.php',
    'PHPStan\\Type\\FalseBooleanType' => $baseDir . '/src/Type/FalseBooleanType.php',
    'PHPStan\\Type\\FileTypeMapper' => $baseDir . '/src/Type/FileTypeMapper.php',
    'PHPStan\\Type\\FloatType' => $baseDir . '/src/Type/FloatType.php',
    'PHPStan\\Type\\IntegerType' => $baseDir . '/src/Type/IntegerType.php',
    'PHPStan\\Type\\IntersectionType' => $baseDir . '/src/Type/IntersectionType.php',
    'PHPStan\\Type\\IterableIterableType' => $baseDir . '/src/Type/IterableIterableType.php',
    'PHPStan\\Type\\IterableTypeTrait' => $baseDir . '/src/Type/IterableTypeTrait.php',
    'PHPStan\\Type\\JustNullableTypeTrait' => $baseDir . '/src/Type/JustNullableTypeTrait.php',
    'PHPStan\\Type\\MixedType' => $baseDir . '/src/Type/MixedType.php',
    'PHPStan\\Type\\NestedArrayItemType' => $baseDir . '/src/Type/NestedArrayItemType.php',
    'PHPStan\\Type\\NeverType' => $baseDir . '/src/Type/NeverType.php',
    'PHPStan\\Type\\NonexistentParentClassType' => $baseDir . '/src/Type/NonexistentParentClassType.php',
    'PHPStan\\Type\\NullType' => $baseDir . '/src/Type/NullType.php',
    'PHPStan\\Type\\ObjectType' => $baseDir . '/src/Type/ObjectType.php',
    'PHPStan\\Type\\ObjectWithoutClassType' => $baseDir . '/src/Type/ObjectWithoutClassType.php',
    'PHPStan\\Type\\Php\\AllArgumentBasedFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/AllArgumentBasedFunctionReturnTypeExtension.php',
    'PHPStan\\Type\\Php\\ArgumentBasedArrayFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArgumentBasedArrayFunctionReturnTypeExtension.php',
    'PHPStan\\Type\\Php\\ArgumentBasedFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/ArgumentBasedFunctionReturnTypeExtension.php',
    'PHPStan\\Type\\Php\\ArrayFilterFunctionReturnTypeReturnTypeExtension' => $baseDir . '/src/Type/Php/ArrayFilterFunctionReturnTypeReturnTypeExtension.php',
    'PHPStan\\Type\\Php\\CallbackBasedArrayFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/CallbackBasedArrayFunctionReturnTypeExtension.php',
    'PHPStan\\Type\\Php\\CallbackBasedFunctionReturnTypeExtension' => $baseDir . '/src/Type/Php/CallbackBasedFunctionReturnTypeExtension.php',
    'PHPStan\\Type\\RecursionGuard' => $baseDir . '/src/Type/RecursionGuard.php',
    'PHPStan\\Type\\ResourceType' => $baseDir . '/src/Type/ResourceType.php',
    'PHPStan\\Type\\StaticResolvableType' => $baseDir . '/src/Type/StaticResolvableType.php',
    'PHPStan\\Type\\StaticType' => $baseDir . '/src/Type/StaticType.php',
    'PHPStan\\Type\\StringType' => $baseDir . '/src/Type/StringType.php',
    'PHPStan\\Type\\ThisType' => $baseDir . '/src/Type/ThisType.php',
    'PHPStan\\Type\\TrueBooleanType' => $baseDir . '/src/Type/TrueBooleanType.php',
    'PHPStan\\Type\\TrueOrFalseBooleanType' => $baseDir . '/src/Type/TrueOrFalseBooleanType.php',
    'PHPStan\\Type\\Type' => $baseDir . '/src/Type/Type.php',
    'PHPStan\\Type\\TypeCombinator' => $baseDir . '/src/Type/TypeCombinator.php',
    'PHPStan\\Type\\TypeWithClassName' => $baseDir . '/src/Type/TypeWithClassName.php',
    'PHPStan\\Type\\TypehintHelper' => $baseDir . '/src/Type/TypehintHelper.php',
    'PHPStan\\Type\\UnionType' => $baseDir . '/src/Type/UnionType.php',
    'PHPStan\\Type\\UnionTypeHelper' => $baseDir . '/src/Type/UnionTypeHelper.php',
    'PHPStan\\Type\\VoidType' => $baseDir . '/src/Type/VoidType.php',
    'PhpParser\\Autoloader' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Autoloader.php',
    'PhpParser\\Builder' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder.php',
    'PhpParser\\BuilderAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/BuilderAbstract.php',
    'PhpParser\\BuilderFactory' => $vendorDir . '/nikic/php-parser/lib/PhpParser/BuilderFactory.php',
    'PhpParser\\Builder\\Class_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Class_.php',
    'PhpParser\\Builder\\Declaration' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Declaration.php',
    'PhpParser\\Builder\\FunctionLike' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php',
    'PhpParser\\Builder\\Function_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Function_.php',
    'PhpParser\\Builder\\Interface_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Interface_.php',
    'PhpParser\\Builder\\Method' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Method.php',
    'PhpParser\\Builder\\Namespace_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php',
    'PhpParser\\Builder\\Param' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Param.php',
    'PhpParser\\Builder\\Property' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Property.php',
    'PhpParser\\Builder\\Trait_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Trait_.php',
    'PhpParser\\Builder\\Use_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Use_.php',
    'PhpParser\\Comment' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Comment.php',
    'PhpParser\\Comment\\Doc' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Comment/Doc.php',
    'PhpParser\\Error' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Error.php',
    'PhpParser\\ErrorHandler' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ErrorHandler.php',
    'PhpParser\\ErrorHandler\\Collecting' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php',
    'PhpParser\\ErrorHandler\\Throwing' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php',
    'PhpParser\\Lexer' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer.php',
    'PhpParser\\Lexer\\Emulative' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php',
    'PhpParser\\Node' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node.php',
    'PhpParser\\NodeAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeAbstract.php',
    'PhpParser\\NodeDumper' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeDumper.php',
    'PhpParser\\NodeTraverser' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeTraverser.php',
    'PhpParser\\NodeTraverserInterface' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php',
    'PhpParser\\NodeVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor.php',
    'PhpParser\\NodeVisitorAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php',
    'PhpParser\\NodeVisitor\\NameResolver' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php',
    'PhpParser\\Node\\Arg' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Arg.php',
    'PhpParser\\Node\\Const_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Const_.php',
    'PhpParser\\Node\\Expr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr.php',
    'PhpParser\\Node\\Expr\\ArrayDimFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php',
    'PhpParser\\Node\\Expr\\ArrayItem' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php',
    'PhpParser\\Node\\Expr\\Array_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php',
    'PhpParser\\Node\\Expr\\Assign' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php',
    'PhpParser\\Node\\Expr\\AssignOp' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php',
    'PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php',
    'PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php',
    'PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php',
    'PhpParser\\Node\\Expr\\AssignOp\\Concat' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php',
    'PhpParser\\Node\\Expr\\AssignOp\\Div' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php',
    'PhpParser\\Node\\Expr\\AssignOp\\Minus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php',
    'PhpParser\\Node\\Expr\\AssignOp\\Mod' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php',
    'PhpParser\\Node\\Expr\\AssignOp\\Mul' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php',
    'PhpParser\\Node\\Expr\\AssignOp\\Plus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php',
    'PhpParser\\Node\\Expr\\AssignOp\\Pow' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php',
    'PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php',
    'PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php',
    'PhpParser\\Node\\Expr\\AssignRef' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php',
    'PhpParser\\Node\\Expr\\BinaryOp' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\Coalesce' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\Concat' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\Div' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\Equal' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\Greater' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\Identical' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\Minus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\Mod' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\Mul' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\Plus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\Pow' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php',
    'PhpParser\\Node\\Expr\\BinaryOp\\Spaceship' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php',
    'PhpParser\\Node\\Expr\\BitwiseNot' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php',
    'PhpParser\\Node\\Expr\\BooleanNot' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php',
    'PhpParser\\Node\\Expr\\Cast' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php',
    'PhpParser\\Node\\Expr\\Cast\\Array_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php',
    'PhpParser\\Node\\Expr\\Cast\\Bool_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php',
    'PhpParser\\Node\\Expr\\Cast\\Double' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php',
    'PhpParser\\Node\\Expr\\Cast\\Int_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php',
    'PhpParser\\Node\\Expr\\Cast\\Object_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php',
    'PhpParser\\Node\\Expr\\Cast\\String_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php',
    'PhpParser\\Node\\Expr\\Cast\\Unset_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php',
    'PhpParser\\Node\\Expr\\ClassConstFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php',
    'PhpParser\\Node\\Expr\\Clone_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php',
    'PhpParser\\Node\\Expr\\Closure' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php',
    'PhpParser\\Node\\Expr\\ClosureUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php',
    'PhpParser\\Node\\Expr\\ConstFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php',
    'PhpParser\\Node\\Expr\\Empty_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php',
    'PhpParser\\Node\\Expr\\Error' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php',
    'PhpParser\\Node\\Expr\\ErrorSuppress' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php',
    'PhpParser\\Node\\Expr\\Eval_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php',
    'PhpParser\\Node\\Expr\\Exit_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php',
    'PhpParser\\Node\\Expr\\FuncCall' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php',
    'PhpParser\\Node\\Expr\\Include_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php',
    'PhpParser\\Node\\Expr\\Instanceof_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php',
    'PhpParser\\Node\\Expr\\Isset_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php',
    'PhpParser\\Node\\Expr\\List_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php',
    'PhpParser\\Node\\Expr\\MethodCall' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php',
    'PhpParser\\Node\\Expr\\New_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php',
    'PhpParser\\Node\\Expr\\PostDec' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php',
    'PhpParser\\Node\\Expr\\PostInc' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php',
    'PhpParser\\Node\\Expr\\PreDec' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php',
    'PhpParser\\Node\\Expr\\PreInc' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php',
    'PhpParser\\Node\\Expr\\Print_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php',
    'PhpParser\\Node\\Expr\\PropertyFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php',
    'PhpParser\\Node\\Expr\\ShellExec' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php',
    'PhpParser\\Node\\Expr\\StaticCall' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php',
    'PhpParser\\Node\\Expr\\StaticPropertyFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php',
    'PhpParser\\Node\\Expr\\Ternary' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php',
    'PhpParser\\Node\\Expr\\UnaryMinus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php',
    'PhpParser\\Node\\Expr\\UnaryPlus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php',
    'PhpParser\\Node\\Expr\\Variable' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php',
    'PhpParser\\Node\\Expr\\YieldFrom' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php',
    'PhpParser\\Node\\Expr\\Yield_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php',
    'PhpParser\\Node\\FunctionLike' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php',
    'PhpParser\\Node\\Name' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Name.php',
    'PhpParser\\Node\\Name\\FullyQualified' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php',
    'PhpParser\\Node\\Name\\Relative' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php',
    'PhpParser\\Node\\NullableType' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/NullableType.php',
    'PhpParser\\Node\\Param' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Param.php',
    'PhpParser\\Node\\Scalar' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar.php',
    'PhpParser\\Node\\Scalar\\DNumber' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php',
    'PhpParser\\Node\\Scalar\\Encapsed' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php',
    'PhpParser\\Node\\Scalar\\EncapsedStringPart' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php',
    'PhpParser\\Node\\Scalar\\LNumber' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php',
    'PhpParser\\Node\\Scalar\\MagicConst' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php',
    'PhpParser\\Node\\Scalar\\MagicConst\\Class_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php',
    'PhpParser\\Node\\Scalar\\MagicConst\\Dir' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php',
    'PhpParser\\Node\\Scalar\\MagicConst\\File' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php',
    'PhpParser\\Node\\Scalar\\MagicConst\\Function_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php',
    'PhpParser\\Node\\Scalar\\MagicConst\\Line' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php',
    'PhpParser\\Node\\Scalar\\MagicConst\\Method' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php',
    'PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php',
    'PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php',
    'PhpParser\\Node\\Scalar\\String_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php',
    'PhpParser\\Node\\Stmt' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt.php',
    'PhpParser\\Node\\Stmt\\Break_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php',
    'PhpParser\\Node\\Stmt\\Case_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php',
    'PhpParser\\Node\\Stmt\\Catch_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php',
    'PhpParser\\Node\\Stmt\\ClassConst' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php',
    'PhpParser\\Node\\Stmt\\ClassLike' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php',
    'PhpParser\\Node\\Stmt\\ClassMethod' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php',
    'PhpParser\\Node\\Stmt\\Class_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php',
    'PhpParser\\Node\\Stmt\\Const_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php',
    'PhpParser\\Node\\Stmt\\Continue_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php',
    'PhpParser\\Node\\Stmt\\DeclareDeclare' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php',
    'PhpParser\\Node\\Stmt\\Declare_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php',
    'PhpParser\\Node\\Stmt\\Do_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php',
    'PhpParser\\Node\\Stmt\\Echo_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php',
    'PhpParser\\Node\\Stmt\\ElseIf_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php',
    'PhpParser\\Node\\Stmt\\Else_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php',
    'PhpParser\\Node\\Stmt\\Finally_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php',
    'PhpParser\\Node\\Stmt\\For_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php',
    'PhpParser\\Node\\Stmt\\Foreach_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php',
    'PhpParser\\Node\\Stmt\\Function_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php',
    'PhpParser\\Node\\Stmt\\Global_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php',
    'PhpParser\\Node\\Stmt\\Goto_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php',
    'PhpParser\\Node\\Stmt\\GroupUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php',
    'PhpParser\\Node\\Stmt\\HaltCompiler' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php',
    'PhpParser\\Node\\Stmt\\If_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php',
    'PhpParser\\Node\\Stmt\\InlineHTML' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php',
    'PhpParser\\Node\\Stmt\\Interface_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php',
    'PhpParser\\Node\\Stmt\\Label' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php',
    'PhpParser\\Node\\Stmt\\Namespace_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php',
    'PhpParser\\Node\\Stmt\\Nop' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php',
    'PhpParser\\Node\\Stmt\\Property' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php',
    'PhpParser\\Node\\Stmt\\PropertyProperty' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php',
    'PhpParser\\Node\\Stmt\\Return_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php',
    'PhpParser\\Node\\Stmt\\StaticVar' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php',
    'PhpParser\\Node\\Stmt\\Static_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php',
    'PhpParser\\Node\\Stmt\\Switch_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php',
    'PhpParser\\Node\\Stmt\\Throw_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php',
    'PhpParser\\Node\\Stmt\\TraitUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php',
    'PhpParser\\Node\\Stmt\\TraitUseAdaptation' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php',
    'PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Alias' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php',
    'PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Precedence' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php',
    'PhpParser\\Node\\Stmt\\Trait_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php',
    'PhpParser\\Node\\Stmt\\TryCatch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php',
    'PhpParser\\Node\\Stmt\\Unset_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php',
    'PhpParser\\Node\\Stmt\\UseUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php',
    'PhpParser\\Node\\Stmt\\Use_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php',
    'PhpParser\\Node\\Stmt\\While_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php',
    'PhpParser\\Parser' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser.php',
    'PhpParser\\ParserAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ParserAbstract.php',
    'PhpParser\\ParserFactory' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ParserFactory.php',
    'PhpParser\\Parser\\Multiple' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser/Multiple.php',
    'PhpParser\\Parser\\Php5' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser/Php5.php',
    'PhpParser\\Parser\\Php7' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser/Php7.php',
    'PhpParser\\Parser\\Tokens' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser/Tokens.php',
    'PhpParser\\PrettyPrinterAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php',
    'PhpParser\\PrettyPrinter\\Standard' => $vendorDir . '/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php',
    'PhpParser\\Serializer' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Serializer.php',
    'PhpParser\\Serializer\\XML' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Serializer/XML.php',
    'PhpParser\\Unserializer' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Unserializer.php',
    'PhpParser\\Unserializer\\XML' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Unserializer/XML.php',
);
<?php

// autoload_files.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
);
<?php

// autoload_namespaces.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    '' => array($vendorDir . '/netresearch/composer-patches-plugin/src'),
);
<?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
    'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
    'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
    'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
    'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
    'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
    'PackageVersions\\' => array($vendorDir . '/ocramius/package-versions/src/PackageVersions'),
    'PHPStan\\PhpDocParser\\' => array($vendorDir . '/phpstan/phpdoc-parser/src'),
    'PHPStan\\' => array($baseDir . '/src', $baseDir . '/build/PHPStan'),
    'Jean85\\' => array($vendorDir . '/jean85/pretty-package-versions/src'),
);
<?php

// autoload_real.php @generated by Composer

class ComposerAutoloaderInit125b023f43356e6992e24cd9f1067aeb
{
    private static $loader;

    public static function loadClassLoader($class)
    {
        if ('Composer\Autoload\ClassLoader' === $class) {
            require __DIR__ . '/ClassLoader.php';
        }
    }

    public static function getLoader()
    {
        if (null !== self::$loader) {
            return self::$loader;
        }

        spl_autoload_register(array('ComposerAutoloaderInit125b023f43356e6992e24cd9f1067aeb', 'loadClassLoader'), true, true);
        self::$loader = $loader = new \Composer\Autoload\ClassLoader();
        spl_autoload_unregister(array('ComposerAutoloaderInit125b023f43356e6992e24cd9f1067aeb', 'loadClassLoader'));

        $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
        if ($useStaticLoader) {
            require_once __DIR__ . '/autoload_static.php';

            call_user_func(\Composer\Autoload\ComposerStaticInit125b023f43356e6992e24cd9f1067aeb::getInitializer($loader));
        } else {
            $classMap = require __DIR__ . '/autoload_classmap.php';
            if ($classMap) {
                $loader->addClassMap($classMap);
            }
        }

        $loader->setClassMapAuthoritative(true);
        $loader->register(true);

        if ($useStaticLoader) {
            $includeFiles = Composer\Autoload\ComposerStaticInit125b023f43356e6992e24cd9f1067aeb::$files;
        } else {
            $includeFiles = require __DIR__ . '/autoload_files.php';
        }
        foreach ($includeFiles as $fileIdentifier => $file) {
            composerRequire125b023f43356e6992e24cd9f1067aeb($fileIdentifier, $file);
        }

        return $loader;
    }
}

function composerRequire125b023f43356e6992e24cd9f1067aeb($fileIdentifier, $file)
{
    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
        require $file;

        $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
    }
}
<?php

// autoload_static.php @generated by Composer

namespace Composer\Autoload;

class ComposerStaticInit125b023f43356e6992e24cd9f1067aeb
{
    public static $files = array (
        '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
    );

    public static $prefixLengthsPsr4 = array (
        'S' => 
        array (
            'Symfony\\Polyfill\\Mbstring\\' => 26,
            'Symfony\\Component\\Finder\\' => 25,
            'Symfony\\Component\\Debug\\' => 24,
            'Symfony\\Component\\Console\\' => 26,
        ),
        'P' => 
        array (
            'Psr\\Log\\' => 8,
            'PhpParser\\' => 10,
            'PackageVersions\\' => 16,
            'PHPStan\\PhpDocParser\\' => 21,
            'PHPStan\\' => 8,
        ),
        'J' => 
        array (
            'Jean85\\' => 7,
        ),
    );

    public static $prefixDirsPsr4 = array (
        'Symfony\\Polyfill\\Mbstring\\' => 
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
        ),
        'Symfony\\Component\\Finder\\' => 
        array (
            0 => __DIR__ . '/..' . '/symfony/finder',
        ),
        'Symfony\\Component\\Debug\\' => 
        array (
            0 => __DIR__ . '/..' . '/symfony/debug',
        ),
        'Symfony\\Component\\Console\\' => 
        array (
            0 => __DIR__ . '/..' . '/symfony/console',
        ),
        'Psr\\Log\\' => 
        array (
            0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
        ),
        'PhpParser\\' => 
        array (
            0 => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser',
        ),
        'PackageVersions\\' => 
        array (
            0 => __DIR__ . '/..' . '/ocramius/package-versions/src/PackageVersions',
        ),
        'PHPStan\\PhpDocParser\\' => 
        array (
            0 => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src',
        ),
        'PHPStan\\' => 
        array (
            0 => __DIR__ . '/../..' . '/src',
            1 => __DIR__ . '/../..' . '/build/PHPStan',
        ),
        'Jean85\\' => 
        array (
            0 => __DIR__ . '/..' . '/jean85/pretty-package-versions/src',
        ),
    );

    public static $fallbackDirsPsr0 = array (
        0 => __DIR__ . '/..' . '/netresearch/composer-patches-plugin/src',
    );

    public static $classMap = array (
        'ComposerAutoloaderInit125b023f43356e6992e24cd9f1067aeb' => __DIR__ . '/..' . '/composer/autoload_real.php',
        'Composer\\Autoload\\ClassLoader' => __DIR__ . '/..' . '/composer/ClassLoader.php',
        'Composer\\Autoload\\ComposerStaticInit125b023f43356e6992e24cd9f1067aeb' => __DIR__ . '/..' . '/composer/autoload_static.php',
        'PHPStanVendor\\Jean85\\PrettyVersions' => __DIR__ . '/..' . '/jean85/pretty-package-versions/src/PrettyVersions.php',
        'PHPStanVendor\\Jean85\\Version' => __DIR__ . '/..' . '/jean85/pretty-package-versions/src/Version.php',
        'PHPStanVendor\\Nette\\ArgumentOutOfRangeException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\Bridges\\DITracy\\ContainerPanel' => __DIR__ . '/..' . '/nette/di/src/Bridges/DITracy/ContainerPanel.php',
        'PHPStanVendor\\Nette\\Bridges\\Framework\\TracyBridge' => __DIR__ . '/..' . '/nette/bootstrap/src/Bridges/Framework/TracyBridge.php',
        'PHPStanVendor\\Nette\\Configurator' => __DIR__ . '/..' . '/nette/bootstrap/src/Bootstrap/Configurator.php',
        'PHPStanVendor\\Nette\\DI\\Compiler' => __DIR__ . '/..' . '/nette/di/src/DI/Compiler.php',
        'PHPStanVendor\\Nette\\DI\\CompilerExtension' => __DIR__ . '/..' . '/nette/di/src/DI/CompilerExtension.php',
        'PHPStanVendor\\Nette\\DI\\Config\\Adapters\\IniAdapter' => __DIR__ . '/..' . '/nette/di/src/DI/Config/Adapters/IniAdapter.php',
        'PHPStanVendor\\Nette\\DI\\Config\\Adapters\\NeonAdapter' => __DIR__ . '/..' . '/nette/di/src/DI/Config/Adapters/NeonAdapter.php',
        'PHPStanVendor\\Nette\\DI\\Config\\Adapters\\PhpAdapter' => __DIR__ . '/..' . '/nette/di/src/DI/Config/Adapters/PhpAdapter.php',
        'PHPStanVendor\\Nette\\DI\\Config\\Helpers' => __DIR__ . '/..' . '/nette/di/src/DI/Config/Helpers.php',
        'PHPStanVendor\\Nette\\DI\\Config\\IAdapter' => __DIR__ . '/..' . '/nette/di/src/DI/Config/IAdapter.php',
        'PHPStanVendor\\Nette\\DI\\Config\\Loader' => __DIR__ . '/..' . '/nette/di/src/DI/Config/Loader.php',
        'PHPStanVendor\\Nette\\DI\\Container' => __DIR__ . '/..' . '/nette/di/src/DI/Container.php',
        'PHPStanVendor\\Nette\\DI\\ContainerBuilder' => __DIR__ . '/..' . '/nette/di/src/DI/ContainerBuilder.php',
        'PHPStanVendor\\Nette\\DI\\ContainerLoader' => __DIR__ . '/..' . '/nette/di/src/DI/ContainerLoader.php',
        'PHPStanVendor\\Nette\\DI\\DependencyChecker' => __DIR__ . '/..' . '/nette/di/src/DI/DependencyChecker.php',
        'PHPStanVendor\\Nette\\DI\\Extensions\\ConstantsExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/ConstantsExtension.php',
        'PHPStanVendor\\Nette\\DI\\Extensions\\DIExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/DIExtension.php',
        'PHPStanVendor\\Nette\\DI\\Extensions\\DecoratorExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/DecoratorExtension.php',
        'PHPStanVendor\\Nette\\DI\\Extensions\\ExtensionsExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/ExtensionsExtension.php',
        'PHPStanVendor\\Nette\\DI\\Extensions\\InjectExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/InjectExtension.php',
        'PHPStanVendor\\Nette\\DI\\Extensions\\PhpExtension' => __DIR__ . '/..' . '/nette/di/src/DI/Extensions/PhpExtension.php',
        'PHPStanVendor\\Nette\\DI\\Helpers' => __DIR__ . '/..' . '/nette/di/src/DI/Helpers.php',
        'PHPStanVendor\\Nette\\DI\\MissingServiceException' => __DIR__ . '/..' . '/nette/di/src/DI/exceptions.php',
        'PHPStanVendor\\Nette\\DI\\PhpGenerator' => __DIR__ . '/..' . '/nette/di/src/DI/PhpGenerator.php',
        'PHPStanVendor\\Nette\\DI\\PhpReflection' => __DIR__ . '/..' . '/nette/di/src/DI/PhpReflection.php',
        'PHPStanVendor\\Nette\\DI\\ServiceCreationException' => __DIR__ . '/..' . '/nette/di/src/DI/exceptions.php',
        'PHPStanVendor\\Nette\\DI\\ServiceDefinition' => __DIR__ . '/..' . '/nette/di/src/DI/ServiceDefinition.php',
        'PHPStanVendor\\Nette\\DI\\Statement' => __DIR__ . '/..' . '/nette/di/src/DI/Statement.php',
        'PHPStanVendor\\Nette\\DeprecatedException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\DirectoryNotFoundException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\FileNotFoundException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\IOException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\InvalidArgumentException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\InvalidStateException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\Iterators\\CachingIterator' => __DIR__ . '/..' . '/nette/utils/src/Iterators/CachingIterator.php',
        'PHPStanVendor\\Nette\\Iterators\\Filter' => __DIR__ . '/..' . '/nette/utils/src/Iterators/Filter.php',
        'PHPStanVendor\\Nette\\Iterators\\Mapper' => __DIR__ . '/..' . '/nette/utils/src/Iterators/Mapper.php',
        'PHPStanVendor\\Nette\\Iterators\\RecursiveFilter' => __DIR__ . '/..' . '/nette/utils/src/Iterators/RecursiveFilter.php',
        'PHPStanVendor\\Nette\\Loaders\\RobotLoader' => __DIR__ . '/..' . '/nette/robot-loader/src/RobotLoader/RobotLoader.php',
        'PHPStanVendor\\Nette\\Localization\\ITranslator' => __DIR__ . '/..' . '/nette/utils/src/Utils/ITranslator.php',
        'PHPStanVendor\\Nette\\MemberAccessException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\Neon\\Decoder' => __DIR__ . '/..' . '/nette/neon/src/Neon/Decoder.php',
        'PHPStanVendor\\Nette\\Neon\\Encoder' => __DIR__ . '/..' . '/nette/neon/src/Neon/Encoder.php',
        'PHPStanVendor\\Nette\\Neon\\Entity' => __DIR__ . '/..' . '/nette/neon/src/Neon/Entity.php',
        'PHPStanVendor\\Nette\\Neon\\Exception' => __DIR__ . '/..' . '/nette/neon/src/Neon/Exception.php',
        'PHPStanVendor\\Nette\\Neon\\Neon' => __DIR__ . '/..' . '/nette/neon/src/Neon/Neon.php',
        'PHPStanVendor\\Nette\\NotImplementedException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\NotSupportedException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\Object' => __DIR__ . '/..' . '/nette/utils/src/Utils/Object.php',
        'PHPStanVendor\\Nette\\OutOfRangeException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\PhpGenerator\\ClassType' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/ClassType.php',
        'PHPStanVendor\\Nette\\PhpGenerator\\Closure' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Closure.php',
        'PHPStanVendor\\Nette\\PhpGenerator\\Constant' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Constant.php',
        'PHPStanVendor\\Nette\\PhpGenerator\\Factory' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Factory.php',
        'PHPStanVendor\\Nette\\PhpGenerator\\GlobalFunction' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/GlobalFunction.php',
        'PHPStanVendor\\Nette\\PhpGenerator\\Helpers' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Helpers.php',
        'PHPStanVendor\\Nette\\PhpGenerator\\Method' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Method.php',
        'PHPStanVendor\\Nette\\PhpGenerator\\Parameter' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Parameter.php',
        'PHPStanVendor\\Nette\\PhpGenerator\\PhpFile' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/PhpFile.php',
        'PHPStanVendor\\Nette\\PhpGenerator\\PhpLiteral' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/PhpLiteral.php',
        'PHPStanVendor\\Nette\\PhpGenerator\\PhpNamespace' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/PhpNamespace.php',
        'PHPStanVendor\\Nette\\PhpGenerator\\Property' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Property.php',
        'PHPStanVendor\\Nette\\PhpGenerator\\Traits\\CommentAware' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/CommentAware.php',
        'PHPStanVendor\\Nette\\PhpGenerator\\Traits\\FunctionLike' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/FunctionLike.php',
        'PHPStanVendor\\Nette\\PhpGenerator\\Traits\\NameAware' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/NameAware.php',
        'PHPStanVendor\\Nette\\PhpGenerator\\Traits\\VisibilityAware' => __DIR__ . '/..' . '/nette/php-generator/src/PhpGenerator/Traits/VisibilityAware.php',
        'PHPStanVendor\\Nette\\SmartObject' => __DIR__ . '/..' . '/nette/utils/src/Utils/SmartObject.php',
        'PHPStanVendor\\Nette\\StaticClass' => __DIR__ . '/..' . '/nette/utils/src/Utils/StaticClass.php',
        'PHPStanVendor\\Nette\\StaticClassException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\UnexpectedValueException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\Utils\\ArrayHash' => __DIR__ . '/..' . '/nette/utils/src/Utils/ArrayHash.php',
        'PHPStanVendor\\Nette\\Utils\\ArrayList' => __DIR__ . '/..' . '/nette/utils/src/Utils/ArrayList.php',
        'PHPStanVendor\\Nette\\Utils\\Arrays' => __DIR__ . '/..' . '/nette/utils/src/Utils/Arrays.php',
        'PHPStanVendor\\Nette\\Utils\\AssertionException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\Utils\\Callback' => __DIR__ . '/..' . '/nette/utils/src/Utils/Callback.php',
        'PHPStanVendor\\Nette\\Utils\\DateTime' => __DIR__ . '/..' . '/nette/utils/src/Utils/DateTime.php',
        'PHPStanVendor\\Nette\\Utils\\FileSystem' => __DIR__ . '/..' . '/nette/utils/src/Utils/FileSystem.php',
        'PHPStanVendor\\Nette\\Utils\\Finder' => __DIR__ . '/..' . '/nette/finder/src/Utils/Finder.php',
        'PHPStanVendor\\Nette\\Utils\\Html' => __DIR__ . '/..' . '/nette/utils/src/Utils/Html.php',
        'PHPStanVendor\\Nette\\Utils\\IHtmlString' => __DIR__ . '/..' . '/nette/utils/src/Utils/IHtmlString.php',
        'PHPStanVendor\\Nette\\Utils\\Image' => __DIR__ . '/..' . '/nette/utils/src/Utils/Image.php',
        'PHPStanVendor\\Nette\\Utils\\ImageException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\Utils\\Json' => __DIR__ . '/..' . '/nette/utils/src/Utils/Json.php',
        'PHPStanVendor\\Nette\\Utils\\JsonException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\Utils\\ObjectMixin' => __DIR__ . '/..' . '/nette/utils/src/Utils/ObjectMixin.php',
        'PHPStanVendor\\Nette\\Utils\\Paginator' => __DIR__ . '/..' . '/nette/utils/src/Utils/Paginator.php',
        'PHPStanVendor\\Nette\\Utils\\Random' => __DIR__ . '/..' . '/nette/utils/src/Utils/Random.php',
        'PHPStanVendor\\Nette\\Utils\\Reflection' => __DIR__ . '/..' . '/nette/utils/src/Utils/Reflection.php',
        'PHPStanVendor\\Nette\\Utils\\RegexpException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\Utils\\Strings' => __DIR__ . '/..' . '/nette/utils/src/Utils/Strings.php',
        'PHPStanVendor\\Nette\\Utils\\UnknownImageFileException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
        'PHPStanVendor\\Nette\\Utils\\Validators' => __DIR__ . '/..' . '/nette/utils/src/Utils/Validators.php',
        'PHPStanVendor\\PackageVersions\\FallbackVersions' => __DIR__ . '/..' . '/ocramius/package-versions/src/PackageVersions/FallbackVersions.php',
        'PHPStanVendor\\PackageVersions\\Installer' => __DIR__ . '/..' . '/ocramius/package-versions/src/PackageVersions/Installer.php',
        'PHPStanVendor\\PackageVersions\\Versions' => __DIR__ . '/..' . '/ocramius/package-versions/src/PackageVersions/Versions.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Application' => __DIR__ . '/..' . '/symfony/console/Application.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => __DIR__ . '/..' . '/symfony/console/CommandLoader/CommandLoaderInterface.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/ContainerCommandLoader.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/FactoryCommandLoader.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Command\\Command' => __DIR__ . '/..' . '/symfony/console/Command/Command.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Command\\HelpCommand' => __DIR__ . '/..' . '/symfony/console/Command/HelpCommand.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Command\\ListCommand' => __DIR__ . '/..' . '/symfony/console/Command/ListCommand.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Command\\LockableTrait' => __DIR__ . '/..' . '/symfony/console/Command/LockableTrait.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\ConsoleEvents' => __DIR__ . '/..' . '/symfony/console/ConsoleEvents.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => __DIR__ . '/..' . '/symfony/console/DependencyInjection/AddConsoleCommandPass.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => __DIR__ . '/..' . '/symfony/console/Descriptor/ApplicationDescription.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Descriptor\\Descriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/Descriptor.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => __DIR__ . '/..' . '/symfony/console/Descriptor/DescriptorInterface.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/JsonDescriptor.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/MarkdownDescriptor.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/TextDescriptor.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/XmlDescriptor.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\EventListener\\ErrorListener' => __DIR__ . '/..' . '/symfony/console/EventListener/ErrorListener.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleCommandEvent.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleErrorEvent.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Event\\ConsoleEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleEvent.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Event\\ConsoleExceptionEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleExceptionEvent.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleTerminateEvent.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => __DIR__ . '/..' . '/symfony/console/Exception/CommandNotFoundException.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/console/Exception/ExceptionInterface.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidArgumentException.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Exception\\InvalidOptionException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidOptionException.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/console/Exception/LogicException.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/console/Exception/RuntimeException.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatter' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatter.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterInterface.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyle.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyleInterface.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyleStack.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DebugFormatterHelper.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\DescriptorHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DescriptorHelper.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\FormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/FormatterHelper.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\Helper' => __DIR__ . '/..' . '/symfony/console/Helper/Helper.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\HelperInterface' => __DIR__ . '/..' . '/symfony/console/Helper/HelperInterface.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\HelperSet' => __DIR__ . '/..' . '/symfony/console/Helper/HelperSet.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\InputAwareHelper' => __DIR__ . '/..' . '/symfony/console/Helper/InputAwareHelper.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\ProcessHelper' => __DIR__ . '/..' . '/symfony/console/Helper/ProcessHelper.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\ProgressBar' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressBar.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\ProgressIndicator' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressIndicator.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\QuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/QuestionHelper.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/SymfonyQuestionHelper.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\Table' => __DIR__ . '/..' . '/symfony/console/Helper/Table.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\TableCell' => __DIR__ . '/..' . '/symfony/console/Helper/TableCell.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\TableSeparator' => __DIR__ . '/..' . '/symfony/console/Helper/TableSeparator.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Helper\\TableStyle' => __DIR__ . '/..' . '/symfony/console/Helper/TableStyle.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Input\\ArgvInput' => __DIR__ . '/..' . '/symfony/console/Input/ArgvInput.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Input\\ArrayInput' => __DIR__ . '/..' . '/symfony/console/Input/ArrayInput.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Input\\Input' => __DIR__ . '/..' . '/symfony/console/Input/Input.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Input\\InputArgument' => __DIR__ . '/..' . '/symfony/console/Input/InputArgument.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Input\\InputAwareInterface' => __DIR__ . '/..' . '/symfony/console/Input/InputAwareInterface.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Input\\InputDefinition' => __DIR__ . '/..' . '/symfony/console/Input/InputDefinition.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Input\\InputInterface' => __DIR__ . '/..' . '/symfony/console/Input/InputInterface.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Input\\InputOption' => __DIR__ . '/..' . '/symfony/console/Input/InputOption.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Input\\StreamableInputInterface' => __DIR__ . '/..' . '/symfony/console/Input/StreamableInputInterface.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Input\\StringInput' => __DIR__ . '/..' . '/symfony/console/Input/StringInput.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Logger\\ConsoleLogger' => __DIR__ . '/..' . '/symfony/console/Logger/ConsoleLogger.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Output\\BufferedOutput' => __DIR__ . '/..' . '/symfony/console/Output/BufferedOutput.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Output\\ConsoleOutput' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleOutput.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleOutputInterface.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Output\\NullOutput' => __DIR__ . '/..' . '/symfony/console/Output/NullOutput.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Output\\Output' => __DIR__ . '/..' . '/symfony/console/Output/Output.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Output\\OutputInterface' => __DIR__ . '/..' . '/symfony/console/Output/OutputInterface.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Output\\StreamOutput' => __DIR__ . '/..' . '/symfony/console/Output/StreamOutput.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Question\\ChoiceQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ChoiceQuestion.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ConfirmationQuestion.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Question\\Question' => __DIR__ . '/..' . '/symfony/console/Question/Question.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Style\\OutputStyle' => __DIR__ . '/..' . '/symfony/console/Style/OutputStyle.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Style\\StyleInterface' => __DIR__ . '/..' . '/symfony/console/Style/StyleInterface.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Style\\SymfonyStyle' => __DIR__ . '/..' . '/symfony/console/Style/SymfonyStyle.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Terminal' => __DIR__ . '/..' . '/symfony/console/Terminal.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Tester\\ApplicationTester' => __DIR__ . '/..' . '/symfony/console/Tester/ApplicationTester.php',
        'PHPStanVendor\\Symfony\\Component\\Console\\Tester\\CommandTester' => __DIR__ . '/..' . '/symfony/console/Tester/CommandTester.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Comparator\\Comparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/Comparator.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Comparator\\DateComparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/DateComparator.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Comparator\\NumberComparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/NumberComparator.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Exception\\AccessDeniedException' => __DIR__ . '/..' . '/symfony/finder/Exception/AccessDeniedException.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/finder/Exception/ExceptionInterface.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Finder' => __DIR__ . '/..' . '/symfony/finder/Finder.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Glob' => __DIR__ . '/..' . '/symfony/finder/Glob.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\CustomFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/CustomFilterIterator.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\DateRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/DateRangeFilterIterator.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\DepthRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/DepthRangeFilterIterator.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\ExcludeDirectoryFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FileTypeFilterIterator.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FilecontentFilterIterator.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FilenameFilterIterator.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\FilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FilterIterator.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/MultiplePcreFilterIterator.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/PathFilterIterator.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/RecursiveDirectoryIterator.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/SizeRangeFilterIterator.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\Iterator\\SortableIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/SortableIterator.php',
        'PHPStanVendor\\Symfony\\Component\\Finder\\SplFileInfo' => __DIR__ . '/..' . '/symfony/finder/SplFileInfo.php',
        'PHPStanVendor\\Symfony\\Polyfill\\Mbstring\\Mbstring' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/Mbstring.php',
        'PHPStan\\AnalysedCodeException' => __DIR__ . '/../..' . '/src/AnalysedCodeException.php',
        'PHPStan\\Analyser\\Analyser' => __DIR__ . '/../..' . '/src/Analyser/Analyser.php',
        'PHPStan\\Analyser\\Error' => __DIR__ . '/../..' . '/src/Analyser/Error.php',
        'PHPStan\\Analyser\\LookForAssignsSettings' => __DIR__ . '/../..' . '/src/Analyser/LookForAssignsSettings.php',
        'PHPStan\\Analyser\\NameScope' => __DIR__ . '/../..' . '/src/Analyser/NameScope.php',
        'PHPStan\\Analyser\\NodeScopeResolver' => __DIR__ . '/../..' . '/src/Analyser/NodeScopeResolver.php',
        'PHPStan\\Analyser\\Scope' => __DIR__ . '/../..' . '/src/Analyser/Scope.php',
        'PHPStan\\Analyser\\SpecifiedTypes' => __DIR__ . '/../..' . '/src/Analyser/SpecifiedTypes.php',
        'PHPStan\\Analyser\\StatementList' => __DIR__ . '/../..' . '/src/Analyser/StatementList.php',
        'PHPStan\\Analyser\\TypeSpecifier' => __DIR__ . '/../..' . '/src/Analyser/TypeSpecifier.php',
        'PHPStan\\Analyser\\UndefinedVariableException' => __DIR__ . '/../..' . '/src/Analyser/UndefinedVariableException.php',
        'PHPStan\\Analyser\\VariableTypeHolder' => __DIR__ . '/../..' . '/src/Analyser/VariableTypeHolder.php',
        'PHPStan\\Broker\\Broker' => __DIR__ . '/../..' . '/src/Broker/Broker.php',
        'PHPStan\\Broker\\BrokerFactory' => __DIR__ . '/../..' . '/src/Broker/BrokerFactory.php',
        'PHPStan\\Broker\\ClassAutoloadingException' => __DIR__ . '/../..' . '/src/Broker/ClassAutoloadingException.php',
        'PHPStan\\Broker\\ClassNotFoundException' => __DIR__ . '/../..' . '/src/Broker/ClassNotFoundException.php',
        'PHPStan\\Broker\\FunctionNotFoundException' => __DIR__ . '/../..' . '/src/Broker/FunctionNotFoundException.php',
        'PHPStan\\Cache\\Cache' => __DIR__ . '/../..' . '/src/Cache/Cache.php',
        'PHPStan\\Cache\\CacheStorage' => __DIR__ . '/../..' . '/src/Cache/CacheStorage.php',
        'PHPStan\\Cache\\FileCacheStorage' => __DIR__ . '/../..' . '/src/Cache/FileCacheStorage.php',
        'PHPStan\\Cache\\MemoryCacheStorage' => __DIR__ . '/../..' . '/src/Cache/MemoryCacheStorage.php',
        'PHPStan\\Command\\AnalyseApplication' => __DIR__ . '/../..' . '/src/Command/AnalyseApplication.php',
        'PHPStan\\Command\\AnalyseCommand' => __DIR__ . '/../..' . '/src/Command/AnalyseCommand.php',
        'PHPStan\\Command\\AnalysisResult' => __DIR__ . '/../..' . '/src/Command/AnalysisResult.php',
        'PHPStan\\Command\\ErrorFormatter\\CheckstyleErrorFormatter' => __DIR__ . '/../..' . '/src/Command/ErrorFormatter/CheckstyleErrorFormatter.php',
        'PHPStan\\Command\\ErrorFormatter\\ErrorFormatter' => __DIR__ . '/../..' . '/src/Command/ErrorFormatter/ErrorFormatter.php',
        'PHPStan\\Command\\ErrorFormatter\\RawErrorFormatter' => __DIR__ . '/../..' . '/src/Command/ErrorFormatter/RawErrorFormatter.php',
        'PHPStan\\Command\\ErrorFormatter\\TableErrorFormatter' => __DIR__ . '/../..' . '/src/Command/ErrorFormatter/TableErrorFormatter.php',
        'PHPStan\\Command\\ErrorsConsoleStyle' => __DIR__ . '/../..' . '/src/Command/ErrorsConsoleStyle.php',
        'PHPStan\\DependencyInjection\\ContainerFactory' => __DIR__ . '/../..' . '/src/DependencyInjection/ContainerFactory.php',
        'PHPStan\\File\\FileExcluder' => __DIR__ . '/../..' . '/src/File/FileExcluder.php',
        'PHPStan\\File\\FileHelper' => __DIR__ . '/../..' . '/src/File/FileHelper.php',
        'PHPStan\\Parser\\CachedParser' => __DIR__ . '/../..' . '/src/Parser/CachedParser.php',
        'PHPStan\\Parser\\DirectParser' => __DIR__ . '/../..' . '/src/Parser/DirectParser.php',
        'PHPStan\\Parser\\FunctionCallStatementFinder' => __DIR__ . '/../..' . '/src/Parser/FunctionCallStatementFinder.php',
        'PHPStan\\Parser\\Parser' => __DIR__ . '/../..' . '/src/Parser/Parser.php',
        'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayItemNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php',
        'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php',
        'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFalseNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php',
        'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFloatNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php',
        'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprIntegerNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php',
        'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php',
        'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNullNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php',
        'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprStringNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php',
        'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprTrueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php',
        'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstFetchNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php',
        'PHPStan\\PhpDocParser\\Ast\\Node' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Node.php',
        'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\GenericTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php',
        'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\InvalidTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php',
        'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php',
        'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueParameterNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php',
        'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php',
        'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocChildNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php',
        'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php',
        'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php',
        'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php',
        'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTextNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php',
        'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PropertyTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php',
        'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ReturnTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php',
        'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ThrowsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php',
        'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\VarTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php',
        'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php',
        'PHPStan\\PhpDocParser\\Ast\\Type\\GenericTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php',
        'PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php',
        'PHPStan\\PhpDocParser\\Ast\\Type\\IntersectionTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php',
        'PHPStan\\PhpDocParser\\Ast\\Type\\NullableTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php',
        'PHPStan\\PhpDocParser\\Ast\\Type\\ThisTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php',
        'PHPStan\\PhpDocParser\\Ast\\Type\\TypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php',
        'PHPStan\\PhpDocParser\\Ast\\Type\\UnionTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php',
        'PHPStan\\PhpDocParser\\Lexer\\Lexer' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Lexer/Lexer.php',
        'PHPStan\\PhpDocParser\\Parser\\ConstExprParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php',
        'PHPStan\\PhpDocParser\\Parser\\ParserException' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/ParserException.php',
        'PHPStan\\PhpDocParser\\Parser\\PhpDocParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php',
        'PHPStan\\PhpDocParser\\Parser\\TokenIterator' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/TokenIterator.php',
        'PHPStan\\PhpDocParser\\Parser\\TypeParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/TypeParser.php',
        'PHPStan\\PhpDoc\\PhpDocBlock' => __DIR__ . '/../..' . '/src/PhpDoc/PhpDocBlock.php',
        'PHPStan\\PhpDoc\\PhpDocNodeResolver' => __DIR__ . '/../..' . '/src/PhpDoc/PhpDocNodeResolver.php',
        'PHPStan\\PhpDoc\\PhpDocStringResolver' => __DIR__ . '/../..' . '/src/PhpDoc/PhpDocStringResolver.php',
        'PHPStan\\PhpDoc\\ResolvedPhpDocBlock' => __DIR__ . '/../..' . '/src/PhpDoc/ResolvedPhpDocBlock.php',
        'PHPStan\\PhpDoc\\Tag\\MethodTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/MethodTag.php',
        'PHPStan\\PhpDoc\\Tag\\MethodTagParameter' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/MethodTagParameter.php',
        'PHPStan\\PhpDoc\\Tag\\ParamTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/ParamTag.php',
        'PHPStan\\PhpDoc\\Tag\\PropertyTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/PropertyTag.php',
        'PHPStan\\PhpDoc\\Tag\\ReturnTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/ReturnTag.php',
        'PHPStan\\PhpDoc\\Tag\\VarTag' => __DIR__ . '/../..' . '/src/PhpDoc/Tag/VarTag.php',
        'PHPStan\\PhpDoc\\TypeNodeResolver' => __DIR__ . '/../..' . '/src/PhpDoc/TypeNodeResolver.php',
        'PHPStan\\PhpDoc\\TypeStringResolver' => __DIR__ . '/../..' . '/src/PhpDoc/TypeStringResolver.php',
        'PHPStan\\Reflection\\Annotations\\AnnotationMethodReflection' => __DIR__ . '/../..' . '/src/Reflection/Annotations/AnnotationMethodReflection.php',
        'PHPStan\\Reflection\\Annotations\\AnnotationPropertyReflection' => __DIR__ . '/../..' . '/src/Reflection/Annotations/AnnotationPropertyReflection.php',
        'PHPStan\\Reflection\\Annotations\\AnnotationsMethodParameterReflection' => __DIR__ . '/../..' . '/src/Reflection/Annotations/AnnotationsMethodParameterReflection.php',
        'PHPStan\\Reflection\\Annotations\\AnnotationsMethodsClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/Annotations/AnnotationsMethodsClassReflectionExtension.php',
        'PHPStan\\Reflection\\Annotations\\AnnotationsPropertiesClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/Annotations/AnnotationsPropertiesClassReflectionExtension.php',
        'PHPStan\\Reflection\\BrokerAwareClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/BrokerAwareClassReflectionExtension.php',
        'PHPStan\\Reflection\\BrokerAwareExtension' => __DIR__ . '/../..' . '/src/Reflection/BrokerAwareExtension.php',
        'PHPStan\\Reflection\\ClassConstantReflection' => __DIR__ . '/../..' . '/src/Reflection/ClassConstantReflection.php',
        'PHPStan\\Reflection\\ClassConstantWithVisibilityReflection' => __DIR__ . '/../..' . '/src/Reflection/ClassConstantWithVisibilityReflection.php',
        'PHPStan\\Reflection\\ClassMemberReflection' => __DIR__ . '/../..' . '/src/Reflection/ClassMemberReflection.php',
        'PHPStan\\Reflection\\ClassReflection' => __DIR__ . '/../..' . '/src/Reflection/ClassReflection.php',
        'PHPStan\\Reflection\\FunctionReflection' => __DIR__ . '/../..' . '/src/Reflection/FunctionReflection.php',
        'PHPStan\\Reflection\\FunctionReflectionFactory' => __DIR__ . '/../..' . '/src/Reflection/FunctionReflectionFactory.php',
        'PHPStan\\Reflection\\MethodReflection' => __DIR__ . '/../..' . '/src/Reflection/MethodReflection.php',
        'PHPStan\\Reflection\\MethodsClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/MethodsClassReflectionExtension.php',
        'PHPStan\\Reflection\\MissingMethodFromReflectionException' => __DIR__ . '/../..' . '/src/Reflection/MissingMethodFromReflectionException.php',
        'PHPStan\\Reflection\\MissingPropertyFromReflectionException' => __DIR__ . '/../..' . '/src/Reflection/MissingPropertyFromReflectionException.php',
        'PHPStan\\Reflection\\ObsoleteClassConstantReflection' => __DIR__ . '/../..' . '/src/Reflection/ObsoleteClassConstantReflection.php',
        'PHPStan\\Reflection\\ParameterReflection' => __DIR__ . '/../..' . '/src/Reflection/ParameterReflection.php',
        'PHPStan\\Reflection\\ParametersAcceptor' => __DIR__ . '/../..' . '/src/Reflection/ParametersAcceptor.php',
        'PHPStan\\Reflection\\ParametersAcceptorWithPhpDocs' => __DIR__ . '/../..' . '/src/Reflection/ParametersAcceptorWithPhpDocs.php',
        'PHPStan\\Reflection\\PhpDefect\\PhpDefectClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/PhpDefect/PhpDefectClassReflectionExtension.php',
        'PHPStan\\Reflection\\PhpDefect\\PhpDefectPropertyReflection' => __DIR__ . '/../..' . '/src/Reflection/PhpDefect/PhpDefectPropertyReflection.php',
        'PHPStan\\Reflection\\Php\\DummyParameter' => __DIR__ . '/../..' . '/src/Reflection/Php/DummyParameter.php',
        'PHPStan\\Reflection\\Php\\PhpClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/Php/PhpClassReflectionExtension.php',
        'PHPStan\\Reflection\\Php\\PhpFunctionFromParserNodeReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php',
        'PHPStan\\Reflection\\Php\\PhpMethodFromParserNodeReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/PhpMethodFromParserNodeReflection.php',
        'PHPStan\\Reflection\\Php\\PhpMethodReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/PhpMethodReflection.php',
        'PHPStan\\Reflection\\Php\\PhpMethodReflectionFactory' => __DIR__ . '/../..' . '/src/Reflection/Php/PhpMethodReflectionFactory.php',
        'PHPStan\\Reflection\\Php\\PhpParameterFromParserNodeReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/PhpParameterFromParserNodeReflection.php',
        'PHPStan\\Reflection\\Php\\PhpParameterReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/PhpParameterReflection.php',
        'PHPStan\\Reflection\\Php\\PhpPropertyReflection' => __DIR__ . '/../..' . '/src/Reflection/Php/PhpPropertyReflection.php',
        'PHPStan\\Reflection\\Php\\UniversalObjectCrateProperty' => __DIR__ . '/../..' . '/src/Reflection/Php/UniversalObjectCrateProperty.php',
        'PHPStan\\Reflection\\Php\\UniversalObjectCratesClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/Php/UniversalObjectCratesClassReflectionExtension.php',
        'PHPStan\\Reflection\\PropertiesClassReflectionExtension' => __DIR__ . '/../..' . '/src/Reflection/PropertiesClassReflectionExtension.php',
        'PHPStan\\Reflection\\PropertyReflection' => __DIR__ . '/../..' . '/src/Reflection/PropertyReflection.php',
        'PHPStan\\Rules\\Arrays\\AllowedArrayKeysTypes' => __DIR__ . '/../..' . '/src/Rules/Arrays/AllowedArrayKeysTypes.php',
        'PHPStan\\Rules\\Arrays\\AppendedArrayItemTypeRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/AppendedArrayItemTypeRule.php',
        'PHPStan\\Rules\\Arrays\\DuplicateKeysInLiteralArraysRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/DuplicateKeysInLiteralArraysRule.php',
        'PHPStan\\Rules\\Arrays\\InvalidKeyInArrayDimFetchRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/InvalidKeyInArrayDimFetchRule.php',
        'PHPStan\\Rules\\Arrays\\InvalidKeyInArrayItemRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/InvalidKeyInArrayItemRule.php',
        'PHPStan\\Rules\\Arrays\\IterableInForeachRule' => __DIR__ . '/../..' . '/src/Rules/Arrays/IterableInForeachRule.php',
        'PHPStan\\Rules\\Cast\\UselessCastRule' => __DIR__ . '/../..' . '/src/Rules/Cast/UselessCastRule.php',
        'PHPStan\\Rules\\ClassCaseSensitivityCheck' => __DIR__ . '/../..' . '/src/Rules/ClassCaseSensitivityCheck.php',
        'PHPStan\\Rules\\Classes\\ClassConstantRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ClassConstantRule.php',
        'PHPStan\\Rules\\Classes\\ExistingClassInClassExtendsRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ExistingClassInClassExtendsRule.php',
        'PHPStan\\Rules\\Classes\\ExistingClassInInstanceOfRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ExistingClassInInstanceOfRule.php',
        'PHPStan\\Rules\\Classes\\ExistingClassInTraitUseRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ExistingClassInTraitUseRule.php',
        'PHPStan\\Rules\\Classes\\ExistingClassesInClassImplementsRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ExistingClassesInClassImplementsRule.php',
        'PHPStan\\Rules\\Classes\\ExistingClassesInInterfaceExtendsRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ExistingClassesInInterfaceExtendsRule.php',
        'PHPStan\\Rules\\Classes\\ImpossibleInstanceOfRule' => __DIR__ . '/../..' . '/src/Rules/Classes/ImpossibleInstanceOfRule.php',
        'PHPStan\\Rules\\Classes\\InstantiationRule' => __DIR__ . '/../..' . '/src/Rules/Classes/InstantiationRule.php',
        'PHPStan\\Rules\\Classes\\RequireParentConstructCallRule' => __DIR__ . '/../..' . '/src/Rules/Classes/RequireParentConstructCallRule.php',
        'PHPStan\\Rules\\Classes\\UnusedConstructorParametersRule' => __DIR__ . '/../..' . '/src/Rules/Classes/UnusedConstructorParametersRule.php',
        'PHPStan\\Rules\\Comparison\\ImpossibleCheckTypeFunctionCallRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/ImpossibleCheckTypeFunctionCallRule.php',
        'PHPStan\\Rules\\Comparison\\StrictComparisonOfDifferentTypesRule' => __DIR__ . '/../..' . '/src/Rules/Comparison/StrictComparisonOfDifferentTypesRule.php',
        'PHPStan\\Rules\\Constants\\ConstantRule' => __DIR__ . '/../..' . '/src/Rules/Constants/ConstantRule.php',
        'PHPStan\\Rules\\Exceptions\\CaughtExceptionExistenceRule' => __DIR__ . '/../..' . '/src/Rules/Exceptions/CaughtExceptionExistenceRule.php',
        'PHPStan\\Rules\\FoundTypeResult' => __DIR__ . '/../..' . '/src/Rules/FoundTypeResult.php',
        'PHPStan\\Rules\\FunctionCallParametersCheck' => __DIR__ . '/../..' . '/src/Rules/FunctionCallParametersCheck.php',
        'PHPStan\\Rules\\FunctionDefinitionCheck' => __DIR__ . '/../..' . '/src/Rules/FunctionDefinitionCheck.php',
        'PHPStan\\Rules\\FunctionReturnTypeCheck' => __DIR__ . '/../..' . '/src/Rules/FunctionReturnTypeCheck.php',
        'PHPStan\\Rules\\Functions\\CallToCountOnlyWithArrayOrCountableRule' => __DIR__ . '/../..' . '/src/Rules/Functions/CallToCountOnlyWithArrayOrCountableRule.php',
        'PHPStan\\Rules\\Functions\\CallToFunctionParametersRule' => __DIR__ . '/../..' . '/src/Rules/Functions/CallToFunctionParametersRule.php',
        'PHPStan\\Rules\\Functions\\CallToNonExistentFunctionRule' => __DIR__ . '/../..' . '/src/Rules/Functions/CallToNonExistentFunctionRule.php',
        'PHPStan\\Rules\\Functions\\ClosureReturnTypeRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ClosureReturnTypeRule.php',
        'PHPStan\\Rules\\Functions\\ExistingClassesInClosureTypehintsRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ExistingClassesInClosureTypehintsRule.php',
        'PHPStan\\Rules\\Functions\\ExistingClassesInTypehintsRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ExistingClassesInTypehintsRule.php',
        'PHPStan\\Rules\\Functions\\InnerFunctionRule' => __DIR__ . '/../..' . '/src/Rules/Functions/InnerFunctionRule.php',
        'PHPStan\\Rules\\Functions\\NonExistentDefinedFunctionRule' => __DIR__ . '/../..' . '/src/Rules/Functions/NonExistentDefinedFunctionRule.php',
        'PHPStan\\Rules\\Functions\\PrintfParametersRule' => __DIR__ . '/../..' . '/src/Rules/Functions/PrintfParametersRule.php',
        'PHPStan\\Rules\\Functions\\ReturnTypeRule' => __DIR__ . '/../..' . '/src/Rules/Functions/ReturnTypeRule.php',
        'PHPStan\\Rules\\Functions\\UnusedClosureUsesRule' => __DIR__ . '/../..' . '/src/Rules/Functions/UnusedClosureUsesRule.php',
        'PHPStan\\Rules\\Methods\\CallMethodsOnPossiblyNullRule' => __DIR__ . '/../..' . '/src/Rules/Methods/CallMethodsOnPossiblyNullRule.php',
        'PHPStan\\Rules\\Methods\\CallMethodsRule' => __DIR__ . '/../..' . '/src/Rules/Methods/CallMethodsRule.php',
        'PHPStan\\Rules\\Methods\\CallStaticMethodsRule' => __DIR__ . '/../..' . '/src/Rules/Methods/CallStaticMethodsRule.php',
        'PHPStan\\Rules\\Methods\\ExistingClassesInTypehintsRule' => __DIR__ . '/../..' . '/src/Rules/Methods/ExistingClassesInTypehintsRule.php',
        'PHPStan\\Rules\\Methods\\ReturnTypeRule' => __DIR__ . '/../..' . '/src/Rules/Methods/ReturnTypeRule.php',
        'PHPStan\\Rules\\Namespaces\\ExistingNamesInGroupUseRule' => __DIR__ . '/../..' . '/src/Rules/Namespaces/ExistingNamesInGroupUseRule.php',
        'PHPStan\\Rules\\Namespaces\\ExistingNamesInUseRule' => __DIR__ . '/../..' . '/src/Rules/Namespaces/ExistingNamesInUseRule.php',
        'PHPStan\\Rules\\PhpDoc\\IncompatiblePhpDocTypeRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/IncompatiblePhpDocTypeRule.php',
        'PHPStan\\Rules\\PhpDoc\\InvalidPhpDocTagValueRule' => __DIR__ . '/../..' . '/src/Rules/PhpDoc/InvalidPhpDocTagValueRule.php',
        'PHPStan\\Rules\\Properties\\AccessPropertiesOnPossiblyNullRule' => __DIR__ . '/../..' . '/src/Rules/Properties/AccessPropertiesOnPossiblyNullRule.php',
        'PHPStan\\Rules\\Properties\\AccessPropertiesRule' => __DIR__ . '/../..' . '/src/Rules/Properties/AccessPropertiesRule.php',
        'PHPStan\\Rules\\Properties\\AccessStaticPropertiesRule' => __DIR__ . '/../..' . '/src/Rules/Properties/AccessStaticPropertiesRule.php',
        'PHPStan\\Rules\\Properties\\DefaultValueTypesAssignedToPropertiesRule' => __DIR__ . '/../..' . '/src/Rules/Properties/DefaultValueTypesAssignedToPropertiesRule.php',
        'PHPStan\\Rules\\Properties\\ExistingClassesInPropertiesRule' => __DIR__ . '/../..' . '/src/Rules/Properties/ExistingClassesInPropertiesRule.php',
        'PHPStan\\Rules\\Properties\\PropertyDescriptor' => __DIR__ . '/../..' . '/src/Rules/Properties/PropertyDescriptor.php',
        'PHPStan\\Rules\\Properties\\PropertyReflectionFinder' => __DIR__ . '/../..' . '/src/Rules/Properties/PropertyReflectionFinder.php',
        'PHPStan\\Rules\\Properties\\ReadingWriteOnlyPropertiesRule' => __DIR__ . '/../..' . '/src/Rules/Properties/ReadingWriteOnlyPropertiesRule.php',
        'PHPStan\\Rules\\Properties\\TypesAssignedToPropertiesRule' => __DIR__ . '/../..' . '/src/Rules/Properties/TypesAssignedToPropertiesRule.php',
        'PHPStan\\Rules\\Properties\\WritingToReadOnlyPropertiesRule' => __DIR__ . '/../..' . '/src/Rules/Properties/WritingToReadOnlyPropertiesRule.php',
        'PHPStan\\Rules\\Registry' => __DIR__ . '/../..' . '/src/Rules/Registry.php',
        'PHPStan\\Rules\\RegistryFactory' => __DIR__ . '/../..' . '/src/Rules/RegistryFactory.php',
        'PHPStan\\Rules\\Rule' => __DIR__ . '/../..' . '/src/Rules/Rule.php',
        'PHPStan\\Rules\\RuleLevelHelper' => __DIR__ . '/../..' . '/src/Rules/RuleLevelHelper.php',
        'PHPStan\\Rules\\UnusedFunctionParametersCheck' => __DIR__ . '/../..' . '/src/Rules/UnusedFunctionParametersCheck.php',
        'PHPStan\\Rules\\Variables\\DefinedVariableInAnonymousFunctionUseRule' => __DIR__ . '/../..' . '/src/Rules/Variables/DefinedVariableInAnonymousFunctionUseRule.php',
        'PHPStan\\Rules\\Variables\\DefinedVariableRule' => __DIR__ . '/../..' . '/src/Rules/Variables/DefinedVariableRule.php',
        'PHPStan\\Rules\\Variables\\ThisVariableRule' => __DIR__ . '/../..' . '/src/Rules/Variables/ThisVariableRule.php',
        'PHPStan\\Rules\\Variables\\VariableCertaintyInIssetRule' => __DIR__ . '/../..' . '/src/Rules/Variables/VariableCertaintyInIssetRule.php',
        'PHPStan\\Rules\\Variables\\VariableCloningRule' => __DIR__ . '/../..' . '/src/Rules/Variables/VariableCloningRule.php',
        'PHPStan\\ShouldNotHappenException' => __DIR__ . '/../..' . '/src/ShouldNotHappenException.php',
        'PHPStan\\Testing\\RuleTestCase' => __DIR__ . '/../..' . '/src/Testing/RuleTestCase.php',
        'PHPStan\\Testing\\TestCase' => __DIR__ . '/../..' . '/src/Testing/TestCase.php',
        'PHPStan\\TrinaryLogic' => __DIR__ . '/../..' . '/src/TrinaryLogic.php',
        'PHPStan\\Type\\ArrayType' => __DIR__ . '/../..' . '/src/Type/ArrayType.php',
        'PHPStan\\Type\\BooleanType' => __DIR__ . '/../..' . '/src/Type/BooleanType.php',
        'PHPStan\\Type\\CallableType' => __DIR__ . '/../..' . '/src/Type/CallableType.php',
        'PHPStan\\Type\\CommentHelper' => __DIR__ . '/../..' . '/src/Type/CommentHelper.php',
        'PHPStan\\Type\\CompoundType' => __DIR__ . '/../..' . '/src/Type/CompoundType.php',
        'PHPStan\\Type\\CompoundTypeHelper' => __DIR__ . '/../..' . '/src/Type/CompoundTypeHelper.php',
        'PHPStan\\Type\\DynamicFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/DynamicFunctionReturnTypeExtension.php',
        'PHPStan\\Type\\DynamicMethodReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/DynamicMethodReturnTypeExtension.php',
        'PHPStan\\Type\\DynamicStaticMethodReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/DynamicStaticMethodReturnTypeExtension.php',
        'PHPStan\\Type\\ErrorType' => __DIR__ . '/../..' . '/src/Type/ErrorType.php',
        'PHPStan\\Type\\FalseBooleanType' => __DIR__ . '/../..' . '/src/Type/FalseBooleanType.php',
        'PHPStan\\Type\\FileTypeMapper' => __DIR__ . '/../..' . '/src/Type/FileTypeMapper.php',
        'PHPStan\\Type\\FloatType' => __DIR__ . '/../..' . '/src/Type/FloatType.php',
        'PHPStan\\Type\\IntegerType' => __DIR__ . '/../..' . '/src/Type/IntegerType.php',
        'PHPStan\\Type\\IntersectionType' => __DIR__ . '/../..' . '/src/Type/IntersectionType.php',
        'PHPStan\\Type\\IterableIterableType' => __DIR__ . '/../..' . '/src/Type/IterableIterableType.php',
        'PHPStan\\Type\\IterableTypeTrait' => __DIR__ . '/../..' . '/src/Type/IterableTypeTrait.php',
        'PHPStan\\Type\\JustNullableTypeTrait' => __DIR__ . '/../..' . '/src/Type/JustNullableTypeTrait.php',
        'PHPStan\\Type\\MixedType' => __DIR__ . '/../..' . '/src/Type/MixedType.php',
        'PHPStan\\Type\\NestedArrayItemType' => __DIR__ . '/../..' . '/src/Type/NestedArrayItemType.php',
        'PHPStan\\Type\\NeverType' => __DIR__ . '/../..' . '/src/Type/NeverType.php',
        'PHPStan\\Type\\NonexistentParentClassType' => __DIR__ . '/../..' . '/src/Type/NonexistentParentClassType.php',
        'PHPStan\\Type\\NullType' => __DIR__ . '/../..' . '/src/Type/NullType.php',
        'PHPStan\\Type\\ObjectType' => __DIR__ . '/../..' . '/src/Type/ObjectType.php',
        'PHPStan\\Type\\ObjectWithoutClassType' => __DIR__ . '/../..' . '/src/Type/ObjectWithoutClassType.php',
        'PHPStan\\Type\\Php\\AllArgumentBasedFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/AllArgumentBasedFunctionReturnTypeExtension.php',
        'PHPStan\\Type\\Php\\ArgumentBasedArrayFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArgumentBasedArrayFunctionReturnTypeExtension.php',
        'PHPStan\\Type\\Php\\ArgumentBasedFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArgumentBasedFunctionReturnTypeExtension.php',
        'PHPStan\\Type\\Php\\ArrayFilterFunctionReturnTypeReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/ArrayFilterFunctionReturnTypeReturnTypeExtension.php',
        'PHPStan\\Type\\Php\\CallbackBasedArrayFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/CallbackBasedArrayFunctionReturnTypeExtension.php',
        'PHPStan\\Type\\Php\\CallbackBasedFunctionReturnTypeExtension' => __DIR__ . '/../..' . '/src/Type/Php/CallbackBasedFunctionReturnTypeExtension.php',
        'PHPStan\\Type\\RecursionGuard' => __DIR__ . '/../..' . '/src/Type/RecursionGuard.php',
        'PHPStan\\Type\\ResourceType' => __DIR__ . '/../..' . '/src/Type/ResourceType.php',
        'PHPStan\\Type\\StaticResolvableType' => __DIR__ . '/../..' . '/src/Type/StaticResolvableType.php',
        'PHPStan\\Type\\StaticType' => __DIR__ . '/../..' . '/src/Type/StaticType.php',
        'PHPStan\\Type\\StringType' => __DIR__ . '/../..' . '/src/Type/StringType.php',
        'PHPStan\\Type\\ThisType' => __DIR__ . '/../..' . '/src/Type/ThisType.php',
        'PHPStan\\Type\\TrueBooleanType' => __DIR__ . '/../..' . '/src/Type/TrueBooleanType.php',
        'PHPStan\\Type\\TrueOrFalseBooleanType' => __DIR__ . '/../..' . '/src/Type/TrueOrFalseBooleanType.php',
        'PHPStan\\Type\\Type' => __DIR__ . '/../..' . '/src/Type/Type.php',
        'PHPStan\\Type\\TypeCombinator' => __DIR__ . '/../..' . '/src/Type/TypeCombinator.php',
        'PHPStan\\Type\\TypeWithClassName' => __DIR__ . '/../..' . '/src/Type/TypeWithClassName.php',
        'PHPStan\\Type\\TypehintHelper' => __DIR__ . '/../..' . '/src/Type/TypehintHelper.php',
        'PHPStan\\Type\\UnionType' => __DIR__ . '/../..' . '/src/Type/UnionType.php',
        'PHPStan\\Type\\UnionTypeHelper' => __DIR__ . '/../..' . '/src/Type/UnionTypeHelper.php',
        'PHPStan\\Type\\VoidType' => __DIR__ . '/../..' . '/src/Type/VoidType.php',
        'PhpParser\\Autoloader' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Autoloader.php',
        'PhpParser\\Builder' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder.php',
        'PhpParser\\BuilderAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/BuilderAbstract.php',
        'PhpParser\\BuilderFactory' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/BuilderFactory.php',
        'PhpParser\\Builder\\Class_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Class_.php',
        'PhpParser\\Builder\\Declaration' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Declaration.php',
        'PhpParser\\Builder\\FunctionLike' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php',
        'PhpParser\\Builder\\Function_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Function_.php',
        'PhpParser\\Builder\\Interface_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Interface_.php',
        'PhpParser\\Builder\\Method' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Method.php',
        'PhpParser\\Builder\\Namespace_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php',
        'PhpParser\\Builder\\Param' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Param.php',
        'PhpParser\\Builder\\Property' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Property.php',
        'PhpParser\\Builder\\Trait_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Trait_.php',
        'PhpParser\\Builder\\Use_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Use_.php',
        'PhpParser\\Comment' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Comment.php',
        'PhpParser\\Comment\\Doc' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Comment/Doc.php',
        'PhpParser\\Error' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Error.php',
        'PhpParser\\ErrorHandler' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ErrorHandler.php',
        'PhpParser\\ErrorHandler\\Collecting' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php',
        'PhpParser\\ErrorHandler\\Throwing' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php',
        'PhpParser\\Lexer' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer.php',
        'PhpParser\\Lexer\\Emulative' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php',
        'PhpParser\\Node' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node.php',
        'PhpParser\\NodeAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeAbstract.php',
        'PhpParser\\NodeDumper' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeDumper.php',
        'PhpParser\\NodeTraverser' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeTraverser.php',
        'PhpParser\\NodeTraverserInterface' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php',
        'PhpParser\\NodeVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor.php',
        'PhpParser\\NodeVisitorAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php',
        'PhpParser\\NodeVisitor\\NameResolver' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php',
        'PhpParser\\Node\\Arg' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Arg.php',
        'PhpParser\\Node\\Const_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Const_.php',
        'PhpParser\\Node\\Expr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr.php',
        'PhpParser\\Node\\Expr\\ArrayDimFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php',
        'PhpParser\\Node\\Expr\\ArrayItem' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php',
        'PhpParser\\Node\\Expr\\Array_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php',
        'PhpParser\\Node\\Expr\\Assign' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php',
        'PhpParser\\Node\\Expr\\AssignOp' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php',
        'PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php',
        'PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php',
        'PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php',
        'PhpParser\\Node\\Expr\\AssignOp\\Concat' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php',
        'PhpParser\\Node\\Expr\\AssignOp\\Div' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php',
        'PhpParser\\Node\\Expr\\AssignOp\\Minus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php',
        'PhpParser\\Node\\Expr\\AssignOp\\Mod' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php',
        'PhpParser\\Node\\Expr\\AssignOp\\Mul' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php',
        'PhpParser\\Node\\Expr\\AssignOp\\Plus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php',
        'PhpParser\\Node\\Expr\\AssignOp\\Pow' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php',
        'PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php',
        'PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php',
        'PhpParser\\Node\\Expr\\AssignRef' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php',
        'PhpParser\\Node\\Expr\\BinaryOp' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\Coalesce' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\Concat' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\Div' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\Equal' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\Greater' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\Identical' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\Minus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\Mod' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\Mul' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\Plus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\Pow' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php',
        'PhpParser\\Node\\Expr\\BinaryOp\\Spaceship' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php',
        'PhpParser\\Node\\Expr\\BitwiseNot' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php',
        'PhpParser\\Node\\Expr\\BooleanNot' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php',
        'PhpParser\\Node\\Expr\\Cast' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php',
        'PhpParser\\Node\\Expr\\Cast\\Array_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php',
        'PhpParser\\Node\\Expr\\Cast\\Bool_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php',
        'PhpParser\\Node\\Expr\\Cast\\Double' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php',
        'PhpParser\\Node\\Expr\\Cast\\Int_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php',
        'PhpParser\\Node\\Expr\\Cast\\Object_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php',
        'PhpParser\\Node\\Expr\\Cast\\String_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php',
        'PhpParser\\Node\\Expr\\Cast\\Unset_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php',
        'PhpParser\\Node\\Expr\\ClassConstFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php',
        'PhpParser\\Node\\Expr\\Clone_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php',
        'PhpParser\\Node\\Expr\\Closure' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php',
        'PhpParser\\Node\\Expr\\ClosureUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php',
        'PhpParser\\Node\\Expr\\ConstFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php',
        'PhpParser\\Node\\Expr\\Empty_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php',
        'PhpParser\\Node\\Expr\\Error' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php',
        'PhpParser\\Node\\Expr\\ErrorSuppress' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php',
        'PhpParser\\Node\\Expr\\Eval_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php',
        'PhpParser\\Node\\Expr\\Exit_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php',
        'PhpParser\\Node\\Expr\\FuncCall' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php',
        'PhpParser\\Node\\Expr\\Include_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php',
        'PhpParser\\Node\\Expr\\Instanceof_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php',
        'PhpParser\\Node\\Expr\\Isset_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php',
        'PhpParser\\Node\\Expr\\List_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php',
        'PhpParser\\Node\\Expr\\MethodCall' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php',
        'PhpParser\\Node\\Expr\\New_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php',
        'PhpParser\\Node\\Expr\\PostDec' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php',
        'PhpParser\\Node\\Expr\\PostInc' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php',
        'PhpParser\\Node\\Expr\\PreDec' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php',
        'PhpParser\\Node\\Expr\\PreInc' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php',
        'PhpParser\\Node\\Expr\\Print_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php',
        'PhpParser\\Node\\Expr\\PropertyFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php',
        'PhpParser\\Node\\Expr\\ShellExec' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php',
        'PhpParser\\Node\\Expr\\StaticCall' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php',
        'PhpParser\\Node\\Expr\\StaticPropertyFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php',
        'PhpParser\\Node\\Expr\\Ternary' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php',
        'PhpParser\\Node\\Expr\\UnaryMinus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php',
        'PhpParser\\Node\\Expr\\UnaryPlus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php',
        'PhpParser\\Node\\Expr\\Variable' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php',
        'PhpParser\\Node\\Expr\\YieldFrom' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php',
        'PhpParser\\Node\\Expr\\Yield_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php',
        'PhpParser\\Node\\FunctionLike' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php',
        'PhpParser\\Node\\Name' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Name.php',
        'PhpParser\\Node\\Name\\FullyQualified' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php',
        'PhpParser\\Node\\Name\\Relative' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php',
        'PhpParser\\Node\\NullableType' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/NullableType.php',
        'PhpParser\\Node\\Param' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Param.php',
        'PhpParser\\Node\\Scalar' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar.php',
        'PhpParser\\Node\\Scalar\\DNumber' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php',
        'PhpParser\\Node\\Scalar\\Encapsed' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php',
        'PhpParser\\Node\\Scalar\\EncapsedStringPart' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php',
        'PhpParser\\Node\\Scalar\\LNumber' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php',
        'PhpParser\\Node\\Scalar\\MagicConst' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php',
        'PhpParser\\Node\\Scalar\\MagicConst\\Class_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php',
        'PhpParser\\Node\\Scalar\\MagicConst\\Dir' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php',
        'PhpParser\\Node\\Scalar\\MagicConst\\File' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php',
        'PhpParser\\Node\\Scalar\\MagicConst\\Function_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php',
        'PhpParser\\Node\\Scalar\\MagicConst\\Line' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php',
        'PhpParser\\Node\\Scalar\\MagicConst\\Method' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php',
        'PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php',
        'PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php',
        'PhpParser\\Node\\Scalar\\String_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php',
        'PhpParser\\Node\\Stmt' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt.php',
        'PhpParser\\Node\\Stmt\\Break_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php',
        'PhpParser\\Node\\Stmt\\Case_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php',
        'PhpParser\\Node\\Stmt\\Catch_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php',
        'PhpParser\\Node\\Stmt\\ClassConst' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php',
        'PhpParser\\Node\\Stmt\\ClassLike' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php',
        'PhpParser\\Node\\Stmt\\ClassMethod' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php',
        'PhpParser\\Node\\Stmt\\Class_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php',
        'PhpParser\\Node\\Stmt\\Const_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php',
        'PhpParser\\Node\\Stmt\\Continue_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php',
        'PhpParser\\Node\\Stmt\\DeclareDeclare' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php',
        'PhpParser\\Node\\Stmt\\Declare_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php',
        'PhpParser\\Node\\Stmt\\Do_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php',
        'PhpParser\\Node\\Stmt\\Echo_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php',
        'PhpParser\\Node\\Stmt\\ElseIf_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php',
        'PhpParser\\Node\\Stmt\\Else_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php',
        'PhpParser\\Node\\Stmt\\Finally_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php',
        'PhpParser\\Node\\Stmt\\For_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php',
        'PhpParser\\Node\\Stmt\\Foreach_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php',
        'PhpParser\\Node\\Stmt\\Function_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php',
        'PhpParser\\Node\\Stmt\\Global_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php',
        'PhpParser\\Node\\Stmt\\Goto_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php',
        'PhpParser\\Node\\Stmt\\GroupUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php',
        'PhpParser\\Node\\Stmt\\HaltCompiler' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php',
        'PhpParser\\Node\\Stmt\\If_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php',
        'PhpParser\\Node\\Stmt\\InlineHTML' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php',
        'PhpParser\\Node\\Stmt\\Interface_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php',
        'PhpParser\\Node\\Stmt\\Label' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php',
        'PhpParser\\Node\\Stmt\\Namespace_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php',
        'PhpParser\\Node\\Stmt\\Nop' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php',
        'PhpParser\\Node\\Stmt\\Property' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php',
        'PhpParser\\Node\\Stmt\\PropertyProperty' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php',
        'PhpParser\\Node\\Stmt\\Return_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php',
        'PhpParser\\Node\\Stmt\\StaticVar' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php',
        'PhpParser\\Node\\Stmt\\Static_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php',
        'PhpParser\\Node\\Stmt\\Switch_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php',
        'PhpParser\\Node\\Stmt\\Throw_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php',
        'PhpParser\\Node\\Stmt\\TraitUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php',
        'PhpParser\\Node\\Stmt\\TraitUseAdaptation' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php',
        'PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Alias' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php',
        'PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Precedence' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php',
        'PhpParser\\Node\\Stmt\\Trait_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php',
        'PhpParser\\Node\\Stmt\\TryCatch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php',
        'PhpParser\\Node\\Stmt\\Unset_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php',
        'PhpParser\\Node\\Stmt\\UseUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php',
        'PhpParser\\Node\\Stmt\\Use_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php',
        'PhpParser\\Node\\Stmt\\While_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php',
        'PhpParser\\Parser' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser.php',
        'PhpParser\\ParserAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ParserAbstract.php',
        'PhpParser\\ParserFactory' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ParserFactory.php',
        'PhpParser\\Parser\\Multiple' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser/Multiple.php',
        'PhpParser\\Parser\\Php5' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser/Php5.php',
        'PhpParser\\Parser\\Php7' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser/Php7.php',
        'PhpParser\\Parser\\Tokens' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser/Tokens.php',
        'PhpParser\\PrettyPrinterAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php',
        'PhpParser\\PrettyPrinter\\Standard' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php',
        'PhpParser\\Serializer' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Serializer.php',
        'PhpParser\\Serializer\\XML' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Serializer/XML.php',
        'PhpParser\\Unserializer' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Unserializer.php',
        'PhpParser\\Unserializer\\XML' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Unserializer/XML.php',
    );

    public static function getInitializer(ClassLoader $loader)
    {
        return \Closure::bind(function () use ($loader) {
            $loader->prefixLengthsPsr4 = ComposerStaticInit125b023f43356e6992e24cd9f1067aeb::$prefixLengthsPsr4;
            $loader->prefixDirsPsr4 = ComposerStaticInit125b023f43356e6992e24cd9f1067aeb::$prefixDirsPsr4;
            $loader->fallbackDirsPsr0 = ComposerStaticInit125b023f43356e6992e24cd9f1067aeb::$fallbackDirsPsr0;
            $loader->classMap = ComposerStaticInit125b023f43356e6992e24cd9f1067aeb::$classMap;

        }, null, ClassLoader::class);
    }
}
[
    {
        "name": "ocramius/package-versions",
        "version": "1.2.0",
        "version_normalized": "1.2.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/Ocramius/PackageVersions.git",
            "reference": "ad8a245decad4897cc6b432743913dad0d69753c"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/ad8a245decad4897cc6b432743913dad0d69753c",
            "reference": "ad8a245decad4897cc6b432743913dad0d69753c",
            "shasum": ""
        },
        "require": {
            "composer-plugin-api": "^1.0",
            "php": "~7.0"
        },
        "require-dev": {
            "composer/composer": "^1.3",
            "ext-zip": "*",
            "humbug/humbug": "dev-master",
            "phpunit/phpunit": "^6.4"
        },
        "time": "2017-11-24T11:07:03+00:00",
        "type": "composer-plugin",
        "extra": {
            "class": "PackageVersions\\Installer",
            "branch-alias": {
                "dev-master": "2.0.x-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "psr-4": {
                "PackageVersions\\": "src/PackageVersions"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Marco Pivetta",
                "email": "ocramius@gmail.com"
            }
        ],
        "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)"
    },
    {
        "name": "phpstan/phpdoc-parser",
        "version": "0.2",
        "version_normalized": "0.2.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/phpstan/phpdoc-parser.git",
            "reference": "02f909f134fe06f0cd4790d8627ee24efbe84d6a"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/02f909f134fe06f0cd4790d8627ee24efbe84d6a",
            "reference": "02f909f134fe06f0cd4790d8627ee24efbe84d6a",
            "shasum": ""
        },
        "require": {
            "php": "~7.0"
        },
        "require-dev": {
            "consistence/coding-standard": "^2.0.0",
            "jakub-onderka/php-parallel-lint": "^0.9.2",
            "phing/phing": "^2.16.0",
            "phpstan/phpstan": "^0.9",
            "phpunit/phpunit": "^6.3",
            "slevomat/coding-standard": "^3.3.0"
        },
        "time": "2018-01-13T18:19:41+00:00",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "0.1-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "psr-4": {
                "PHPStan\\PhpDocParser\\": [
                    "src/"
                ]
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "description": "PHPDoc parser with support for nullable, intersection and generic types"
    },
    {
        "name": "nette/utils",
        "version": "v2.4.8",
        "version_normalized": "2.4.8.0",
        "source": {
            "type": "git",
            "url": "https://github.com/nette/utils.git",
            "reference": "f1584033b5af945b470533b466b81a789d532034"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/nette/utils/zipball/f1584033b5af945b470533b466b81a789d532034",
            "reference": "f1584033b5af945b470533b466b81a789d532034",
            "shasum": ""
        },
        "require": {
            "php": ">=5.6.0"
        },
        "conflict": {
            "nette/nette": "<2.2"
        },
        "require-dev": {
            "nette/tester": "~2.0",
            "tracy/tracy": "^2.3"
        },
        "suggest": {
            "ext-gd": "to use Image",
            "ext-iconv": "to use Strings::webalize() and toAscii()",
            "ext-intl": "for script transliteration in Strings::webalize() and toAscii()",
            "ext-json": "to use Nette\\Utils\\Json",
            "ext-mbstring": "to use Strings::lower() etc...",
            "ext-xml": "to use Strings::length() etc. when mbstring is not available"
        },
        "time": "2017-08-20T17:32:29+00:00",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.4-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "classmap": [
                "src/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause",
            "GPL-2.0",
            "GPL-3.0"
        ],
        "authors": [
            {
                "name": "David Grudl",
                "homepage": "https://davidgrudl.com"
            },
            {
                "name": "Nette Community",
                "homepage": "https://nette.org/contributors"
            }
        ],
        "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.",
        "homepage": "https://nette.org",
        "keywords": [
            "array",
            "core",
            "datetime",
            "images",
            "json",
            "nette",
            "paginator",
            "password",
            "slugify",
            "string",
            "unicode",
            "utf-8",
            "utility",
            "validation"
        ]
    },
    {
        "name": "nette/php-generator",
        "version": "v3.0.1",
        "version_normalized": "3.0.1.0",
        "source": {
            "type": "git",
            "url": "https://github.com/nette/php-generator.git",
            "reference": "eb2dbc9c3409e9db40568109ca4994d51373b60c"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/nette/php-generator/zipball/eb2dbc9c3409e9db40568109ca4994d51373b60c",
            "reference": "eb2dbc9c3409e9db40568109ca4994d51373b60c",
            "shasum": ""
        },
        "require": {
            "nette/utils": "^2.4.2 || ~3.0.0",
            "php": ">=7.0"
        },
        "conflict": {
            "nette/nette": "<2.2"
        },
        "require-dev": {
            "nette/tester": "^2.0",
            "tracy/tracy": "^2.3"
        },
        "time": "2017-07-11T19:07:13+00:00",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "3.0-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "classmap": [
                "src/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause",
            "GPL-2.0",
            "GPL-3.0"
        ],
        "authors": [
            {
                "name": "David Grudl",
                "homepage": "https://davidgrudl.com"
            },
            {
                "name": "Nette Community",
                "homepage": "https://nette.org/contributors"
            }
        ],
        "description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 7.1 features.",
        "homepage": "https://nette.org",
        "keywords": [
            "code",
            "nette",
            "php",
            "scaffolding"
        ]
    },
    {
        "name": "nette/neon",
        "version": "v2.4.2",
        "version_normalized": "2.4.2.0",
        "source": {
            "type": "git",
            "url": "https://github.com/nette/neon.git",
            "reference": "9eacd50553b26b53a3977bfb2fea2166d4331622"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/nette/neon/zipball/9eacd50553b26b53a3977bfb2fea2166d4331622",
            "reference": "9eacd50553b26b53a3977bfb2fea2166d4331622",
            "shasum": ""
        },
        "require": {
            "ext-iconv": "*",
            "ext-json": "*",
            "php": ">=5.6.0"
        },
        "require-dev": {
            "nette/tester": "~2.0",
            "tracy/tracy": "^2.3"
        },
        "time": "2017-07-11T18:29:08+00:00",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.4-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "classmap": [
                "src/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause",
            "GPL-2.0",
            "GPL-3.0"
        ],
        "authors": [
            {
                "name": "David Grudl",
                "homepage": "https://davidgrudl.com"
            },
            {
                "name": "Nette Community",
                "homepage": "https://nette.org/contributors"
            }
        ],
        "description": "Nette NEON: parser & generator for Nette Object Notation",
        "homepage": "http://ne-on.org"
    },
    {
        "name": "nette/di",
        "version": "v2.4.10",
        "version_normalized": "2.4.10.0",
        "source": {
            "type": "git",
            "url": "https://github.com/nette/di.git",
            "reference": "a4b3be935b755f23aebea1ce33d7e3c832cdff98"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/nette/di/zipball/a4b3be935b755f23aebea1ce33d7e3c832cdff98",
            "reference": "a4b3be935b755f23aebea1ce33d7e3c832cdff98",
            "shasum": ""
        },
        "require": {
            "ext-tokenizer": "*",
            "nette/neon": "^2.3.3 || ~3.0.0",
            "nette/php-generator": "^2.6.1 || ~3.0.0",
            "nette/utils": "^2.4.3 || ~3.0.0",
            "php": ">=5.6.0"
        },
        "conflict": {
            "nette/bootstrap": "<2.4",
            "nette/nette": "<2.2"
        },
        "require-dev": {
            "nette/tester": "^2.0",
            "tracy/tracy": "^2.3"
        },
        "time": "2017-08-31T22:42:00+00:00",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.4-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "classmap": [
                "src/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause",
            "GPL-2.0",
            "GPL-3.0"
        ],
        "authors": [
            {
                "name": "David Grudl",
                "homepage": "https://davidgrudl.com"
            },
            {
                "name": "Nette Community",
                "homepage": "https://nette.org/contributors"
            }
        ],
        "description": "💎 Nette Dependency Injection Container: Flexible, compiled and full-featured DIC with perfectly usable autowiring and support for all new PHP 7.1 features.",
        "homepage": "https://nette.org",
        "keywords": [
            "compiled",
            "di",
            "dic",
            "factory",
            "ioc",
            "nette",
            "static"
        ]
    },
    {
        "name": "nette/bootstrap",
        "version": "v2.4.5",
        "version_normalized": "2.4.5.0",
        "source": {
            "type": "git",
            "url": "https://github.com/nette/bootstrap.git",
            "reference": "804925787764d708a7782ea0d9382a310bb21968"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/nette/bootstrap/zipball/804925787764d708a7782ea0d9382a310bb21968",
            "reference": "804925787764d708a7782ea0d9382a310bb21968",
            "shasum": ""
        },
        "require": {
            "nette/di": "~2.4.7",
            "nette/utils": "~2.4",
            "php": ">=5.6.0"
        },
        "conflict": {
            "nette/nette": "<2.2"
        },
        "require-dev": {
            "latte/latte": "~2.2",
            "nette/application": "~2.3",
            "nette/caching": "~2.3",
            "nette/database": "~2.3",
            "nette/forms": "~2.3",
            "nette/http": "~2.4.0",
            "nette/mail": "~2.3",
            "nette/robot-loader": "^2.4.2 || ^3.0",
            "nette/safe-stream": "~2.2",
            "nette/security": "~2.3",
            "nette/tester": "~2.0",
            "tracy/tracy": "^2.4.1"
        },
        "suggest": {
            "nette/robot-loader": "to use Configurator::createRobotLoader()",
            "tracy/tracy": "to use Configurator::enableTracy()"
        },
        "time": "2017-08-20T17:36:59+00:00",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.4-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "classmap": [
                "src/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause",
            "GPL-2.0",
            "GPL-3.0"
        ],
        "authors": [
            {
                "name": "David Grudl",
                "homepage": "https://davidgrudl.com"
            },
            {
                "name": "Nette Community",
                "homepage": "https://nette.org/contributors"
            }
        ],
        "description": "🅱 Nette Bootstrap: the simple way to configure and bootstrap your Nette application.",
        "homepage": "https://nette.org",
        "keywords": [
            "bootstrapping",
            "configurator",
            "nette"
        ]
    },
    {
        "name": "nette/finder",
        "version": "v2.4.1",
        "version_normalized": "2.4.1.0",
        "source": {
            "type": "git",
            "url": "https://github.com/nette/finder.git",
            "reference": "4d43a66d072c57d585bf08a3ef68d3587f7e9547"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/nette/finder/zipball/4d43a66d072c57d585bf08a3ef68d3587f7e9547",
            "reference": "4d43a66d072c57d585bf08a3ef68d3587f7e9547",
            "shasum": ""
        },
        "require": {
            "nette/utils": "^2.4 || ~3.0.0",
            "php": ">=5.6.0"
        },
        "conflict": {
            "nette/nette": "<2.2"
        },
        "require-dev": {
            "nette/tester": "^2.0",
            "tracy/tracy": "^2.3"
        },
        "time": "2017-07-10T23:47:08+00:00",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.4-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "classmap": [
                "src/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause",
            "GPL-2.0",
            "GPL-3.0"
        ],
        "authors": [
            {
                "name": "David Grudl",
                "homepage": "https://davidgrudl.com"
            },
            {
                "name": "Nette Community",
                "homepage": "https://nette.org/contributors"
            }
        ],
        "description": "Nette Finder: Files Searching",
        "homepage": "https://nette.org"
    },
    {
        "name": "nette/robot-loader",
        "version": "v3.0.2",
        "version_normalized": "3.0.2.0",
        "source": {
            "type": "git",
            "url": "https://github.com/nette/robot-loader.git",
            "reference": "b703b4f5955831b0bcaacbd2f6af76021b056826"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/nette/robot-loader/zipball/b703b4f5955831b0bcaacbd2f6af76021b056826",
            "reference": "b703b4f5955831b0bcaacbd2f6af76021b056826",
            "shasum": ""
        },
        "require": {
            "ext-tokenizer": "*",
            "nette/finder": "^2.3 || ^3.0",
            "nette/utils": "^2.4 || ^3.0",
            "php": ">=5.6.0"
        },
        "conflict": {
            "nette/nette": "<2.2"
        },
        "require-dev": {
            "nette/tester": "^2.0",
            "tracy/tracy": "^2.3"
        },
        "time": "2017-07-18T00:09:56+00:00",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "3.0-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "classmap": [
                "src/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause",
            "GPL-2.0",
            "GPL-3.0"
        ],
        "authors": [
            {
                "name": "David Grudl",
                "homepage": "https://davidgrudl.com"
            },
            {
                "name": "Nette Community",
                "homepage": "https://nette.org/contributors"
            }
        ],
        "description": "🍀 Nette RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.",
        "homepage": "https://nette.org",
        "keywords": [
            "autoload",
            "class",
            "interface",
            "nette",
            "trait"
        ]
    },
    {
        "name": "nikic/php-parser",
        "version": "v3.1.4",
        "version_normalized": "3.1.4.0",
        "source": {
            "type": "git",
            "url": "https://github.com/nikic/PHP-Parser.git",
            "reference": "e57b3a09784f846411aa7ed664eedb73e3399078"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/e57b3a09784f846411aa7ed664eedb73e3399078",
            "reference": "e57b3a09784f846411aa7ed664eedb73e3399078",
            "shasum": ""
        },
        "require": {
            "ext-tokenizer": "*",
            "php": ">=5.5"
        },
        "require-dev": {
            "phpunit/phpunit": "~4.0|~5.0"
        },
        "time": "2018-01-25T21:31:33+00:00",
        "bin": [
            "bin/php-parse"
        ],
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "3.0-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "psr-4": {
                "PhpParser\\": "lib/PhpParser"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause"
        ],
        "authors": [
            {
                "name": "Nikita Popov"
            }
        ],
        "description": "A PHP parser written in PHP",
        "keywords": [
            "parser",
            "php"
        ]
    },
    {
        "name": "symfony/polyfill-mbstring",
        "version": "v1.6.0",
        "version_normalized": "1.6.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/symfony/polyfill-mbstring.git",
            "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296",
            "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "suggest": {
            "ext-mbstring": "For best performance"
        },
        "time": "2017-10-11T12:05:26+00:00",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "1.6-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "psr-4": {
                "Symfony\\Polyfill\\Mbstring\\": ""
            },
            "files": [
                "bootstrap.php"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Nicolas Grekas",
                "email": "p@tchwork.com"
            },
            {
                "name": "Symfony Community",
                "homepage": "https://symfony.com/contributors"
            }
        ],
        "description": "Symfony polyfill for the Mbstring extension",
        "homepage": "https://symfony.com",
        "keywords": [
            "compatibility",
            "mbstring",
            "polyfill",
            "portable",
            "shim"
        ]
    },
    {
        "name": "jean85/pretty-package-versions",
        "version": "1.1",
        "version_normalized": "1.1.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/Jean85/pretty-package-versions.git",
            "reference": "d457344b6a035ef99236bdda4729ad7eeb233f54"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/d457344b6a035ef99236bdda4729ad7eeb233f54",
            "reference": "d457344b6a035ef99236bdda4729ad7eeb233f54",
            "shasum": ""
        },
        "require": {
            "ocramius/package-versions": "^1.2.0",
            "php": "^7.0"
        },
        "require-dev": {
            "phpunit/phpunit": "^6.0"
        },
        "time": "2018-01-21T13:54:22+00:00",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "1.x-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "psr-4": {
                "Jean85\\": "src/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Alessandro Lai",
                "email": "alessandro.lai85@gmail.com"
            }
        ],
        "description": "A wrapper for ocramius/pretty-package-versions to get pretty versions strings",
        "keywords": [
            "composer",
            "package",
            "release",
            "versions"
        ]
    },
    {
        "name": "netresearch/composer-patches-plugin",
        "version": "1.2.1",
        "version_normalized": "1.2.1.0",
        "source": {
            "type": "git",
            "url": "https://github.com/netresearch/composer-patches-plugin.git",
            "reference": "3a3de792955eb7e6bad2b5e892b63a1f6d9be000"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/netresearch/composer-patches-plugin/zipball/3a3de792955eb7e6bad2b5e892b63a1f6d9be000",
            "reference": "3a3de792955eb7e6bad2b5e892b63a1f6d9be000",
            "shasum": ""
        },
        "require": {
            "composer-plugin-api": "^1.0"
        },
        "require-dev": {
            "composer/composer": "1.*"
        },
        "time": "2016-01-06T11:59:02+00:00",
        "type": "composer-plugin",
        "extra": {
            "class": "Netresearch\\Composer\\Patches\\Plugin",
            "branch-alias": {
                "dev-master": "1.2.x-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "psr-0": {
                "": "src/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "GPL-2.0"
        ],
        "authors": [
            {
                "name": "Christian Opitz",
                "email": "christian.opitz@netresearch.de"
            }
        ],
        "description": "Composer patches plugin",
        "keywords": [
            "composer",
            "patches",
            "plugin"
        ]
    },
    {
        "name": "dg/composer-cleaner",
        "version": "v1.1",
        "version_normalized": "1.1.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/dg/composer-cleaner.git",
            "reference": "417979b0169b2fc28fd05e48ceb20f87a3113d4e"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/dg/composer-cleaner/zipball/417979b0169b2fc28fd05e48ceb20f87a3113d4e",
            "reference": "417979b0169b2fc28fd05e48ceb20f87a3113d4e",
            "shasum": ""
        },
        "require": {
            "composer-plugin-api": "^1.0",
            "php": ">=5.4.0"
        },
        "require-dev": {
            "nette/tester": "^1.7"
        },
        "time": "2017-05-02T12:58:25+00:00",
        "type": "composer-plugin",
        "extra": {
            "class": "DG\\ComposerCleaner\\Plugin"
        },
        "installation-source": "dist",
        "autoload": {
            "classmap": [
                "src/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause"
        ],
        "authors": [
            {
                "name": "David Grudl",
                "homepage": "https://davidgrudl.com"
            }
        ],
        "description": "Victor The Cleaner: removes unnecessary files from vendor directory.",
        "keywords": [
            "composer"
        ]
    },
    {
        "name": "psr/log",
        "version": "1.0.2",
        "version_normalized": "1.0.2.0",
        "source": {
            "type": "git",
            "url": "https://github.com/php-fig/log.git",
            "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
            "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.0"
        },
        "time": "2016-10-10T12:19:37+00:00",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "1.0.x-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "psr-4": {
                "Psr\\Log\\": "Psr/Log/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "PHP-FIG",
                "homepage": "http://www.php-fig.org/"
            }
        ],
        "description": "Common interface for logging libraries",
        "homepage": "https://github.com/php-fig/log",
        "keywords": [
            "log",
            "psr",
            "psr-3"
        ]
    },
    {
        "name": "symfony/debug",
        "version": "v4.0.3",
        "version_normalized": "4.0.3.0",
        "source": {
            "type": "git",
            "url": "https://github.com/symfony/debug.git",
            "reference": "9ae4223a661b56a9abdce144de4886cca37f198f"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/symfony/debug/zipball/9ae4223a661b56a9abdce144de4886cca37f198f",
            "reference": "9ae4223a661b56a9abdce144de4886cca37f198f",
            "shasum": ""
        },
        "require": {
            "php": "^7.1.3",
            "psr/log": "~1.0"
        },
        "conflict": {
            "symfony/http-kernel": "<3.4"
        },
        "require-dev": {
            "symfony/http-kernel": "~3.4|~4.0"
        },
        "time": "2018-01-03T17:15:19+00:00",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "4.0-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "psr-4": {
                "Symfony\\Component\\Debug\\": ""
            },
            "exclude-from-classmap": [
                "/Tests/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Fabien Potencier",
                "email": "fabien@symfony.com"
            },
            {
                "name": "Symfony Community",
                "homepage": "https://symfony.com/contributors"
            }
        ],
        "description": "Symfony Debug Component",
        "homepage": "https://symfony.com"
    },
    {
        "name": "symfony/console",
        "version": "v3.4.3",
        "version_normalized": "3.4.3.0",
        "source": {
            "type": "git",
            "url": "https://github.com/symfony/console.git",
            "reference": "8394c8ef121949e8f858f13bc1e34f05169e4e7d"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/symfony/console/zipball/8394c8ef121949e8f858f13bc1e34f05169e4e7d",
            "reference": "8394c8ef121949e8f858f13bc1e34f05169e4e7d",
            "shasum": ""
        },
        "require": {
            "php": "^5.5.9|>=7.0.8",
            "symfony/debug": "~2.8|~3.0|~4.0",
            "symfony/polyfill-mbstring": "~1.0"
        },
        "conflict": {
            "symfony/dependency-injection": "<3.4",
            "symfony/process": "<3.3"
        },
        "require-dev": {
            "psr/log": "~1.0",
            "symfony/config": "~3.3|~4.0",
            "symfony/dependency-injection": "~3.4|~4.0",
            "symfony/event-dispatcher": "~2.8|~3.0|~4.0",
            "symfony/lock": "~3.4|~4.0",
            "symfony/process": "~3.3|~4.0"
        },
        "suggest": {
            "psr/log": "For using the console logger",
            "symfony/event-dispatcher": "",
            "symfony/lock": "",
            "symfony/process": ""
        },
        "time": "2018-01-03T07:37:34+00:00",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "3.4-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "psr-4": {
                "Symfony\\Component\\Console\\": ""
            },
            "exclude-from-classmap": [
                "/Tests/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Fabien Potencier",
                "email": "fabien@symfony.com"
            },
            {
                "name": "Symfony Community",
                "homepage": "https://symfony.com/contributors"
            }
        ],
        "description": "Symfony Console Component",
        "homepage": "https://symfony.com"
    },
    {
        "name": "phpstan/package-patches",
        "version": "1.0.0",
        "version_normalized": "1.0.0.0",
        "require": {
            "netresearch/composer-patches-plugin": "~1.0"
        },
        "type": "metapackage",
        "extra": {
            "patches": {
                "nette/di": [
                    {
                        "title": "Fixed including of paths with scheme in config loader",
                        "url": "/Users/ondrej/Development/phpstan-compiler/src/Compiler/../../patches/nette/di/include-scheme.patch"
                    }
                ]
            }
        }
    },
    {
        "name": "symfony/finder",
        "version": "v3.4.3",
        "version_normalized": "3.4.3.0",
        "source": {
            "type": "git",
            "url": "https://github.com/symfony/finder.git",
            "reference": "613e26310776f49a1773b6737c6bd554b8bc8c6f"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/symfony/finder/zipball/613e26310776f49a1773b6737c6bd554b8bc8c6f",
            "reference": "613e26310776f49a1773b6737c6bd554b8bc8c6f",
            "shasum": ""
        },
        "require": {
            "php": "^5.5.9|>=7.0.8"
        },
        "time": "2018-01-03T07:37:34+00:00",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "3.4-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "psr-4": {
                "Symfony\\Component\\Finder\\": ""
            },
            "exclude-from-classmap": [
                "/Tests/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Fabien Potencier",
                "email": "fabien@symfony.com"
            },
            {
                "name": "Symfony Community",
                "homepage": "https://symfony.com/contributors"
            }
        ],
        "description": "Symfony Finder Component",
        "homepage": "https://symfony.com"
    }
]
{
    "name": "jean85/pretty-package-versions",
    "description": "A wrapper for ocramius/pretty-package-versions to get pretty versions strings",
    "type": "library",
    "require": {
        "php": "^7.0",
        "ocramius/package-versions": "^1.2.0"
    },
    "require-dev": {
        "phpunit/phpunit": "^6.0"
    },
    "license": "MIT",
    "authors": [
        {
            "name": "Alessandro Lai",
            "email": "alessandro.lai85@gmail.com"
        }
    ],
    "support": {
        "issues": "https://github.com/Jean85/pretty-package-versions/issues"
    },
    "keywords": [
        "package",
        "versions",
        "composer",
        "release"
    ],
    "extra": {
        "branch-alias": {
            "dev-master": "1.x-dev"
        }
    },
    "autoload": {
        "psr-4": {
            "Jean85\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests"
        }
    }
}
<?php

namespace PHPStanVendor\Jean85;

class PrettyVersions
{
    const SHORT_COMMIT_LENGTH = 7;

    public static function getVersion(string $packageName): \PHPStanVendor\Jean85\Version
    {
        return new \PHPStanVendor\Jean85\Version($packageName, \PHPStanVendor\PackageVersions\Versions::getVersion($packageName));
    }
}
<?php

namespace PHPStanVendor\Jean85;

class Version
{
    const SHORT_COMMIT_LENGTH = 7;

    /** @var string */
    private $packageName;

    /** @var string */
    private $shortVersion;

    /** @var string */
    private $commitHash;
    
    /** @var bool */
    private $versionIsTagged;

    /**
     * Version constructor.
     * @param string $packageName
     * @param string $version
     */
    public function __construct(string $packageName, string $version)
    {
        $this->packageName = $packageName;
        $splittedVersion = explode('@', $version);
        $this->shortVersion = $splittedVersion[0];
        $this->commitHash = $splittedVersion[1];
        $this->versionIsTagged = preg_match('/[^v\d\.]/', $this->getShortVersion()) === 0;
    }

    public function getPrettyVersion(): string
    {
        if ($this->versionIsTagged) {
            return $this->getShortVersion();
        }

        return $this->getVersionWithShortCommit();
    }

    public function getFullVersion(): string
    {
        return $this->getShortVersion() . '@' . $this->getCommitHash();
    }

    public function getVersionWithShortCommit(): string
    {
        return $this->getShortVersion() . '@' . substr($this->getCommitHash(), 0, self::SHORT_COMMIT_LENGTH);
    }

    public function getPackageName(): string
    {
        return $this->packageName;
    }

    public function getShortVersion(): string
    {
        return $this->shortVersion;
    }

    public function getCommitHash(): string
    {
        return $this->commitHash;
    }
    
    public function __toString(): string
    {
        return $this->getPrettyVersion();
    }
}
{
	"name": "nette/bootstrap",
	"description": "🅱 Nette Bootstrap: the simple way to configure and bootstrap your Nette application.",
	"keywords": ["nette", "configurator", "bootstrapping"],
	"homepage": "https://nette.org",
	"license": ["BSD-3-Clause", "GPL-2.0", "GPL-3.0"],
	"authors": [
		{
			"name": "David Grudl",
			"homepage": "https://davidgrudl.com"
		},
		{
			"name": "Nette Community",
			"homepage": "https://nette.org/contributors"
		}
	],
	"require": {
		"php": ">=5.6.0",
		"nette/di": "~2.4.7",
		"nette/utils": "~2.4"
	},
	"suggest": {
		"nette/robot-loader": "to use Configurator::createRobotLoader()",
		"tracy/tracy": "to use Configurator::enableTracy()"
	},
	"require-dev": {
		"nette/application": "~2.3",
		"nette/caching": "~2.3",
		"nette/database": "~2.3",
		"nette/forms": "~2.3",
		"nette/http": "~2.4.0",
		"nette/mail": "~2.3",
		"nette/robot-loader": "^2.4.2 || ^3.0",
		"nette/safe-stream": "~2.2",
		"nette/security": "~2.3",
		"nette/tester": "~2.0",
		"latte/latte": "~2.2",
		"tracy/tracy": "^2.4.1"
	},
	"conflict": {
		"nette/nette": "<2.2"
	},
	"autoload": {
		"classmap": ["src/"]
	},
	"minimum-stability": "dev",
	"extra": {
		"branch-alias": {
			"dev-master": "2.4-dev"
		}
	}
}
Licenses
========

Good news! You may use Nette Framework under the terms of either
the New BSD License or the GNU General Public License (GPL) version 2 or 3.

The BSD License is recommended for most projects. It is easy to understand and it
places almost no restrictions on what you can do with the framework. If the GPL
fits better to your project, you can use the framework under this license.

You don't have to notify anyone which license you are using. You can freely
use Nette Framework in commercial projects as long as the copyright header
remains intact.

Please be advised that the name "Nette Framework" is a protected trademark and its
usage has some limitations. So please do not use word "Nette" in the name of your
project or top-level domain, and choose a name that stands on its own merits.
If your stuff is good, it will not take long to establish a reputation for yourselves.


New BSD License
---------------

Copyright (c) 2004, 2014 David Grudl (https://davidgrudl.com)
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

	* Redistributions of source code must retain the above copyright notice,
	this list of conditions and the following disclaimer.

	* Redistributions in binary form must reproduce the above copyright notice,
	this list of conditions and the following disclaimer in the documentation
	and/or other materials provided with the distribution.

	* Neither the name of "Nette Framework" nor the names of its contributors
	may be used to endorse or promote products derived from this software
	without specific prior written permission.

This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall the copyright owner or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused and on
any theory of liability, whether in contract, strict liability, or tort
(including negligence or otherwise) arising in any way out of the use of this
software, even if advised of the possibility of such damage.


GNU General Public License
--------------------------

GPL licenses are very very long, so instead of including them here we offer
you URLs with full text:

- [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html)
- [GPL version 3](http://www.gnu.org/licenses/gpl-3.0.html)
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette;


/**
 * Initial system DI container generator.
 */
class Configurator
{
	use \PHPStanVendor\Nette\SmartObject;

	const AUTO = true,
		NONE = false;

	const COOKIE_SECRET = 'nette-debug';

	/** @var callable[]  function (Configurator $sender, DI\Compiler $compiler); Occurs after the compiler is created */
	public $onCompile;

	/** @var array */
	public $defaultExtensions = [
		'php' => \PHPStanVendor\Nette\DI\Extensions\PhpExtension::class,
		'constants' => \PHPStanVendor\Nette\DI\Extensions\ConstantsExtension::class,
		'extensions' => \PHPStanVendor\Nette\DI\Extensions\ExtensionsExtension::class,
		'application' => [\PHPStanVendor\Nette\Bridges\ApplicationDI\ApplicationExtension::class, ['%debugMode%', ['%appDir%'], '%tempDir%/cache']],
		'decorator' => \PHPStanVendor\Nette\DI\Extensions\DecoratorExtension::class,
		'cache' => [\PHPStanVendor\Nette\Bridges\CacheDI\CacheExtension::class, ['%tempDir%']],
		'database' => [\PHPStanVendor\Nette\Bridges\DatabaseDI\DatabaseExtension::class, ['%debugMode%']],
		'di' => [\PHPStanVendor\Nette\DI\Extensions\DIExtension::class, ['%debugMode%']],
		'forms' => \PHPStanVendor\Nette\Bridges\FormsDI\FormsExtension::class,
		'http' => [\PHPStanVendor\Nette\Bridges\HttpDI\HttpExtension::class, ['%consoleMode%']],
		'latte' => [\PHPStanVendor\Nette\Bridges\ApplicationDI\LatteExtension::class, ['%tempDir%/cache/latte', '%debugMode%']],
		'mail' => \PHPStanVendor\Nette\Bridges\MailDI\MailExtension::class,
		'routing' => [\PHPStanVendor\Nette\Bridges\ApplicationDI\RoutingExtension::class, ['%debugMode%']],
		'security' => [\PHPStanVendor\Nette\Bridges\SecurityDI\SecurityExtension::class, ['%debugMode%']],
		'session' => [\PHPStanVendor\Nette\Bridges\HttpDI\SessionExtension::class, ['%debugMode%', '%consoleMode%']],
		'tracy' => [\PHPStanVendor\Tracy\Bridges\Nette\TracyExtension::class, ['%debugMode%', '%consoleMode%']],
		'inject' => \PHPStanVendor\Nette\DI\Extensions\InjectExtension::class,
	];

	/** @var string[] of classes which shouldn't be autowired */
	public $autowireExcludedClasses = [
		'stdClass',
	];

	/** @var array */
	protected $parameters;

	/** @var array */
	protected $dynamicParameters = [];

	/** @var array */
	protected $services = [];

	/** @var array [file|array, section] */
	protected $files = [];


	public function __construct()
	{
		$this->parameters = $this->getDefaultParameters();
	}


	/**
	 * Set parameter %debugMode%.
	 * @param  bool|string|array
	 * @return static
	 */
	public function setDebugMode($value)
	{
		if (is_string($value) || is_array($value)) {
			$value = static::detectDebugMode($value);
		} elseif (!is_bool($value)) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException(sprintf('Value must be either a string, array, or boolean, %s given.', gettype($value)));
		}
		$this->parameters['debugMode'] = $value;
		$this->parameters['productionMode'] = !$this->parameters['debugMode']; // compatibility
		return $this;
	}


	/**
	 * @return bool
	 */
	public function isDebugMode()
	{
		return $this->parameters['debugMode'];
	}


	/**
	 * Sets path to temporary directory.
	 * @param  string
	 * @return static
	 */
	public function setTempDirectory($path)
	{
		$this->parameters['tempDir'] = $path;
		return $this;
	}


	/**
	 * Sets the default timezone.
	 * @param  string
	 * @return static
	 */
	public function setTimeZone($timezone)
	{
		date_default_timezone_set($timezone);
		@ini_set('date.timezone', $timezone); // @ - function may be disabled
		return $this;
	}


	/**
	 * Adds new parameters. The %params% will be expanded.
	 * @return static
	 */
	public function addParameters(array $params)
	{
		$this->parameters = \PHPStanVendor\Nette\DI\Config\Helpers::merge($params, $this->parameters);
		return $this;
	}


	/**
	 * Adds new dynamic parameters.
	 * @return static
	 */
	public function addDynamicParameters(array $params)
	{
		$this->dynamicParameters = $params + $this->dynamicParameters;
		return $this;
	}


	/**
	 * Add instances of services.
	 * @return static
	 */
	public function addServices(array $services)
	{
		$this->services = $services + $this->services;
		return $this;
	}


	/**
	 * @return array
	 */
	protected function getDefaultParameters()
	{
		$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
		$last = end($trace);
		$debugMode = static::detectDebugMode();
		return [
			'appDir' => isset($trace[1]['file']) ? dirname($trace[1]['file']) : null,
			'wwwDir' => isset($last['file']) ? dirname($last['file']) : null,
			'debugMode' => $debugMode,
			'productionMode' => !$debugMode,
			'consoleMode' => PHP_SAPI === 'cli',
		];
	}


	/**
	 * @param  string  error log directory
	 * @param  string  administrator email
	 * @return void
	 */
	public function enableTracy($logDirectory = null, $email = null)
	{
		$this->enableDebugger($logDirectory, $email);
	}


	/**
	 * Alias for enableTracy()
	 * @param  string
	 * @param  string
	 * @return void
	 */
	public function enableDebugger($logDirectory = null, $email = null)
	{
		\PHPStanVendor\Tracy\Debugger::$strictMode = true;
		\PHPStanVendor\Tracy\Debugger::enable(!$this->parameters['debugMode'], $logDirectory, $email);
		\PHPStanVendor\Nette\Bridges\Framework\TracyBridge::initialize();
	}


	/**
	 * @return Nette\Loaders\RobotLoader
	 * @throws Nette\NotSupportedException if RobotLoader is not available
	 */
	public function createRobotLoader()
	{
		if (!class_exists(\PHPStanVendor\Nette\Loaders\RobotLoader::class)) {
			throw new \PHPStanVendor\Nette\NotSupportedException('RobotLoader not found, do you have `nette/robot-loader` package installed?');
		}

		$loader = new \PHPStanVendor\Nette\Loaders\RobotLoader;
		$loader->setTempDirectory($this->getCacheDirectory() . '/Nette.RobotLoader');
		$loader->setAutoRefresh($this->parameters['debugMode']);
		return $loader;
	}


	/**
	 * Adds configuration file.
	 * @param  string|array
	 * @return static
	 */
	public function addConfig($file)
	{
		$section = func_num_args() > 1 ? func_get_arg(1) : null;
		if ($section !== null) {
			trigger_error('Sections in config file are deprecated.', E_USER_DEPRECATED);
		}
		$this->files[] = [$file, $section === self::AUTO ? ($this->parameters['debugMode'] ? 'development' : 'production') : $section];
		return $this;
	}


	/**
	 * Returns system DI container.
	 * @return DI\Container
	 */
	public function createContainer()
	{
		$class = $this->loadContainer();
		$container = new $class($this->dynamicParameters);
		foreach ($this->services as $name => $service) {
			$container->addService($name, $service);
		}
		$container->initialize();
		if (class_exists(\PHPStanVendor\Nette\Environment::class)) {
			\PHPStanVendor\Nette\Environment::setContext($container); // back compatibility
		}
		return $container;
	}


	/**
	 * Loads system DI container class and returns its name.
	 * @return string
	 */
	public function loadContainer()
	{
		$loader = new \PHPStanVendor\Nette\DI\ContainerLoader(
			$this->getCacheDirectory() . '/Nette.Configurator',
			$this->parameters['debugMode']
		);
		$class = $loader->load(
			[$this, 'generateContainer'],
			[$this->parameters, array_keys($this->dynamicParameters), $this->files, PHP_VERSION_ID - PHP_RELEASE_VERSION]
		);
		return $class;
	}


	/**
	 * @return string
	 * @internal
	 */
	public function generateContainer(\PHPStanVendor\Nette\DI\Compiler $compiler)
	{
		$compiler->addConfig(['parameters' => $this->parameters]);
		$compiler->setDynamicParameterNames(array_keys($this->dynamicParameters));

		$loader = $this->createLoader();
		$fileInfo = [];
		foreach ($this->files as $info) {
			if (is_scalar($info[0])) {
				$fileInfo[] = "// source: $info[0] $info[1]";
				$info[0] = $loader->load($info[0], $info[1]);
			}
			$compiler->addConfig($this->fixCompatibility($info[0]));
		}
		$compiler->addDependencies($loader->getDependencies());

		$builder = $compiler->getContainerBuilder();
		$builder->addExcludedClasses($this->autowireExcludedClasses);

		foreach ($this->defaultExtensions as $name => $extension) {
			list($class, $args) = is_string($extension) ? [$extension, []] : $extension;
			if (class_exists($class)) {
				$args = \PHPStanVendor\Nette\DI\Helpers::expand($args, $this->parameters, true);
				$compiler->addExtension($name, (new \ReflectionClass($class))->newInstanceArgs($args));
			}
		}

		$this->onCompile($this, $compiler);

		$classes = $compiler->compile();
		return implode("\n", $fileInfo) . "\n\n" . $classes;
	}


	/**
	 * @return DI\Config\Loader
	 */
	protected function createLoader()
	{
		return new \PHPStanVendor\Nette\DI\Config\Loader;
	}


	/**
	 * @return string
	 */
	protected function getCacheDirectory()
	{
		if (empty($this->parameters['tempDir'])) {
			throw new \PHPStanVendor\Nette\InvalidStateException('Set path to temporary directory using setTempDirectory().');
		}
		$dir = $this->parameters['tempDir'] . '/cache';
		\PHPStanVendor\Nette\Utils\FileSystem::createDir($dir);
		return $dir;
	}


	/**
	 * Back compatibility with < v2.3
	 * @return array
	 */
	protected function fixCompatibility($config)
	{
		if (isset($config['nette']['security']['frames'])) {
			$config['nette']['http']['frames'] = $config['nette']['security']['frames'];
			unset($config['nette']['security']['frames']);
		}
		foreach (['application', 'cache', 'database', 'di' => 'container', 'forms', 'http',
			'latte', 'mail' => 'mailer', 'routing', 'security', 'session', 'tracy' => 'debugger', ] as $new => $old) {
			if (isset($config['nette'][$old])) {
				$new = is_int($new) ? $old : $new;
				if (isset($config[$new])) {
					throw new \PHPStanVendor\Nette\DeprecatedException("You can use (deprecated) section 'nette.$old' or new section '$new', but not both of them.");
				} else {
					trigger_error("Configuration section 'nette.$old' is deprecated, use section '$new' (without 'nette')", E_USER_DEPRECATED);
				}
				$config[$new] = $config['nette'][$old];
				unset($config['nette'][$old]);
			}
		}
		if (isset($config['nette']['xhtml'])) {
			trigger_error("Configuration option 'nette.xhtml' is deprecated, use section 'latte.xhtml' instead.", E_USER_DEPRECATED);
			$config['latte']['xhtml'] = $config['nette']['xhtml'];
			unset($config['nette']['xhtml']);
		}

		if (empty($config['nette'])) {
			unset($config['nette']);
		}
		return $config;
	}


	/********************* tools ****************d*g**/


	/**
	 * Detects debug mode by IP addresses or computer names whitelist detection.
	 * @param  string|array
	 * @return bool
	 */
	public static function detectDebugMode($list = null)
	{
		$addr = isset($_SERVER['REMOTE_ADDR'])
			? $_SERVER['REMOTE_ADDR']
			: php_uname('n');
		$secret = isset($_COOKIE[self::COOKIE_SECRET]) && is_string($_COOKIE[self::COOKIE_SECRET])
			? $_COOKIE[self::COOKIE_SECRET]
			: null;
		$list = is_string($list)
			? preg_split('#[,\s]+#', $list)
			: (array) $list;
		if (!isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !isset($_SERVER['HTTP_FORWARDED'])) {
			$list[] = '127.0.0.1';
			$list[] = '::1';
		}
		return in_array($addr, $list, true) || in_array("$secret@$addr", $list, true);
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Bridges\Framework;


/**
 * Initializes Tracy.
 */
class TracyBridge
{
	use \PHPStanVendor\Nette\StaticClass;

	public static function initialize()
	{
		$blueScreen = \PHPStanVendor\Tracy\Debugger::getBlueScreen();

		if (class_exists(\PHPStanVendor\Nette\Framework::class)) {
			$version = \PHPStanVendor\Nette\Framework::VERSION . (\PHPStanVendor\Nette\Framework::REVISION ? ' (' . \PHPStanVendor\Nette\Framework::REVISION . ')' : '');
			\PHPStanVendor\Tracy\Debugger::getBar()->getPanel('Tracy:info')->data['Nette Framework'] = $version;
			$blueScreen->info[] = "Nette Framework $version";
		}

		$blueScreen->addPanel(function ($e) {
			if ($e instanceof \Latte\CompileException) {
				return [
					'tab' => 'Template',
					'panel' => (preg_match('#\n|\?#', $e->sourceName)
							? ''
							: '<p>'
								. (@is_file($e->sourceName) // @ - may trigger error
									? '<b>File:</b> ' . \PHPStanVendor\Tracy\Helpers::editorLink($e->sourceName, $e->sourceLine)
									: '<b>' . htmlspecialchars($e->sourceName . ($e->sourceLine ? ':' . $e->sourceLine : '')) . '</b>')
								. '</p>')
						. '<pre class=code><div>'
						. \PHPStanVendor\Tracy\BlueScreen::highlightLine(htmlspecialchars($e->sourceCode, ENT_IGNORE, 'UTF-8'), $e->sourceLine)
						. '</div></pre>',
				];
			}
		});

		$blueScreen->addPanel(function ($e) {
			if ($e instanceof \PHPStanVendor\Nette\Neon\Exception && preg_match('#line (\d+)#', $e->getMessage(), $m)
				&& ($trace = \PHPStanVendor\Tracy\Helpers::findTrace($e->getTrace(), '\PHPStanVendor\Nette\Neon\Decoder::decode'))
			) {
				return [
					'tab' => 'NEON',
					'panel' => ($trace2 = \PHPStanVendor\Tracy\Helpers::findTrace($e->getTrace(), '\PHPStanVendor\Nette\DI\Config\Adapters\NeonAdapter::load'))
						? '<p><b>File:</b> ' . \PHPStanVendor\Tracy\Helpers::editorLink($trace2['args'][0], $m[1]) . '</p>'
							. \PHPStanVendor\Tracy\BlueScreen::highlightFile($trace2['args'][0], $m[1])
						: \PHPStanVendor\Tracy\BlueScreen::highlightPhp($trace['args'][0], $m[1]),
				];
			}
		});
	}
}
{
	"name": "nette/di",
	"description": "💎 Nette Dependency Injection Container: Flexible, compiled and full-featured DIC with perfectly usable autowiring and support for all new PHP 7.1 features.",
	"keywords": ["nette", "di", "dic", "ioc", "factory", "compiled", "static"],
	"homepage": "https://nette.org",
	"license": ["BSD-3-Clause", "GPL-2.0", "GPL-3.0"],
	"authors": [
		{
			"name": "David Grudl",
			"homepage": "https://davidgrudl.com"
		},
		{
			"name": "Nette Community",
			"homepage": "https://nette.org/contributors"
		}
	],
	"require": {
		"php": ">=5.6.0",
		"ext-tokenizer": "*",
		"nette/neon": "^2.3.3 || ~3.0.0",
		"nette/php-generator": "^2.6.1 || ~3.0.0",
		"nette/utils": "^2.4.3 || ~3.0.0"
	},
	"require-dev": {
		"nette/tester": "^2.0",
		"tracy/tracy": "^2.3"
	},
	"conflict": {
		"nette/nette": "<2.2",
		"nette/bootstrap": "<2.4"
	},
	"autoload": {
		"classmap": ["src/"]
	},
	"minimum-stability": "dev",
	"extra": {
		"branch-alias": {
			"dev-master": "2.4-dev"
		}
	}
}
Licenses
========

Good news! You may use Nette Framework under the terms of either
the New BSD License or the GNU General Public License (GPL) version 2 or 3.

The BSD License is recommended for most projects. It is easy to understand and it
places almost no restrictions on what you can do with the framework. If the GPL
fits better to your project, you can use the framework under this license.

You don't have to notify anyone which license you are using. You can freely
use Nette Framework in commercial projects as long as the copyright header
remains intact.

Please be advised that the name "Nette Framework" is a protected trademark and its
usage has some limitations. So please do not use word "Nette" in the name of your
project or top-level domain, and choose a name that stands on its own merits.
If your stuff is good, it will not take long to establish a reputation for yourselves.


New BSD License
---------------

Copyright (c) 2004, 2014 David Grudl (https://davidgrudl.com)
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

	* Redistributions of source code must retain the above copyright notice,
	this list of conditions and the following disclaimer.

	* Redistributions in binary form must reproduce the above copyright notice,
	this list of conditions and the following disclaimer in the documentation
	and/or other materials provided with the distribution.

	* Neither the name of "Nette Framework" nor the names of its contributors
	may be used to endorse or promote products derived from this software
	without specific prior written permission.

This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall the copyright owner or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused and on
any theory of liability, whether in contract, strict liability, or tort
(including negligence or otherwise) arising in any way out of the use of this
software, even if advised of the possibility of such damage.


GNU General Public License
--------------------------

GPL licenses are very very long, so instead of including them here we offer
you URLs with full text:

- [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html)
- [GPL version 3](http://www.gnu.org/licenses/gpl-3.0.html)
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Bridges\DITracy;


/**
 * Dependency injection container panel for Debugger Bar.
 */
class ContainerPanel implements \PHPStanVendor\Tracy\IBarPanel
{
	use \PHPStanVendor\Nette\SmartObject;

	/** @var int */
	public static $compilationTime;

	/** @var Nette\DI\Container */
	private $container;

	/** @var int|null */
	private $elapsedTime;


	public function __construct(\PHPStanVendor\Nette\DI\Container $container)
	{
		$this->container = $container;
		$this->elapsedTime = self::$compilationTime ? microtime(true) - self::$compilationTime : null;
	}


	/**
	 * Renders tab.
	 * @return string
	 */
	public function getTab()
	{
		ob_start(function () {});
		$elapsedTime = $this->elapsedTime;
		require __DIR__ . '/templates/ContainerPanel.tab.phtml';
		return ob_get_clean();
	}


	/**
	 * Renders panel.
	 * @return string
	 */
	public function getPanel()
	{
		$container = $this->container;
		$registry = $this->getContainerProperty('registry');
		$file = (new \ReflectionClass($container))->getFileName();
		$tags = [];
		$meta = $this->getContainerProperty('meta');
		$services = $meta[\PHPStanVendor\Nette\DI\Container::SERVICES];
		ksort($services);
		if (isset($meta[\PHPStanVendor\Nette\DI\Container::TAGS])) {
			foreach ($meta[\PHPStanVendor\Nette\DI\Container::TAGS] as $tag => $tmp) {
				foreach ($tmp as $service => $val) {
					$tags[$service][$tag] = $val;
				}
			}
		}

		ob_start(function () {});
		require __DIR__ . '/templates/ContainerPanel.panel.phtml';
		return ob_get_clean();
	}


	private function getContainerProperty($name)
	{
		$prop = (new \ReflectionClass(\PHPStanVendor\Nette\DI\Container::class))->getProperty($name);
		$prop->setAccessible(true);
		return $prop->getValue($this->container);
	}
}
<?php

namespace Nette\Bridges\DITracy;

use Nette;
use Tracy\Dumper;
use Tracy\Helpers;

?>
<style class="tracy-debug">

	#tracy-debug .nette-ContainerPanel .tracy-inner {
		width: 700px;
	}

	#tracy-debug .nette-ContainerPanel table {
		width: 100%;
		white-space: nowrap;
	}

	#tracy-debug .nette-ContainerPanel .created {
		font-weight: bold;
	}

	#tracy-debug .nette-ContainerPanel .yes {
		color: green;
		font-weight: bold;
	}

</style>

<div class="nette-ContainerPanel">
<h1><?= get_class($container) ?></h1>

<div class="tracy-inner">
	<h2>Services</h2>

	<table>
		<thead>
		<tr>
			<th>Name</th>
			<th>Autowired</th>
			<th>Service</th>
			<th>Tags</th>
		</tr>
		</thead>
		<tbody>
		<?php foreach ($services as $name => $type): ?>
		<?php $autowired = !empty($meta[Nette\DI\Container::TYPES][$type][true]) && in_array($name, $meta[Nette\DI\Container::TYPES][$type][true], true) ?>
		<tr>
			<td class="<?= isset($registry[$name]) ? 'created' : '' ?>"><?= htmlspecialchars($name) ?></td>
			<td class="<?= $autowired ? 'yes' : '' ?>"><?= $autowired ? 'yes' : 'no' ?></td>
			<td>
				<?php if (isset($registry[$name]) && !$registry[$name] instanceof Nette\DI\Container): ?>
					<?= Dumper::toHtml($registry[$name], [Dumper::COLLAPSE => true, Dumper::LIVE => true]); ?>
				<?php elseif (isset($registry[$name])): ?>
					<code><?= get_class($registry[$name]) ?></code>
				<?php elseif (is_string($type)): ?>
					<code><?= htmlspecialchars($type) ?></code>
				<?php endif ?>
			</td>
			<td><?php if (isset($tags[$name])) { echo Dumper::toHtml($tags[$name], [Dumper::COLLAPSE => true]); } ?></td>
		</tr>
		<?php endforeach ?>
		</tbody>
	</table>

	<h2>Parameters</h2>

	<div class="nette-ContainerPanel-parameters">
		<?= Dumper::toHtml($container->parameters); ?>
	</div>

	<p>Source: <?= Helpers::editorLink($file) ?></p>
</div>
</div>
<?php

namespace Nette\Bridges\DITracy;


?>
<span title="Dependency Injection Container">
<svg viewBox="0 0 2048 2048"><path fill="#ae7c21" d="m1675 690.55v-125c0-36-4-60-13-71-9-12-26-18-52-18s-43 6-52 17c-8 11-12 36-12 72v910.62c0 37 4 61 12 72 9 11 26 17 52 17s44-6 52-17c9-12 13-36 13-72v-207h243v165c0 86-4 148-12 187-8 38-21 70-39 96-20 28-45 48-77 59-31 11-87 16-170 16-96 0-161-5-196-16-34-11-63-31-86-59-21-26-36-59-45-97-9-39-14-101-14-186v-826.62c0-85 4-147 13-185s25-71 46-97c23-29 54-49 92-60s102-17 189-17c75 0 130 6 164 17s61 30 81 59c19 26 33 59 41 99 8 39 12 101 12 185v84zm-524 1086.6h-254v-1514.6h254zm-1025 0v-1514.6h316c127 0 212 27 257 81 44 53 66 159 66 316v721.62c0 157-22 263-66 317-44 53-130 80-257 80zm388-314v-884.62c0-35-4-58-13-70-9-11-26-17-53-17h-66v1058.6h66c26 0 44-6 53-17 9-12 14-35 14-70z"/>
</svg><span class="tracy-label"><?= $elapsedTime ? sprintf('%0.1f ms', $elapsedTime * 1000) : '' ?></span>
</span>
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI;


/**
 * DI container compiler.
 */
class Compiler
{
	use \PHPStanVendor\Nette\SmartObject;

	/** @var CompilerExtension[] */
	private $extensions = [];

	/** @var ContainerBuilder */
	private $builder;

	/** @var array */
	private $config = [];

	/** @var DependencyChecker */
	private $dependencies;

	/** @var string */
	private $className = 'Container';

	/** @var string[] */
	private $dynamicParams = [];

	/** @var array reserved section names */
	private static $reserved = ['services' => 1, 'parameters' => 1];


	public function __construct(\PHPStanVendor\Nette\DI\ContainerBuilder $builder = null)
	{
		$this->builder = $builder ?: new \PHPStanVendor\Nette\DI\ContainerBuilder;
		$this->dependencies = new \PHPStanVendor\Nette\DI\DependencyChecker;
	}


	/**
	 * Add custom configurator extension.
	 * @param  string|null
	 * @return static
	 */
	public function addExtension($name, \PHPStanVendor\Nette\DI\CompilerExtension $extension)
	{
		if ($name === null) {
			$name = '_' . count($this->extensions);
		} elseif (isset($this->extensions[$name]) || isset(self::$reserved[$name])) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException("Name '$name' is already used or reserved.");
		}
		$this->extensions[$name] = $extension->setCompiler($this, $name);
		return $this;
	}


	/**
	 * @return array
	 */
	public function getExtensions($type = null)
	{
		return $type
			? array_filter($this->extensions, function ($item) use ($type) { return $item instanceof $type; })
			: $this->extensions;
	}


	/**
	 * @return ContainerBuilder
	 */
	public function getContainerBuilder()
	{
		return $this->builder;
	}


	/**
	 * @return static
	 */
	public function setClassName($className)
	{
		$this->className = $className;
		return $this;
	}


	/**
	 * Adds new configuration.
	 * @return static
	 */
	public function addConfig(array $config)
	{
		$this->config = \PHPStanVendor\Nette\DI\Config\Helpers::merge($config, $this->config);
		return $this;
	}


	/**
	 * Adds new configuration from file.
	 * @return static
	 */
	public function loadConfig($file)
	{
		$loader = new \PHPStanVendor\Nette\DI\Config\Loader;
		$this->addConfig($loader->load($file));
		$this->dependencies->add($loader->getDependencies());
		return $this;
	}


	/**
	 * Returns configuration.
	 * @return array
	 */
	public function getConfig()
	{
		return $this->config;
	}


	/**
	 * Sets the names of dynamic parameters.
	 * @return static
	 */
	public function setDynamicParameterNames(array $names)
	{
		$this->dynamicParams = $names;
		return $this;
	}


	/**
	 * Adds dependencies to the list.
	 * @param  array of ReflectionClass|\ReflectionFunctionAbstract|string
	 * @return static
	 */
	public function addDependencies(array $deps)
	{
		$this->dependencies->add(array_filter($deps));
		return $this;
	}


	/**
	 * Exports dependencies.
	 * @return array
	 */
	public function exportDependencies()
	{
		return $this->dependencies->export();
	}


	/**
	 * @return string
	 */
	public function compile()
	{
		if (func_num_args()) {
			trigger_error(__METHOD__ . ' arguments are deprecated, use Compiler::addConfig() and Compiler::setClassName().', E_USER_DEPRECATED);
			$this->config = func_get_arg(0) ?: $this->config;
			$this->className = @func_get_arg(1) ?: $this->className;
		}
		$this->processParameters();
		$this->processExtensions();
		$this->processServices();
		$classes = $this->generateCode();
		return implode("\n\n\n", $classes);
	}


	/** @internal */
	public function processParameters()
	{
		$params = isset($this->config['parameters']) ? $this->config['parameters'] : [];
		foreach ($this->dynamicParams as $key) {
			$params[$key] = array_key_exists($key, $params)
				? \PHPStanVendor\Nette\DI\ContainerBuilder::literal('isset($this->parameters[?]) \? $this->parameters[?] : ?', [$key, $key, $params[$key]])
				: \PHPStanVendor\Nette\DI\ContainerBuilder::literal('$this->parameters[?]', [$key]);
		}
		$this->builder->parameters = \PHPStanVendor\Nette\DI\Helpers::expand($params, $params, true);
	}


	/** @internal */
	public function processExtensions()
	{
		$this->config = \PHPStanVendor\Nette\DI\Helpers::expand(array_diff_key($this->config, self::$reserved), $this->builder->parameters)
			+ array_intersect_key($this->config, self::$reserved);

		foreach ($first = $this->getExtensions(\PHPStanVendor\Nette\DI\Extensions\ExtensionsExtension::class) as $name => $extension) {
			$extension->setConfig(isset($this->config[$name]) ? $this->config[$name] : []);
			$extension->loadConfiguration();
		}

		$last = $this->getExtensions(\PHPStanVendor\Nette\DI\Extensions\InjectExtension::class);
		$this->extensions = array_merge(array_diff_key($this->extensions, $last), $last);

		$extensions = array_diff_key($this->extensions, $first);
		foreach (array_intersect_key($extensions, $this->config) as $name => $extension) {
			$extension->setConfig($this->config[$name] ?: []);
		}

		foreach ($extensions as $extension) {
			$extension->loadConfiguration();
		}

		if ($extra = array_diff_key($this->extensions, $extensions, $first)) {
			$extra = implode("', '", array_keys($extra));
			throw new \PHPStanVendor\Nette\DeprecatedException("Extensions '$extra' were added while container was being compiled.");

		} elseif ($extra = key(array_diff_key($this->config, self::$reserved, $this->extensions))) {
			$hint = \PHPStanVendor\Nette\Utils\ObjectMixin::getSuggestion(array_keys(self::$reserved + $this->extensions), $extra);
			throw new \PHPStanVendor\Nette\InvalidStateException(
				"Found section '$extra' in configuration, but corresponding extension is missing"
				. ($hint ? ", did you mean '$hint'?" : '.')
			);
		}
	}


	/** @internal */
	public function processServices()
	{
		if (isset($this->config['services'])) {
			self::loadDefinitions($this->builder, $this->config['services']);
		}
	}


	/** @internal */
	public function generateCode()
	{
		if (func_num_args()) {
			trigger_error(__METHOD__ . ' arguments are deprecated, use Compiler::setClassName().', E_USER_DEPRECATED);
			$this->className = func_get_arg(0) ?: $this->className;
		}

		$this->builder->prepareClassList();

		foreach ($this->extensions as $extension) {
			$extension->beforeCompile();
			$this->dependencies->add([(new \ReflectionClass($extension))->getFileName()]);
		}

		$generator = new \PHPStanVendor\Nette\DI\PhpGenerator($this->builder);
		$classes = $generator->generate($this->className);
		$classes[0]->addMethod('initialize');
		$this->dependencies->add($this->builder->getDependencies());

		foreach ($this->extensions as $extension) {
			$extension->afterCompile($classes[0]);
		}
		return $classes;
	}


	/********************* tools ****************d*g**/


	/**
	 * Adds service definitions from configuration.
	 * @return void
	 */
	public static function loadDefinitions(\PHPStanVendor\Nette\DI\ContainerBuilder $builder, array $services, $namespace = null)
	{
		$depths = [];
		foreach ($services as $name => $def) {
			$path = [];
			while (\PHPStanVendor\Nette\DI\Config\Helpers::isInheriting($def)) {
				$path[] = $def;
				$def = isset($services[$def[\PHPStanVendor\Nette\DI\Config\Helpers::EXTENDS_KEY]]) ? $services[$def[\PHPStanVendor\Nette\DI\Config\Helpers::EXTENDS_KEY]] : [];
				if (in_array($def, $path, true)) {
					throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Circular reference detected for service '$name'.");
				}
			}
			$depths[$name] = count($path) + preg_match('#^@[\w\\\\]+\z#', $name);
		}
		@array_multisort($depths, $services); // @ may trigger E_NOTICE: Object of class Nette\DI\Statement could not be converted to int

		foreach ($services as $name => $def) {
			if (is_int($name)) {
				$postfix = $def instanceof \PHPStanVendor\Nette\DI\Statement && is_string($def->getEntity()) ? '.' . $def->getEntity() : (is_scalar($def) ? ".$def" : '');
				$name = (count($builder->getDefinitions()) + 1) . preg_replace('#\W+#', '_', $postfix);
			} elseif (preg_match('#^@[\w\\\\]+\z#', $name)) {
				$name = $builder->getByType(substr($name, 1), true);
			} elseif ($namespace) {
				$name = $namespace . '.' . $name;
			}

			if ($def === false) {
				$builder->removeDefinition($name);
				continue;
			}
			if ($namespace) {
				$def = \PHPStanVendor\Nette\DI\Helpers::prefixServiceName($def, $namespace);
			}

			$params = $builder->parameters;
			if (is_array($def) && isset($def['parameters'])) {
				foreach ((array) $def['parameters'] as $k => $v) {
					$v = explode(' ', is_int($k) ? $v : $k);
					$params[end($v)] = $builder::literal('$' . end($v));
				}
			}
			$def = \PHPStanVendor\Nette\DI\Helpers::expand($def, $params);

			if (is_array($def) && !empty($def['alteration']) && !$builder->hasDefinition($name)) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Service '$name': missing original definition for alteration.");
			}

			if (($parent = \PHPStanVendor\Nette\DI\Config\Helpers::takeParent($def)) && $parent !== $name) {
				if ($parent !== \PHPStanVendor\Nette\DI\Config\Helpers::OVERWRITE) {
					trigger_error("Section inheritance $name < $parent is deprecated.", E_USER_DEPRECATED);
				}
				$builder->removeDefinition($name);
				$definition = $builder->addDefinition(
					$name,
					$parent === \PHPStanVendor\Nette\DI\Config\Helpers::OVERWRITE ? null : clone $builder->getDefinition($parent)
				);
			} elseif ($builder->hasDefinition($name)) {
				$definition = $builder->getDefinition($name);
			} else {
				$definition = $builder->addDefinition($name);
			}

			try {
				static::loadDefinition($definition, $def);
			} catch (\Exception $e) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Service '$name': " . $e->getMessage(), 0, $e);
			}
		}
	}


	/**
	 * Parses single service definition from configuration.
	 * @return void
	 */
	public static function loadDefinition(\PHPStanVendor\Nette\DI\ServiceDefinition $definition, $config)
	{
		if ($config === null) {
			return;

		} elseif (is_string($config) && interface_exists($config)) {
			$config = ['class' => null, 'implement' => $config];

		} elseif ($config instanceof \PHPStanVendor\Nette\DI\Statement && is_string($config->getEntity()) && interface_exists($config->getEntity())) {
			$config = ['class' => null, 'implement' => $config->getEntity(), 'factory' => array_shift($config->arguments)];

		} elseif (!is_array($config) || isset($config[0], $config[1])) {
			$config = ['class' => null, 'factory' => $config];
		}

		if (array_key_exists('create', $config)) {
			trigger_error("Key 'create' is deprecated, use 'factory' or 'type' in configuration.", E_USER_DEPRECATED);
			$config['factory'] = $config['create'];
			unset($config['create']);
		}

		$known = ['type', 'class', 'factory', 'arguments', 'setup', 'autowired', 'dynamic', 'inject', 'parameters', 'implement', 'run', 'tags', 'alteration'];
		if ($error = array_diff(array_keys($config), $known)) {
			$hints = array_filter(array_map(function ($error) use ($known) {
				return \PHPStanVendor\Nette\Utils\ObjectMixin::getSuggestion($known, $error);
			}, $error));
			$hint = $hints ? ", did you mean '" . implode("', '", $hints) . "'?" : '.';
			throw new \PHPStanVendor\Nette\InvalidStateException(sprintf("Unknown key '%s' in definition of service$hint", implode("', '", $error)));
		}

		$config = \PHPStanVendor\Nette\DI\Helpers::filterArguments($config);

		if (array_key_exists('class', $config) || array_key_exists('factory', $config)) {
			$definition->setType(null);
			$definition->setFactory(null);
		}

		if (array_key_exists('type', $config)) {
			\PHPStanVendor\Nette\Utils\Validators::assertField($config, 'type', 'string|null');
			$definition->setType($config['type']);
			if (array_key_exists('class', $config)) {
				throw new \PHPStanVendor\Nette\InvalidStateException("Unexpected 'class' when 'type' is used.");
			}
		}

		if (array_key_exists('class', $config)) {
			\PHPStanVendor\Nette\Utils\Validators::assertField($config, 'class', 'string|\PHPStanVendor\Nette\DI\Statement|null');
			if (!$config['class'] instanceof \PHPStanVendor\Nette\DI\Statement) {
				$definition->setType($config['class']);
			}
			$definition->setFactory($config['class']);
		}

		if (array_key_exists('factory', $config)) {
			\PHPStanVendor\Nette\Utils\Validators::assertField($config, 'factory', 'callable|\PHPStanVendor\Nette\DI\Statement|null');
			$definition->setFactory($config['factory']);
		}

		if (array_key_exists('arguments', $config)) {
			\PHPStanVendor\Nette\Utils\Validators::assertField($config, 'arguments', 'array');
			$arguments = $config['arguments'];
			if (!\PHPStanVendor\Nette\DI\Config\Helpers::takeParent($arguments) && !\PHPStanVendor\Nette\Utils\Arrays::isList($arguments) && $definition->getFactory()) {
				$arguments += $definition->getFactory()->arguments;
			}
			$definition->setArguments($arguments);
		}

		if (isset($config['setup'])) {
			if (\PHPStanVendor\Nette\DI\Config\Helpers::takeParent($config['setup'])) {
				$definition->setSetup([]);
			}
			\PHPStanVendor\Nette\Utils\Validators::assertField($config, 'setup', 'list');
			foreach ($config['setup'] as $id => $setup) {
				\PHPStanVendor\Nette\Utils\Validators::assert($setup, 'callable|\PHPStanVendor\Nette\DI\Statement|array:1', "setup item #$id");
				if (is_array($setup)) {
					$setup = new \PHPStanVendor\Nette\DI\Statement(key($setup), array_values($setup));
				}
				$definition->addSetup($setup);
			}
		}

		if (isset($config['parameters'])) {
			\PHPStanVendor\Nette\Utils\Validators::assertField($config, 'parameters', 'array');
			$definition->setParameters($config['parameters']);
		}

		if (isset($config['implement'])) {
			\PHPStanVendor\Nette\Utils\Validators::assertField($config, 'implement', 'string');
			$definition->setImplement($config['implement']);
			$definition->setAutowired(true);
		}

		if (isset($config['autowired'])) {
			\PHPStanVendor\Nette\Utils\Validators::assertField($config, 'autowired', 'bool|string|array');
			$definition->setAutowired($config['autowired']);
		}

		if (isset($config['dynamic'])) {
			\PHPStanVendor\Nette\Utils\Validators::assertField($config, 'dynamic', 'bool');
			$definition->setDynamic($config['dynamic']);
		}

		if (isset($config['inject'])) {
			\PHPStanVendor\Nette\Utils\Validators::assertField($config, 'inject', 'bool');
			$definition->addTag(\PHPStanVendor\Nette\DI\Extensions\InjectExtension::TAG_INJECT, $config['inject']);
		}

		if (isset($config['run'])) {
			trigger_error("Option 'run' is deprecated, use 'run' as tag.", E_USER_DEPRECATED);
			$config['tags']['run'] = (bool) $config['run'];
		}

		if (isset($config['tags'])) {
			\PHPStanVendor\Nette\Utils\Validators::assertField($config, 'tags', 'array');
			if (\PHPStanVendor\Nette\DI\Config\Helpers::takeParent($config['tags'])) {
				$definition->setTags([]);
			}
			foreach ($config['tags'] as $tag => $attrs) {
				if (is_int($tag) && is_string($attrs)) {
					$definition->addTag($attrs);
				} else {
					$definition->addTag($tag, $attrs);
				}
			}
		}
	}


	/** @deprecated */
	public static function filterArguments(array $args)
	{
		return \PHPStanVendor\Nette\DI\Helpers::filterArguments($args);
	}


	/** @deprecated */
	public static function parseServices(\PHPStanVendor\Nette\DI\ContainerBuilder $builder, array $config, $namespace = null)
	{
		self::loadDefinitions($builder, isset($config['services']) ? $config['services'] : [], $namespace);
	}


	/** @deprecated */
	public static function parseService(\PHPStanVendor\Nette\DI\ServiceDefinition $definition, $config)
	{
		self::loadDefinition($definition, $config);
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI;


/**
 * Configurator compiling extension.
 */
abstract class CompilerExtension
{
	use \PHPStanVendor\Nette\SmartObject;

	/** @var Compiler */
	protected $compiler;

	/** @var string */
	protected $name;

	/** @var array */
	protected $config = [];


	/**
	 * @return static
	 */
	public function setCompiler(\PHPStanVendor\Nette\DI\Compiler $compiler, $name)
	{
		$this->compiler = $compiler;
		$this->name = $name;
		return $this;
	}


	/**
	 * @return static
	 */
	public function setConfig(array $config)
	{
		$this->config = $config;
		return $this;
	}


	/**
	 * Returns extension configuration.
	 * @return array
	 */
	public function getConfig()
	{
		if (func_num_args()) { // deprecated
			return \PHPStanVendor\Nette\DI\Config\Helpers::merge($this->config, $this->getContainerBuilder()->expand(func_get_arg(0)));
		}
		return $this->config;
	}


	/**
	 * Checks whether $config contains only $expected items and returns combined array.
	 * @return array
	 * @throws Nette\InvalidStateException
	 */
	public function validateConfig(array $expected, array $config = null, $name = null)
	{
		if (func_num_args() === 1) {
			return $this->config = $this->validateConfig($expected, $this->config);
		}
		if ($extra = array_diff_key((array) $config, $expected)) {
			$name = $name ?: $this->name;
			$hint = \PHPStanVendor\Nette\Utils\ObjectMixin::getSuggestion(array_keys($expected), key($extra));
			$extra = $hint ? key($extra) : implode(", $name.", array_keys($extra));
			throw new \PHPStanVendor\Nette\InvalidStateException("Unknown configuration option $name.$extra" . ($hint ? ", did you mean $name.$hint?" : '.'));
		}
		return \PHPStanVendor\Nette\DI\Config\Helpers::merge($config, $expected);
	}


	/**
	 * @return ContainerBuilder
	 */
	public function getContainerBuilder()
	{
		return $this->compiler->getContainerBuilder();
	}


	/**
	 * Reads configuration from file.
	 * @param  string  file name
	 * @return array
	 */
	public function loadFromFile($file)
	{
		$loader = new \PHPStanVendor\Nette\DI\Config\Loader;
		$res = $loader->load($file);
		$this->compiler->addDependencies($loader->getDependencies());
		return $res;
	}


	/**
	 * Prepend extension name to identifier or service name.
	 * @param  string
	 * @return string
	 */
	public function prefix($id)
	{
		return substr_replace($id, $this->name . '.', substr($id, 0, 1) === '@' ? 1 : 0, 0);
	}


	/**
	 * Processes configuration data. Intended to be overridden by descendant.
	 * @return void
	 */
	public function loadConfiguration()
	{
	}


	/**
	 * Adjusts DI container before is compiled to PHP class. Intended to be overridden by descendant.
	 * @return void
	 */
	public function beforeCompile()
	{
	}


	/**
	 * Adjusts DI container compiled to PHP class. Intended to be overridden by descendant.
	 * @return void
	 */
	public function afterCompile(\PHPStanVendor\Nette\PhpGenerator\ClassType $class)
	{
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI\Config\Adapters;


/**
 * Reading and generating INI files.
 */
class IniAdapter implements \PHPStanVendor\Nette\DI\Config\IAdapter
{
	use \PHPStanVendor\Nette\SmartObject;

	/** @internal */
	const INHERITING_SEPARATOR = '<', // child < parent
		KEY_SEPARATOR = '.', // key nesting key1.key2.key3
		ESCAPED_KEY_SEPARATOR = '..',
		RAW_SECTION = '!';


	/**
	 * Reads configuration from INI file.
	 * @param  string  file name
	 * @return array
	 * @throws Nette\InvalidStateException
	 */
	public function load($file)
	{
		$ini = @parse_ini_file($file, true); // @ escalated to exception
		if ($ini === false) {
			$error = error_get_last();
			throw new \PHPStanVendor\Nette\InvalidStateException("parse_ini_file(): $error[message]");
		}
		return $this->process($ini);
	}


	/**
	 * @return array
	 * @throws Nette\InvalidStateException
	 */
	public function process(array $arr)
	{
		$data = [];
		foreach ($arr as $secName => $secData) {
			if (is_array($secData)) { // is section?
				if (substr($secName, -1) === self::RAW_SECTION) {
					$secName = substr($secName, 0, -1);
				} else { // process key nesting separator (key1.key2.key3)
					$tmp = [];
					foreach ($secData as $key => $val) {
						$cursor = &$tmp;
						$key = str_replace(self::ESCAPED_KEY_SEPARATOR, "\xFF", $key);
						foreach (explode(self::KEY_SEPARATOR, $key) as $part) {
							$part = str_replace("\xFF", self::KEY_SEPARATOR, $part);
							if (!isset($cursor[$part]) || is_array($cursor[$part])) {
								$cursor = &$cursor[$part];
							} else {
								throw new \PHPStanVendor\Nette\InvalidStateException("Invalid key '$key' in section [$secName].");
							}
						}
						$cursor = $val;
					}
					$secData = $tmp;
				}

				$parts = explode(self::INHERITING_SEPARATOR, $secName);
				if (count($parts) > 1) {
					$secName = trim($parts[0]);
					$secData[\PHPStanVendor\Nette\DI\Config\Helpers::EXTENDS_KEY] = trim($parts[1]);
				}
			}

			$cursor = &$data; // nesting separator in section name
			foreach (explode(self::KEY_SEPARATOR, $secName) as $part) {
				if (!isset($cursor[$part]) || is_array($cursor[$part])) {
					$cursor = &$cursor[$part];
				} else {
					throw new \PHPStanVendor\Nette\InvalidStateException("Invalid section [$secName].");
				}
			}

			if (is_array($secData) && is_array($cursor)) {
				$secData = \PHPStanVendor\Nette\DI\Config\Helpers::merge($secData, $cursor);
			}

			$cursor = $secData;
		}

		return $data;
	}


	/**
	 * Generates configuration in INI format.
	 * @return string
	 */
	public function dump(array $data)
	{
		$output = [];
		foreach ($data as $name => $secData) {
			if (!is_array($secData)) {
				$output = [];
				self::build($data, $output, '');
				break;
			}
			if ($parent = \PHPStanVendor\Nette\DI\Config\Helpers::takeParent($secData)) {
				$output[] = "[$name " . self::INHERITING_SEPARATOR . " $parent]";
			} else {
				$output[] = "[$name]";
			}
			self::build($secData, $output, '');
			$output[] = '';
		}
		return "; generated by \PHPStanVendor\Nette\n\n" . implode(PHP_EOL, $output);
	}


	/**
	 * Recursive builds INI list.
	 * @return void
	 */
	private static function build($input, &$output, $prefix)
	{
		foreach ($input as $key => $val) {
			$key = str_replace(self::KEY_SEPARATOR, self::ESCAPED_KEY_SEPARATOR, $key);
			if (is_array($val)) {
				self::build($val, $output, $prefix . $key . self::KEY_SEPARATOR);

			} elseif (is_bool($val)) {
				$output[] = "$prefix$key = " . ($val ? 'true' : 'false');

			} elseif (is_numeric($val)) {
				$output[] = "$prefix$key = $val";

			} elseif (is_string($val)) {
				$output[] = "$prefix$key = \"$val\"";

			} else {
				throw new \PHPStanVendor\Nette\InvalidArgumentException(sprintf("The '%s' item must be scalar or array, %s given.", $prefix . $key, gettype($val)));
			}
		}
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI\Config\Adapters;


/**
 * Reading and generating NEON files.
 */
class NeonAdapter implements \PHPStanVendor\Nette\DI\Config\IAdapter
{
	use \PHPStanVendor\Nette\SmartObject;

	/** @internal */
	const INHERITING_SEPARATOR = '<', // child < parent
		PREVENT_MERGING = '!';


	/**
	 * Reads configuration from NEON file.
	 * @param  string  file name
	 * @return array
	 */
	public function load($file)
	{
		return $this->process((array) \PHPStanVendor\Nette\Neon\Neon::decode(file_get_contents($file)));
	}


	/**
	 * @return array
	 * @throws Nette\InvalidStateException
	 */
	public function process(array $arr)
	{
		$res = [];
		foreach ($arr as $key => $val) {
			if (is_string($key) && substr($key, -1) === self::PREVENT_MERGING) {
				if (!is_array($val) && $val !== null) {
					throw new \PHPStanVendor\Nette\InvalidStateException("Replacing operator is available only for arrays, item '$key' is not array.");
				}
				$key = substr($key, 0, -1);
				$val[\PHPStanVendor\Nette\DI\Config\Helpers::EXTENDS_KEY] = \PHPStanVendor\Nette\DI\Config\Helpers::OVERWRITE;

			} elseif (is_string($key) && preg_match('#^(\S+)\s+' . self::INHERITING_SEPARATOR . '\s+(\S+)\z#', $key, $matches)) {
				if (!is_array($val) && $val !== null) {
					throw new \PHPStanVendor\Nette\InvalidStateException("Inheritance operator is available only for arrays, item '$key' is not array.");
				}
				list(, $key, $val[\PHPStanVendor\Nette\DI\Config\Helpers::EXTENDS_KEY]) = $matches;
				if (isset($res[$key])) {
					throw new \PHPStanVendor\Nette\InvalidStateException("Duplicated key '$key'.");
				}
			}

			if (is_array($val)) {
				$val = $this->process($val);

			} elseif ($val instanceof \PHPStanVendor\Nette\Neon\Entity) {
				if ($val->value === \PHPStanVendor\Nette\Neon\Neon::CHAIN) {
					$tmp = null;
					foreach ($this->process($val->attributes) as $st) {
						$tmp = new \PHPStanVendor\Nette\DI\Statement(
							$tmp === null ? $st->getEntity() : [$tmp, ltrim($st->getEntity(), ':')],
							$st->arguments
						);
					}
					$val = $tmp;
				} else {
					$tmp = $this->process([$val->value]);
					$val = new \PHPStanVendor\Nette\DI\Statement($tmp[0], $this->process($val->attributes));
				}
			}
			$res[$key] = $val;
		}
		return $res;
	}


	/**
	 * Generates configuration in NEON format.
	 * @return string
	 */
	public function dump(array $data)
	{
		$tmp = [];
		foreach ($data as $name => $secData) {
			if ($parent = \PHPStanVendor\Nette\DI\Config\Helpers::takeParent($secData)) {
				$name .= ' ' . self::INHERITING_SEPARATOR . ' ' . $parent;
			}
			$tmp[$name] = $secData;
		}
		array_walk_recursive(
			$tmp,
			function (&$val) {
				if ($val instanceof \PHPStanVendor\Nette\DI\Statement) {
					$val = self::statementToEntity($val);
				}
			}
		);

		return "# generated by \PHPStanVendor\Nette\n\n" . \PHPStanVendor\Nette\Neon\Neon::encode($tmp, \PHPStanVendor\Nette\Neon\Neon::BLOCK);
	}


	/**
	 * @return Neon\Entity
	 */
	private static function statementToEntity(\PHPStanVendor\Nette\DI\Statement $val)
	{
		array_walk_recursive(
			$val->arguments,
			function (&$val) {
				if ($val instanceof \PHPStanVendor\Nette\DI\Statement) {
					$val = self::statementToEntity($val);
				}
			}
		);
		if (is_array($val->getEntity()) && $val->getEntity()[0] instanceof \PHPStanVendor\Nette\DI\Statement) {
			return new \PHPStanVendor\Nette\Neon\Entity(
				\PHPStanVendor\Nette\Neon\Neon::CHAIN,
				[
					self::statementToEntity($val->getEntity()[0]),
					new \PHPStanVendor\Nette\Neon\Entity('::' . $val->getEntity()[1], $val->arguments),
				]
			);
		} else {
			return new \PHPStanVendor\Nette\Neon\Entity($val->getEntity(), $val->arguments);
		}
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI\Config\Adapters;


/**
 * Reading and generating PHP files.
 */
class PhpAdapter implements \PHPStanVendor\Nette\DI\Config\IAdapter
{
	use \PHPStanVendor\Nette\SmartObject;

	/**
	 * Reads configuration from PHP file.
	 * @param  string  file name
	 * @return array
	 */
	public function load($file)
	{
		return require $file;
	}


	/**
	 * Generates configuration in PHP format.
	 * @return string
	 */
	public function dump(array $data)
	{
		return "<?php // generated by Nette \nreturn " . \PHPStanVendor\Nette\PhpGenerator\Helpers::dump($data) . ';';
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI\Config;


/**
 * Configuration helpers.
 */
class Helpers
{
	use \PHPStanVendor\Nette\StaticClass;

	const
		EXTENDS_KEY = '_extends',
		OVERWRITE = true;


	/**
	 * Merges configurations. Left has higher priority than right one.
	 * @return array|string
	 */
	public static function merge($left, $right)
	{
		if (is_array($left) && is_array($right)) {
			foreach ($left as $key => $val) {
				if (is_int($key)) {
					$right[] = $val;
				} else {
					if (is_array($val) && isset($val[self::EXTENDS_KEY])) {
						if ($val[self::EXTENDS_KEY] === self::OVERWRITE) {
							unset($val[self::EXTENDS_KEY]);
						}
					} elseif (isset($right[$key])) {
						$val = static::merge($val, $right[$key]);
					}
					$right[$key] = $val;
				}
			}
			return $right;

		} elseif ($left === null && is_array($right)) {
			return $right;

		} else {
			return $left;
		}
	}


	/**
	 * Finds out and removes information about the parent.
	 * @return mixed
	 */
	public static function takeParent(&$data)
	{
		if (is_array($data) && isset($data[self::EXTENDS_KEY])) {
			$parent = $data[self::EXTENDS_KEY];
			unset($data[self::EXTENDS_KEY]);
			return $parent;
		}
	}


	/**
	 * @return bool
	 */
	public static function isOverwriting(&$data)
	{
		return is_array($data) && isset($data[self::EXTENDS_KEY]) && $data[self::EXTENDS_KEY] === self::OVERWRITE;
	}


	/**
	 * @return bool
	 */
	public static function isInheriting(&$data)
	{
		return is_array($data) && isset($data[self::EXTENDS_KEY]) && $data[self::EXTENDS_KEY] !== self::OVERWRITE;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI\Config;


/**
 * Adapter for reading and writing configuration files.
 */
interface IAdapter
{

	/**
	 * Reads configuration from file.
	 * @param  string  file name
	 * @return array
	 */
	function load($file);

	/**
	 * Generates configuration string.
	 * @return string
	 */
	function dump(array $data);
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI\Config;


/**
 * Configuration file loader.
 */
class Loader
{
	use \PHPStanVendor\Nette\SmartObject;

	/** @internal */
	const INCLUDES_KEY = 'includes';

	private $adapters = [
		'php' => \PHPStanVendor\Nette\DI\Config\Adapters\PhpAdapter::class,
		'ini' => \PHPStanVendor\Nette\DI\Config\Adapters\IniAdapter::class,
		'neon' => \PHPStanVendor\Nette\DI\Config\Adapters\NeonAdapter::class,
	];

	private $dependencies = [];


	/**
	 * Reads configuration from file.
	 * @param  string  file name
	 * @param  string  optional section to load
	 * @return array
	 */
	public function load($file, $section = null)
	{
		if (!is_file($file) || !is_readable($file)) {
			throw new \PHPStanVendor\Nette\FileNotFoundException("File '$file' is missing or is not readable.");
		}
		$this->dependencies[] = $file;
		$data = $this->getAdapter($file)->load($file);

		if ($section) {
			if (isset($data[self::INCLUDES_KEY])) {
				throw new \PHPStanVendor\Nette\InvalidStateException("Section 'includes' must be placed under some top section in file '$file'.");
			}
			$data = $this->getSection($data, $section, $file);
		}

		// include child files
		$merged = [];
		if (isset($data[self::INCLUDES_KEY])) {
			\PHPStanVendor\Nette\Utils\Validators::assert($data[self::INCLUDES_KEY], 'list', "section 'includes' in file '$file'");
			foreach ($data[self::INCLUDES_KEY] as $include) {
				if (!preg_match('#([a-z]+:)?[/\\\\]#Ai', $include)) {
					$include = dirname($file) . '/' . $include;
				}
				$merged = \PHPStanVendor\Nette\DI\Config\Helpers::merge($this->load($include), $merged);
			}
		}
		unset($data[self::INCLUDES_KEY]);

		return \PHPStanVendor\Nette\DI\Config\Helpers::merge($data, $merged);
	}


	/**
	 * Save configuration to file.
	 * @param  array
	 * @param  string  file
	 * @return void
	 */
	public function save($data, $file)
	{
		if (file_put_contents($file, $this->getAdapter($file)->dump($data)) === false) {
			throw new \PHPStanVendor\Nette\IOException("Cannot write file '$file'.");
		}
	}


	/**
	 * Returns configuration files.
	 * @return array
	 */
	public function getDependencies()
	{
		return array_unique($this->dependencies);
	}


	/**
	 * Registers adapter for given file extension.
	 * @param  string  file extension
	 * @param  string|IAdapter
	 * @return static
	 */
	public function addAdapter($extension, $adapter)
	{
		$this->adapters[strtolower($extension)] = $adapter;
		return $this;
	}


	/** @return IAdapter */
	private function getAdapter($file)
	{
		$extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
		if (!isset($this->adapters[$extension])) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException("Unknown file extension '$file'.");
		}
		return is_object($this->adapters[$extension]) ? $this->adapters[$extension] : new $this->adapters[$extension];
	}


	private function getSection(array $data, $key, $file)
	{
		\PHPStanVendor\Nette\Utils\Validators::assertField($data, $key, 'array|null', "section '%' in file '$file'");
		$item = $data[$key];
		if ($parent = \PHPStanVendor\Nette\DI\Config\Helpers::takeParent($item)) {
			$item = \PHPStanVendor\Nette\DI\Config\Helpers::merge($item, $this->getSection($data, $parent, $file));
		}
		return $item;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI;


/**
 * The dependency injection container default implementation.
 */
class Container
{
	use \PHPStanVendor\Nette\SmartObject;

	const TAGS = 'tags';
	const TYPES = 'types';
	const SERVICES = 'services';
	const ALIASES = 'aliases';

	/** @var array  user parameters */
	public $parameters = [];

	/** @var array[] */
	protected $meta = [];

	/** @var object[]  storage for shared objects */
	private $registry = [];

	/** @var array circular reference detector */
	private $creating;


	public function __construct(array $params = [])
	{
		$this->parameters = $params + $this->parameters;
	}


	/**
	 * @return array
	 */
	public function getParameters()
	{
		return $this->parameters;
	}


	/**
	 * Adds the service to the container.
	 * @param  string
	 * @param  object
	 * @return static
	 */
	public function addService($name, $service)
	{
		if (!is_string($name) || !$name) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException(sprintf('Service name must be a non-empty string, %s given.', gettype($name)));
		}
		$name = isset($this->meta[self::ALIASES][$name]) ? $this->meta[self::ALIASES][$name] : $name;
		if (isset($this->registry[$name])) {
			throw new \PHPStanVendor\Nette\InvalidStateException("Service '$name' already exists.");

		} elseif (!is_object($service)) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException(sprintf("Service '%s' must be a object, %s given.", $name, gettype($service)));

		} elseif (isset($this->meta[self::SERVICES][$name]) && !$service instanceof $this->meta[self::SERVICES][$name]) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException(sprintf("Service '%s' must be instance of %s, %s given.", $name, $this->meta[self::SERVICES][$name], get_class($service)));
		}

		$this->registry[$name] = $service;
		return $this;
	}


	/**
	 * Removes the service from the container.
	 * @param  string
	 * @return void
	 */
	public function removeService($name)
	{
		$name = isset($this->meta[self::ALIASES][$name]) ? $this->meta[self::ALIASES][$name] : $name;
		unset($this->registry[$name]);
	}


	/**
	 * Gets the service object by name.
	 * @param  string
	 * @return object
	 * @throws MissingServiceException
	 */
	public function getService($name)
	{
		if (!isset($this->registry[$name])) {
			if (isset($this->meta[self::ALIASES][$name])) {
				return $this->getService($this->meta[self::ALIASES][$name]);
			}
			$this->registry[$name] = $this->createService($name);
		}
		return $this->registry[$name];
	}


	/**
	 * Gets the service type by name.
	 * @param  string
	 * @return string
	 * @throws MissingServiceException
	 */
	public function getServiceType($name)
	{
		if (isset($this->meta[self::ALIASES][$name])) {
			return $this->getServiceType($this->meta[self::ALIASES][$name]);

		} elseif (isset($this->meta[self::SERVICES][$name])) {
			return $this->meta[self::SERVICES][$name];

		} else {
			throw new \PHPStanVendor\Nette\DI\MissingServiceException("Service '$name' not found.");
		}
	}


	/**
	 * Does the service exist?
	 * @param  string service name
	 * @return bool
	 */
	public function hasService($name)
	{
		$name = isset($this->meta[self::ALIASES][$name]) ? $this->meta[self::ALIASES][$name] : $name;
		return isset($this->registry[$name])
			|| (method_exists($this, $method = self::getMethodName($name))
				&& (new \ReflectionMethod($this, $method))->getName() === $method);
	}


	/**
	 * Is the service created?
	 * @param  string service name
	 * @return bool
	 */
	public function isCreated($name)
	{
		if (!$this->hasService($name)) {
			throw new \PHPStanVendor\Nette\DI\MissingServiceException("Service '$name' not found.");
		}
		$name = isset($this->meta[self::ALIASES][$name]) ? $this->meta[self::ALIASES][$name] : $name;
		return isset($this->registry[$name]);
	}


	/**
	 * Creates new instance of the service.
	 * @param  string service name
	 * @return object
	 * @throws MissingServiceException
	 */
	public function createService($name, array $args = [])
	{
		$name = isset($this->meta[self::ALIASES][$name]) ? $this->meta[self::ALIASES][$name] : $name;
		$method = self::getMethodName($name);
		if (isset($this->creating[$name])) {
			throw new \PHPStanVendor\Nette\InvalidStateException(sprintf('Circular reference detected for services: %s.', implode(', ', array_keys($this->creating))));

		} elseif (!method_exists($this, $method) || (new \ReflectionMethod($this, $method))->getName() !== $method) {
			throw new \PHPStanVendor\Nette\DI\MissingServiceException("Service '$name' not found.");
		}

		try {
			$this->creating[$name] = true;
			$service = $this->$method(...$args);

		} finally {
			unset($this->creating[$name]);
		}

		if (!is_object($service)) {
			throw new \PHPStanVendor\Nette\UnexpectedValueException("Unable to create service '$name', value returned by method $method() is not object.");
		}

		return $service;
	}


	/**
	 * Resolves service by type.
	 * @param  string  class or interface
	 * @param  bool    throw exception if service doesn't exist?
	 * @return object  service or null
	 * @throws MissingServiceException
	 */
	public function getByType($type, $throw = true)
	{
		$type = \PHPStanVendor\Nette\DI\Helpers::normalizeClass($type);
		if (!empty($this->meta[self::TYPES][$type][true])) {
			if (count($names = $this->meta[self::TYPES][$type][true]) === 1) {
				return $this->getService($names[0]);
			}
			throw new \PHPStanVendor\Nette\DI\MissingServiceException("Multiple services of type $type found: " . implode(', ', $names) . '.');

		} elseif ($throw) {
			throw new \PHPStanVendor\Nette\DI\MissingServiceException("Service of type $type not found.");
		}
	}


	/**
	 * Gets the service names of the specified type.
	 * @param  string
	 * @return string[]
	 */
	public function findByType($type)
	{
		$type = \PHPStanVendor\Nette\DI\Helpers::normalizeClass($type);
		return empty($this->meta[self::TYPES][$type])
			? []
			: array_merge(...array_values($this->meta[self::TYPES][$type]));
	}


	/**
	 * Gets the service names of the specified tag.
	 * @param  string
	 * @return array of [service name => tag attributes]
	 */
	public function findByTag($tag)
	{
		return isset($this->meta[self::TAGS][$tag]) ? $this->meta[self::TAGS][$tag] : [];
	}


	/********************* autowiring ****************d*g**/


	/**
	 * Creates new instance using autowiring.
	 * @param  string  class
	 * @param  array   arguments
	 * @return object
	 * @throws Nette\InvalidArgumentException
	 */
	public function createInstance($class, array $args = [])
	{
		$rc = new \ReflectionClass($class);
		if (!$rc->isInstantiable()) {
			throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Class $class is not instantiable.");

		} elseif ($constructor = $rc->getConstructor()) {
			return $rc->newInstanceArgs(\PHPStanVendor\Nette\DI\Helpers::autowireArguments($constructor, $args, $this));

		} elseif ($args) {
			throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Unable to pass arguments, class $class has no constructor.");
		}
		return new $class;
	}


	/**
	 * Calls all methods starting with with "inject" using autowiring.
	 * @param  object
	 * @return void
	 */
	public function callInjects($service)
	{
		\PHPStanVendor\Nette\DI\Extensions\InjectExtension::callInjects($this, $service);
	}


	/**
	 * Calls method using autowiring.
	 * @return mixed
	 */
	public function callMethod(callable $function, array $args = [])
	{
		return $function(...\PHPStanVendor\Nette\DI\Helpers::autowireArguments(\PHPStanVendor\Nette\Utils\Callback::toReflection($function), $args, $this));
	}


	/********************* shortcuts ****************d*g**/


	/**
	 * Expands %placeholders%.
	 * @param  mixed
	 * @return mixed
	 * @deprecated
	 */
	public function expand($s)
	{
		return \PHPStanVendor\Nette\DI\Helpers::expand($s, $this->parameters);
	}


	/** @deprecated */
	public function &__get($name)
	{
		trigger_error(__METHOD__ . ' is deprecated; use getService().', E_USER_DEPRECATED);
		$tmp = $this->getService($name);
		return $tmp;
	}


	/** @deprecated */
	public function __set($name, $service)
	{
		trigger_error(__METHOD__ . ' is deprecated; use addService().', E_USER_DEPRECATED);
		$this->addService($name, $service);
	}


	/** @deprecated */
	public function __isset($name)
	{
		trigger_error(__METHOD__ . ' is deprecated; use hasService().', E_USER_DEPRECATED);
		return $this->hasService($name);
	}


	/** @deprecated */
	public function __unset($name)
	{
		trigger_error(__METHOD__ . ' is deprecated; use removeService().', E_USER_DEPRECATED);
		$this->removeService($name);
	}


	public static function getMethodName($name)
	{
		$uname = ucfirst($name);
		return 'createService' . ((string) $name === $uname ? '__' : '') . str_replace('.', '__', $uname);
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI;


/**
 * Container builder.
 */
class ContainerBuilder
{
	use \PHPStanVendor\Nette\SmartObject;

	const THIS_SERVICE = 'self',
		THIS_CONTAINER = 'container';

	/** @var array */
	public $parameters = [];

	/** @var ServiceDefinition[] */
	private $definitions = [];

	/** @var array of alias => service */
	private $aliases = [];

	/** @var array for auto-wiring */
	private $classList = [];

	/** @var bool */
	private $classListNeedsRefresh = true;

	/** @var string[] of classes excluded from auto-wiring */
	private $excludedClasses = [];

	/** @var array */
	private $dependencies = [];

	/** @var string */
	private $currentService;


	/**
	 * Adds new service definition.
	 * @param  string
	 * @return ServiceDefinition
	 */
	public function addDefinition($name, \PHPStanVendor\Nette\DI\ServiceDefinition $definition = null)
	{
		$this->classListNeedsRefresh = true;
		if (!is_string($name) || !$name) { // builder is not ready for falsy names such as '0'
			throw new \PHPStanVendor\Nette\InvalidArgumentException(sprintf('Service name must be a non-empty string, %s given.', gettype($name)));
		}
		$name = isset($this->aliases[$name]) ? $this->aliases[$name] : $name;
		if (isset($this->definitions[$name])) {
			throw new \PHPStanVendor\Nette\InvalidStateException("Service '$name' has already been added.");
		}
		if (!$definition) {
			$definition = new \PHPStanVendor\Nette\DI\ServiceDefinition;
		}
		$definition->setNotifier(function () {
			$this->classListNeedsRefresh = true;
		});
		return $this->definitions[$name] = $definition;
	}


	/**
	 * Removes the specified service definition.
	 * @param  string
	 * @return void
	 */
	public function removeDefinition($name)
	{
		$this->classListNeedsRefresh = true;
		$name = isset($this->aliases[$name]) ? $this->aliases[$name] : $name;
		unset($this->definitions[$name]);
	}


	/**
	 * Gets the service definition.
	 * @param  string
	 * @return ServiceDefinition
	 */
	public function getDefinition($name)
	{
		$service = isset($this->aliases[$name]) ? $this->aliases[$name] : $name;
		if (!isset($this->definitions[$service])) {
			throw new \PHPStanVendor\Nette\DI\MissingServiceException("Service '$name' not found.");
		}
		return $this->definitions[$service];
	}


	/**
	 * Gets all service definitions.
	 * @return ServiceDefinition[]
	 */
	public function getDefinitions()
	{
		return $this->definitions;
	}


	/**
	 * Does the service definition or alias exist?
	 * @param  string
	 * @return bool
	 */
	public function hasDefinition($name)
	{
		$name = isset($this->aliases[$name]) ? $this->aliases[$name] : $name;
		return isset($this->definitions[$name]);
	}


	/**
	 * @param  string
	 * @param  string
	 */
	public function addAlias($alias, $service)
	{
		if (!is_string($alias) || !$alias) { // builder is not ready for falsy names such as '0'
			throw new \PHPStanVendor\Nette\InvalidArgumentException(sprintf('Alias name must be a non-empty string, %s given.', gettype($alias)));

		} elseif (!is_string($service) || !$service) { // builder is not ready for falsy names such as '0'
			throw new \PHPStanVendor\Nette\InvalidArgumentException(sprintf('Service name must be a non-empty string, %s given.', gettype($service)));

		} elseif (isset($this->aliases[$alias])) {
			throw new \PHPStanVendor\Nette\InvalidStateException("Alias '$alias' has already been added.");

		} elseif (isset($this->definitions[$alias])) {
			throw new \PHPStanVendor\Nette\InvalidStateException("Service '$alias' has already been added.");
		}
		$this->aliases[$alias] = $service;
	}


	/**
	 * Removes the specified alias.
	 * @return void
	 */
	public function removeAlias($alias)
	{
		unset($this->aliases[$alias]);
	}


	/**
	 * Gets all service aliases.
	 * @return array
	 */
	public function getAliases()
	{
		return $this->aliases;
	}


	/**
	 * @param  string[]
	 * @return static
	 */
	public function addExcludedClasses(array $types)
	{
		foreach ($types as $type) {
			if (class_exists($type) || interface_exists($type)) {
				$type = \PHPStanVendor\Nette\DI\Helpers::normalizeClass($type);
				$this->excludedClasses += class_parents($type) + class_implements($type) + [$type => $type];
			}
		}
		return $this;
	}


	/**
	 * @deprecated
	 */
	public function setClassName($name)
	{
		trigger_error(__METHOD__ . ' has been deprecated', E_USER_DEPRECATED);
		return $this;
	}


	/**
	 * @deprecated
	 */
	public function getClassName()
	{
		trigger_error(__METHOD__ . ' has been deprecated', E_USER_DEPRECATED);
	}


	/********************* class resolving ****************d*g**/


	/**
	 * Resolves service name by type.
	 * @param  string  class or interface
	 * @param  bool    throw exception if service doesn't exist?
	 * @return string|null  service name or null
	 * @throws ServiceCreationException
	 */
	public function getByType($type, $throw = false)
	{
		$type = \PHPStanVendor\Nette\DI\Helpers::normalizeClass($type);

		if ($this->currentService !== null
			&& is_a($this->definitions[$this->currentService]->getType(), $type, true)
		) {
			return $this->currentService;
		}

		$types = $this->getClassList();
		if (empty($types[$type][true])) {
			if ($throw) {
				throw new \PHPStanVendor\Nette\DI\MissingServiceException("Service of type '$type' not found.");
			}
			return;

		} elseif (count($types[$type][true]) === 1) {
			return $types[$type][true][0];

		} else {
			$list = $types[$type][true];
			$hint = count($list) === 2 && ($tmp = strpos($list[0], '.') xor strpos($list[1], '.'))
				? '. If you want to overwrite service ' . $list[$tmp ? 0 : 1] . ', give it proper name.'
				: '';
			throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Multiple services of type $type found: " . implode(', ', $list) . $hint);
		}
	}


	/**
	 * Gets the service definition of the specified type.
	 * @param  string
	 * @return ServiceDefinition
	 */
	public function getDefinitionByType($type)
	{
		return $this->getDefinition($this->getByType($type, true));
	}


	/**
	 * Gets the service names and definitions of the specified type.
	 * @param  string
	 * @return ServiceDefinition[]
	 */
	public function findByType($type)
	{
		$type = \PHPStanVendor\Nette\DI\Helpers::normalizeClass($type);
		$found = [];
		$types = $this->getClassList();
		if (!empty($types[$type])) {
			foreach (array_merge(...array_values($types[$type])) as $name) {
				$found[$name] = $this->definitions[$name];
			}
		}
		return $found;
	}


	/**
	 * Gets the service objects of the specified tag.
	 * @param  string
	 * @return array of [service name => tag attributes]
	 */
	public function findByTag($tag)
	{
		$found = [];
		foreach ($this->definitions as $name => $def) {
			if (($tmp = $def->getTag($tag)) !== null) {
				$found[$name] = $tmp;
			}
		}
		return $found;
	}


	/**
	 * @internal
	 */
	public function getClassList()
	{
		if ($this->classList !== false && $this->classListNeedsRefresh) {
			$this->prepareClassList();
			$this->classListNeedsRefresh = false;
		}
		return $this->classList ?: [];
	}


	/**
	 * Generates $dependencies, $classList and normalizes class names.
	 * @return void
	 * @internal
	 */
	public function prepareClassList()
	{
		unset($this->definitions[self::THIS_CONTAINER]);
		$this->addDefinition(self::THIS_CONTAINER)->setType(\PHPStanVendor\Nette\DI\Container::class);

		$this->classList = false;

		foreach ($this->definitions as $name => $def) {
			// prepare generated factories
			if ($def->getImplement()) {
				$this->resolveImplement($def, $name);
			}

			if ($def->isDynamic()) {
				if (!$def->getType()) {
					throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Type is missing in definition of service '$name'.");
				}
				$def->setFactory(null);
				continue;
			}

			// complete class-factory pairs
			if (!$def->getEntity()) {
				if (!$def->getType()) {
					throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Factory and type are missing in definition of service '$name'.");
				}
				$def->setFactory($def->getType(), ($factory = $def->getFactory()) ? $factory->arguments : []);
			}

			// auto-disable autowiring for aliases
			if ($def->getAutowired() === true
				&& ($alias = $this->getServiceName($def->getFactory()->getEntity()))
				&& (!$def->getImplement() || (!\PHPStanVendor\Nette\Utils\Strings::contains($alias, '\\') && $this->definitions[$alias]->getImplement()))
			) {
				$def->setAutowired(false);
			}
		}

		// resolve and check classes
		foreach ($this->definitions as $name => $def) {
			$this->resolveServiceType($name);
		}

		//  build auto-wiring list
		$this->classList = $preferred = [];
		foreach ($this->definitions as $name => $def) {
			if ($type = $def->getImplement() ?: $def->getType()) {
				$defAutowired = $def->getAutowired();
				if (is_array($defAutowired)) {
					foreach ($defAutowired as $k => $autowiredType) {
						if ($autowiredType === self::THIS_SERVICE) {
							$defAutowired[$k] = $type;
						} elseif (!is_a($type, $autowiredType, true)) {
							throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Incompatible class $autowiredType in autowiring definition of service '$name'.");
						}
					}
				}

				foreach (class_parents($type) + class_implements($type) + [$type] as $parent) {
					$autowired = $defAutowired && empty($this->excludedClasses[$parent]);
					if ($autowired && is_array($defAutowired)) {
						$autowired = false;
						foreach ($defAutowired as $autowiredType) {
							if (is_a($parent, $autowiredType, true)) {
								if (empty($preferred[$parent]) && isset($this->classList[$parent][true])) {
									$this->classList[$parent][false] = array_merge(...$this->classList[$parent]);
									$this->classList[$parent][true] = [];
								}
								$preferred[$parent] = $autowired = true;
								break;
							}
						}
					} elseif (isset($preferred[$parent])) {
						$autowired = false;
					}
					$this->classList[$parent][$autowired][] = (string) $name;
				}
			}
		}
	}


	private function resolveImplement(\PHPStanVendor\Nette\DI\ServiceDefinition $def, $name)
	{
		$interface = $def->getImplement();
		if (!interface_exists($interface)) {
			throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Interface $interface used in service '$name' not found.");
		}
		$interface = \PHPStanVendor\Nette\DI\Helpers::normalizeClass($interface);
		$def->setImplement($interface);

		$rc = new \ReflectionClass($interface);
		$this->addDependency($rc);
		$method = $rc->hasMethod('create')
			? $rc->getMethod('create')
			: ($rc->hasMethod('get') ? $rc->getMethod('get') : null);

		if (count($rc->getMethods()) !== 1 || !$method || $method->isStatic()) {
			throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Interface $interface used in service '$name' must have just one non-static method create() or get().");
		}
		$def->setImplementMode($rc->hasMethod('create') ? $def::IMPLEMENT_MODE_CREATE : $def::IMPLEMENT_MODE_GET);
		$methodName = \PHPStanVendor\Nette\Utils\Reflection::toString($method) . '()';

		if (!$def->getType() && !$def->getEntity()) {
			$returnType = \PHPStanVendor\Nette\DI\Helpers::getReturnType($method);
			if (!$returnType) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Method $methodName used in service '$name' has not return type hint or annotation @return.");
			} elseif (!class_exists($returnType)) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Check a type hint or annotation @return of the $methodName method used in service '$name', class '$returnType' cannot be found.");
			}
			$def->setType($returnType);
		}

		if ($rc->hasMethod('get')) {
			if ($method->getParameters()) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Method $methodName used in service '$name' must have no arguments.");
			}
			if (!$def->getEntity()) {
				$def->setFactory('@\\' . ltrim($def->getType(), '\\'));
			} elseif (!$this->getServiceName($def->getFactory()->getEntity())) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Invalid factory in service '$name' definition.");
			}
		}

		if (!$def->parameters) {
			$ctorParams = [];
			if (!$def->getEntity()) {
				$def->setFactory($def->getType(), $def->getFactory() ? $def->getFactory()->arguments : []);
			}
			if (($class = $this->resolveEntityType($def->getFactory(), [$name => 1]))
				&& ($ctor = (new \ReflectionClass($class))->getConstructor())
			) {
				foreach ($ctor->getParameters() as $param) {
					$ctorParams[$param->getName()] = $param;
				}
			}

			foreach ($method->getParameters() as $param) {
				$hint = \PHPStanVendor\Nette\Utils\Reflection::getParameterType($param);
				if (isset($ctorParams[$param->getName()])) {
					$arg = $ctorParams[$param->getName()];
					if ($hint !== \PHPStanVendor\Nette\Utils\Reflection::getParameterType($arg)) {
						throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Type hint for \${$param->getName()} in $methodName doesn't match type hint in $class constructor.");
					}
					$def->getFactory()->arguments[$arg->getPosition()] = self::literal('$' . $arg->getName());
				} elseif (!$def->getSetup()) {
					$hint = \PHPStanVendor\Nette\Utils\ObjectMixin::getSuggestion(array_keys($ctorParams), $param->getName());
					throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Unused parameter \${$param->getName()} when implementing method $methodName" . ($hint ? ", did you mean \${$hint}?" : '.'));
				}
				$nullable = $hint && $param->allowsNull() && (!$param->isDefaultValueAvailable() || $param->getDefaultValue() !== null);
				$paramDef = ($nullable ? '?' : '') . $hint . ' ' . $param->getName();
				if ($param->isDefaultValueAvailable()) {
					$def->parameters[$paramDef] = \PHPStanVendor\Nette\Utils\Reflection::getParameterDefaultValue($param);
				} else {
					$def->parameters[] = $paramDef;
				}
			}
		}
	}


	/** @return string|null */
	private function resolveServiceType($name, $recursive = [])
	{
		if (isset($recursive[$name])) {
			throw new \PHPStanVendor\Nette\DI\ServiceCreationException(sprintf('Circular reference detected for services: %s.', implode(', ', array_keys($recursive))));
		}
		$recursive[$name] = true;

		$def = $this->definitions[$name];
		$factoryClass = $def->getFactory() ? $this->resolveEntityType($def->getFactory()->getEntity(), $recursive) : null; // call always to check entities
		if ($type = $def->getType() ?: $factoryClass) {
			if (!class_exists($type) && !interface_exists($type)) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Class or interface '$type' used in service '$name' not found.");
			}
			$type = \PHPStanVendor\Nette\DI\Helpers::normalizeClass($type);
			$def->setType($type);
			if (count($recursive) === 1) {
				$this->addDependency(new \ReflectionClass($factoryClass ?: $type));
			}

		} elseif ($def->getAutowired()) {
			throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Unknown type of service '$name', declare return type of factory method (for PHP 5 use annotation @return)");
		}
		return $type;
	}


	/** @return string|null */
	private function resolveEntityType($entity, $recursive = [])
	{
		$entity = $this->normalizeEntity($entity instanceof \PHPStanVendor\Nette\DI\Statement ? $entity->getEntity() : $entity);
		$serviceName = current(array_slice(array_keys($recursive), -1));

		if (is_array($entity)) {
			if (($service = $this->getServiceName($entity[0])) || $entity[0] instanceof \PHPStanVendor\Nette\DI\Statement) {
				$entity[0] = $this->resolveEntityType($entity[0], $recursive);
				if (!$entity[0]) {
					return;
				} elseif (isset($this->definitions[$service]) && $this->definitions[$service]->getImplement()) { // @Implement::create
					return $entity[1] === 'create' ? $this->resolveServiceType($service, $recursive) : null;
				}
			}

			try {
				$reflection = \PHPStanVendor\Nette\Utils\Callback::toReflection($entity[0] === '' ? $entity[1] : $entity);
				$refClass = $reflection instanceof \ReflectionMethod ? $reflection->getDeclaringClass() : null;
			} catch (\ReflectionException $e) {
			}

			if (isset($e) || ($refClass && (!$reflection->isPublic()
				|| ($refClass->isTrait() && !$reflection->isStatic())
			))) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException(sprintf("Method %s() used in service '%s' is not callable.", \PHPStanVendor\Nette\Utils\Callback::toString($entity), $serviceName));
			}
			$this->addDependency($reflection);

			$type = \PHPStanVendor\Nette\DI\Helpers::getReturnType($reflection);
			if ($type && !class_exists($type) && !interface_exists($type)) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException(sprintf("Class or interface '%s' not found. Is return type of %s() used in service '%s' correct?", $type, \PHPStanVendor\Nette\Utils\Callback::toString($entity), $serviceName));
			}
			return $type;

		} elseif ($service = $this->getServiceName($entity)) { // alias or factory
			if (\PHPStanVendor\Nette\Utils\Strings::contains($service, '\\')) { // @\Class
				return $service;
			}
			return $this->definitions[$service]->getImplement()
				?: $this->definitions[$service]->getType()
				?: $this->resolveServiceType($service, $recursive);

		} elseif (is_string($entity)) { // class
			if (!class_exists($entity)) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Class $entity used in service '$serviceName' not found.");
			}
			return $entity;
		}
	}


	/**
	 * @return void
	 */
	public function complete()
	{
		$this->prepareClassList();

		foreach ($this->definitions as $name => $def) {
			if ($def->isDynamic()) {
				continue;
			}

			$this->currentService = null;
			$entity = $def->getFactory()->getEntity();
			$serviceRef = $this->getServiceName($entity);
			$factory = $serviceRef && !$def->getFactory()->arguments && !$def->getSetup() && $def->getImplementMode() !== $def::IMPLEMENT_MODE_CREATE
				? new \PHPStanVendor\Nette\DI\Statement(['@' . self::THIS_CONTAINER, 'getService'], [$serviceRef])
				: $def->getFactory();

			try {
				$def->setFactory($this->completeStatement($factory));
				$this->classListNeedsRefresh = false;

				$this->currentService = $name;
				$setups = $def->getSetup();
				foreach ($setups as &$setup) {
					if (is_string($setup->getEntity()) && strpbrk($setup->getEntity(), ':@?\\') === false) { // auto-prepend @self
						$setup = new \PHPStanVendor\Nette\DI\Statement(['@' . $name, $setup->getEntity()], $setup->arguments);
					}
					$setup = $this->completeStatement($setup);
				}
				$def->setSetup($setups);

			} catch (\Exception $e) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Service '$name': " . $e->getMessage(), 0, $e);

			} finally {
				$this->currentService = null;
			}
		}
	}


	/**
	 * @return Statement
	 */
	public function completeStatement(\PHPStanVendor\Nette\DI\Statement $statement)
	{
		$entity = $this->normalizeEntity($statement->getEntity());
		$arguments = $statement->arguments;

		if (is_string($entity) && \PHPStanVendor\Nette\Utils\Strings::contains($entity, '?')) { // PHP literal

		} elseif ($service = $this->getServiceName($entity)) { // factory calling
			$params = [];
			foreach ($this->definitions[$service]->parameters as $k => $v) {
				$params[] = preg_replace('#\w+\z#', '\$$0', (is_int($k) ? $v : $k)) . (is_int($k) ? '' : ' = ' . \PHPStanVendor\Nette\PhpGenerator\Helpers::dump($v));
			}
			$rm = new \ReflectionFunction(eval('return function(' . implode(', ', $params) . ') {};'));
			$arguments = \PHPStanVendor\Nette\DI\Helpers::autowireArguments($rm, $arguments, $this);
			$entity = '@' . $service;

		} elseif ($entity === 'not') { // operator

		} elseif (is_string($entity)) { // class name
			if (!class_exists($entity)) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Class $entity not found.");
			} elseif ((new \ReflectionClass($entity))->isAbstract()) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Class $entity is abstract.");
			} elseif (($rm = (new \ReflectionClass($entity))->getConstructor()) !== null && !$rm->isPublic()) {
				$visibility = $rm->isProtected() ? 'protected' : 'private';
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Class $entity has $visibility constructor.");
			} elseif ($constructor = (new \ReflectionClass($entity))->getConstructor()) {
				$this->addDependency($constructor);
				$arguments = \PHPStanVendor\Nette\DI\Helpers::autowireArguments($constructor, $arguments, $this);
			} elseif ($arguments) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Unable to pass arguments, class $entity has no constructor.");
			}

		} elseif (!\PHPStanVendor\Nette\Utils\Arrays::isList($entity) || count($entity) !== 2) {
			throw new \PHPStanVendor\Nette\DI\ServiceCreationException(sprintf('Expected class, method or property, %s given.', \PHPStanVendor\Nette\PhpGenerator\Helpers::dump($entity)));

		} elseif (!preg_match('#^\$?(\\\\?' . \PHPStanVendor\Nette\PhpGenerator\Helpers::PHP_IDENT . ')+(\[\])?\z#', $entity[1])) {
			throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Expected function, method or property name, '$entity[1]' given.");

		} elseif ($entity[0] === '') { // globalFunc
			if (!\PHPStanVendor\Nette\Utils\Arrays::isList($arguments)) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Unable to pass specified arguments to $entity[0].");
			} elseif (!function_exists($entity[1])) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Function $entity[1] doesn't exist.");
			}

			$rf = new \ReflectionFunction($entity[1]);
			$this->addDependency($rf);
			$arguments = \PHPStanVendor\Nette\DI\Helpers::autowireArguments($rf, $arguments, $this);

		} else {
			if ($entity[0] instanceof \PHPStanVendor\Nette\DI\Statement) {
				$entity[0] = $this->completeStatement($entity[0]);
			} elseif ($service = $this->getServiceName($entity[0])) { // service method
				$entity[0] = '@' . $service;
			}

			if ($entity[1][0] === '$') { // property getter, setter or appender
				\PHPStanVendor\Nette\Utils\Validators::assert($arguments, 'list:0..1', "setup arguments for '" . \PHPStanVendor\Nette\Utils\Callback::toString($entity) . "'");
				if (!$arguments && substr($entity[1], -2) === '[]') {
					throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Missing argument for $entity[1].");
				}
			} elseif ($type = empty($service) || $entity[1] === 'create'
				? $this->resolveEntityType($entity[0])
				: $this->definitions[$service]->getType()
			) {
				$arguments = $this->autowireArguments($type, $entity[1], $arguments);
			}
		}

		array_walk_recursive($arguments, function (&$val) {
			if ($val instanceof \PHPStanVendor\Nette\DI\Statement) {
				$val = $this->completeStatement($val);

			} elseif ($val === $this) {
				trigger_error("Replace object ContainerBuilder in Statement arguments with '@container'.", E_USER_DEPRECATED);
				$val = self::literal('$this');

			} elseif ($val instanceof \PHPStanVendor\Nette\DI\ServiceDefinition) {
				$val = '@' . current(array_keys($this->getDefinitions(), $val, true));

			} elseif (is_string($val) && strlen($val) > 1 && $val[0] === '@' && $val[1] !== '@') {
				$pair = explode('::', $val, 2);
				$name = $this->getServiceName($pair[0]);
				if (!isset($pair[1])) { // @service
					$val = '@' . $name;
				} elseif (preg_match('#^[A-Z][A-Z0-9_]*\z#', $pair[1], $m)) { // @service::CONSTANT
					$val = self::literal($this->getDefinition($name)->getType() . '::' . $pair[1]);
				} else { // @service::property
					$val = new \PHPStanVendor\Nette\DI\Statement(['@' . $name, '$' . $pair[1]]);
				}
			}
		});

		return new \PHPStanVendor\Nette\DI\Statement($entity, $arguments);
	}


	/**
	 * Adds item to the list of dependencies.
	 * @param  ReflectionClass|\ReflectionFunctionAbstract|string
	 * @return static
	 * @internal
	 */
	public function addDependency($dep)
	{
		$this->dependencies[] = $dep;
		return $this;
	}


	/**
	 * Returns the list of dependencies.
	 * @return array
	 */
	public function getDependencies()
	{
		return $this->dependencies;
	}


	/**
	 * Expands %placeholders% in strings.
	 * @return mixed
	 * @deprecated
	 */
	public function expand($value)
	{
		return \PHPStanVendor\Nette\DI\Helpers::expand($value, $this->parameters);
	}


	/**
	 * @return Nette\PhpGenerator\PhpLiteral
	 */
	public static function literal($code, array $args = null)
	{
		return new \PHPStanVendor\Nette\PhpGenerator\PhpLiteral($args === null ? $code : \PHPStanVendor\Nette\PhpGenerator\Helpers::formatArgs($code, $args));
	}


	/** @internal */
	public function normalizeEntity($entity)
	{
		if (is_string($entity) && \PHPStanVendor\Nette\Utils\Strings::contains($entity, '::') && !\PHPStanVendor\Nette\Utils\Strings::contains($entity, '?')) { // Class::method -> [Class, method]
			$entity = explode('::', $entity);
		}

		if (is_array($entity) && $entity[0] instanceof \PHPStanVendor\Nette\DI\ServiceDefinition) { // [ServiceDefinition, ...] -> [@serviceName, ...]
			$entity[0] = '@' . current(array_keys($this->definitions, $entity[0], true));

		} elseif ($entity instanceof \PHPStanVendor\Nette\DI\ServiceDefinition) { // ServiceDefinition -> @serviceName
			$entity = '@' . current(array_keys($this->definitions, $entity, true));

		} elseif (is_array($entity) && $entity[0] === $this) { // [$this, ...] -> [@container, ...]
			trigger_error("Replace object ContainerBuilder in Statement entity with '@container'.", E_USER_DEPRECATED);
			$entity[0] = '@' . self::THIS_CONTAINER;
		}
		return $entity; // Class, @service, [Class, member], [@service, member], [, globalFunc], Statement
	}


	/**
	 * Converts @service or @\Class -> service name and checks its existence.
	 * @return string  of false, if argument is not service name
	 * @internal
	 */
	public function getServiceName($arg)
	{
		if (!is_string($arg) || !preg_match('#^@[\w\\\\.][^:]*\z#', $arg)) {
			return false;
		}
		$service = substr($arg, 1);
		if ($service === self::THIS_SERVICE) {
			$service = $this->currentService;
		}
		if (\PHPStanVendor\Nette\Utils\Strings::contains($service, '\\')) {
			if ($this->classList === false) { // may be disabled by prepareClassList
				return $service;
			}
			$res = $this->getByType($service);
			if (!$res) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Reference to missing service of type $service.");
			}
			return $res;
		}
		$service = isset($this->aliases[$service]) ? $this->aliases[$service] : $service;
		if (!isset($this->definitions[$service])) {
			throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Reference to missing service '$service'.");
		}
		return $service;
	}


	/**
	 * Creates a list of arguments using autowiring.
	 * @return array
	 * @internal
	 */
	public function autowireArguments($class, $method, array $arguments)
	{
		$rc = new \ReflectionClass($class);
		if (!$rc->hasMethod($method)) {
			if (!\PHPStanVendor\Nette\Utils\Arrays::isList($arguments)) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Unable to pass specified arguments to $class::$method().");
			}
			return $arguments;
		}

		$rm = $rc->getMethod($method);
		if (!$rm->isPublic()) {
			throw new \PHPStanVendor\Nette\DI\ServiceCreationException("$class::$method() is not callable.");
		}
		$this->addDependency($rm);
		return \PHPStanVendor\Nette\DI\Helpers::autowireArguments($rm, $arguments, $this);
	}


	/** @deprecated */
	public function generateClasses($className = 'Container', $parentName = null)
	{
		trigger_error(__METHOD__ . ' is deprecated', E_USER_DEPRECATED);
		return (new \PHPStanVendor\Nette\DI\PhpGenerator($this))->generate($className);
	}


	/** @deprecated */
	public function formatStatement(\PHPStanVendor\Nette\DI\Statement $statement)
	{
		trigger_error(__METHOD__ . ' is deprecated', E_USER_DEPRECATED);
		return (new \PHPStanVendor\Nette\DI\PhpGenerator($this))->formatStatement($statement);
	}


	/** @deprecated */
	public function formatPhp($statement, $args)
	{
		array_walk_recursive($args, function (&$val) {
			if ($val instanceof \PHPStanVendor\Nette\DI\Statement) {
				$val = $this->completeStatement($val);

			} elseif ($val === $this) {
				trigger_error("Replace object ContainerBuilder in Statement arguments with '@container'.", E_USER_DEPRECATED);
				$val = self::literal('$this');

			} elseif ($val instanceof \PHPStanVendor\Nette\DI\ServiceDefinition) {
				$val = '@' . current(array_keys($this->getDefinitions(), $val, true));
			}
		});
		return (new \PHPStanVendor\Nette\DI\PhpGenerator($this))->formatPhp($statement, $args);
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI;


/**
 * DI container loader.
 */
class ContainerLoader
{
	use \PHPStanVendor\Nette\SmartObject;

	/** @var bool */
	private $autoRebuild = false;

	/** @var string */
	private $tempDirectory;


	public function __construct($tempDirectory, $autoRebuild = false)
	{
		$this->tempDirectory = $tempDirectory;
		$this->autoRebuild = $autoRebuild;
	}


	/**
	 * @param  callable  function (Nette\DI\Compiler $compiler): string|null
	 * @param  mixed
	 * @return string
	 */
	public function load($generator, $key = null)
	{
		if (!is_callable($generator)) { // back compatiblity
			trigger_error(__METHOD__ . ': order of arguments has been swapped.', E_USER_DEPRECATED);
			list($generator, $key) = [$key, $generator];
		}
		$class = $this->getClassName($key);
		if (!class_exists($class, false)) {
			$this->loadFile($class, $generator);
		}
		return $class;
	}


	/**
	 * @return string
	 */
	public function getClassName($key)
	{
		return 'Container_' . substr(md5(serialize($key)), 0, 10);
	}


	/**
	 * @return void
	 */
	private function loadFile($class, $generator)
	{
		$file = "$this->tempDirectory/$class.php";
		if (!$this->isExpired($file) && (@include $file) !== false) { // @ file may not exist
			return;
		}

		\PHPStanVendor\Nette\Utils\FileSystem::createDir($this->tempDirectory);

		$handle = @fopen("$file.lock", 'c+'); // @ is escalated to exception
		if (!$handle) {
			throw new \PHPStanVendor\Nette\IOException("Unable to create file '$file.lock'. " . error_get_last()['message']);
		} elseif (!@flock($handle, LOCK_EX)) { // @ is escalated to exception
			throw new \PHPStanVendor\Nette\IOException("Unable to acquire exclusive lock on '$file.lock'. " . error_get_last()['message']);
		}

		if (!is_file($file) || $this->isExpired($file, $updatedMeta)) {
			if (isset($updatedMeta)) {
				$toWrite["$file.meta"] = $updatedMeta;
			} else {
				list($toWrite[$file], $toWrite["$file.meta"]) = $this->generate($class, $generator);
			}

			foreach ($toWrite as $name => $content) {
				if (file_put_contents("$name.tmp", $content) !== strlen($content) || !rename("$name.tmp", $name)) {
					@unlink("$name.tmp"); // @ - file may not exist
					throw new \PHPStanVendor\Nette\IOException("Unable to create file '$name'.");
				} elseif (function_exists('opcache_invalidate')) {
					@opcache_invalidate($name, true); // @ can be restricted
				}
			}
		}

		if ((@include $file) === false) { // @ - error escalated to exception
			throw new \PHPStanVendor\Nette\IOException("Unable to include '$file'.");
		}
		flock($handle, LOCK_UN);
	}


	private function isExpired($file, &$updatedMeta = null)
	{
		if ($this->autoRebuild) {
			$meta = @unserialize((string) file_get_contents("$file.meta")); // @ - file may not exist
			$orig = $meta[2];
			return empty($meta[0])
				|| \PHPStanVendor\Nette\DI\DependencyChecker::isExpired(...$meta)
				|| ($orig !== $meta[2] && $updatedMeta = serialize($meta));
		}
		return false;
	}


	/**
	 * @return array of (code, file[])
	 */
	protected function generate($class, $generator)
	{
		$compiler = new \PHPStanVendor\Nette\DI\Compiler;
		$compiler->setClassName($class);
		$code = call_user_func_array($generator, [&$compiler]) ?: $compiler->compile();
		return [
			"<?php\n$code",
			serialize($compiler->exportDependencies()),
		];
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI;


/**
 * Cache dependencies checker.
 */
class DependencyChecker
{
	use \PHPStanVendor\Nette\SmartObject;

	const VERSION = 1;

	/** @var array of ReflectionClass|\ReflectionFunctionAbstract|string */
	private $dependencies = [];


	/**
	 * Adds dependencies to the list.
	 * @return static
	 */
	public function add(array $deps)
	{
		$this->dependencies = array_merge($this->dependencies, $deps);
		return $this;
	}


	/**
	 * Exports dependencies.
	 * @return array
	 */
	public function export()
	{
		$files = $phpFiles = $classes = $functions = [];
		foreach ($this->dependencies as $dep) {
			if (is_string($dep)) {
				$files[] = $dep;

			} elseif ($dep instanceof \ReflectionClass) {
				if (empty($classes[$name = $dep->getName()])) {
					$all = [$name] + class_parents($name) + class_implements($name);
					foreach ($all as &$item) {
						$all += class_uses($item);
						$phpFiles[] = (new \ReflectionClass($item))->getFileName();
						$classes[$item] = true;
					}
				}

			} elseif ($dep instanceof \ReflectionFunctionAbstract) {
				$phpFiles[] = $dep->getFileName();
				$functions[] = \PHPStanVendor\Nette\Utils\Reflection::toString($dep);

			} else {
				throw new \PHPStanVendor\Nette\InvalidStateException('Unexpected dependency ' . gettype($dep));
			}
		}

		$classes = array_keys($classes);
		$functions = array_unique($functions, SORT_REGULAR);
		$hash = self::calculateHash($classes, $functions);
		$files = @array_map('filemtime', array_combine($files, $files)); // @ - file may not exist
		$phpFiles = @array_map('filemtime', array_combine($phpFiles, $phpFiles)); // @ - file may not exist
		return [self::VERSION, $files, $phpFiles, $classes, $functions, $hash];
	}


	/**
	 * Are dependencies expired?
	 * @return bool
	 */
	public static function isExpired($version, $files, &$phpFiles, $classes, $functions, $hash)
	{
		$current = @array_map('filemtime', array_combine($tmp = array_keys($files), $tmp)); // @ - files may not exist
		$origPhpFiles = $phpFiles;
		$phpFiles = @array_map('filemtime', array_combine($tmp = array_keys($phpFiles), $tmp)); // @ - files may not exist
		return $version !== self::VERSION
			|| $files !== $current
			|| ($phpFiles !== $origPhpFiles && $hash !== self::calculateHash($classes, $functions));
	}


	private static function calculateHash($classes, $functions)
	{
		$hash = [];
		foreach ($classes as $name) {
			try {
				$class = new \ReflectionClass($name);
			} catch (\ReflectionException $e) {
				return;
			}
			$hash[] = [
				$name,
				\PHPStanVendor\Nette\Utils\Reflection::getUseStatements($class),
				$class->isAbstract(),
				get_parent_class($name),
				class_implements($name),
				class_uses($name),
			];

			foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) {
				if ($prop->getDeclaringClass() == $class) { // intentionally ==
					$hash[] = [$name, $prop->getName(), $prop->getDocComment()];
				}
			}
			foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
				if ($method->getDeclaringClass() == $class) { // intentionally ==
					$hash[] = [
						$name,
						$method->getName(),
						$method->getDocComment(),
						self::hashParameters($method),
						PHP_VERSION_ID >= 70000 && $method->hasReturnType()
							? [(string) $method->getReturnType(), $method->getReturnType()->allowsNull()]
							: null,
					];
				}
			}
		}

		$flip = array_flip($classes);
		foreach ($functions as $name) {
			try {
				$method = strpos($name, '::') ? new \ReflectionMethod($name) : new \ReflectionFunction($name);
			} catch (\ReflectionException $e) {
				return;
			}
			$class = $method instanceof \ReflectionMethod ? $method->getDeclaringClass() : null;
			if ($class && isset($flip[$class->getName()])) {
				continue;
			}
			$hash[] = [
				$name,
				$class ? \PHPStanVendor\Nette\Utils\Reflection::getUseStatements($method->getDeclaringClass()) : null,
				$method->getDocComment(),
				self::hashParameters($method),
				PHP_VERSION_ID >= 70000 && $method->hasReturnType()
					? [(string) $method->getReturnType(), $method->getReturnType()->allowsNull()]
					: null,
			];
		}

		return md5(serialize($hash));
	}


	private static function hashParameters(\ReflectionFunctionAbstract $method)
	{
		$res = [];
		if (PHP_VERSION_ID < 70000 && $method->getNumberOfParameters() && $method->getFileName()) {
			$res[] = file($method->getFileName())[$method->getStartLine() - 1];
		}
		foreach ($method->getParameters() as $param) {
			$res[] = [
				$param->getName(),
				PHP_VERSION_ID >= 70000 ? [\PHPStanVendor\Nette\Utils\Reflection::getParameterType($param), $param->allowsNull()] : null,
				$param->isVariadic(),
				$param->isDefaultValueAvailable()
					? [\PHPStanVendor\Nette\Utils\Reflection::getParameterDefaultValue($param)]
					: null,
			];
		}
		return $res;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI\Extensions;


/**
 * Constant definitions.
 */
class ConstantsExtension extends \PHPStanVendor\Nette\DI\CompilerExtension
{
	public function afterCompile(\PHPStanVendor\Nette\PhpGenerator\ClassType $class)
	{
		foreach ($this->getConfig() as $name => $value) {
			$class->getMethod('initialize')->addBody('define(?, ?);', [$name, $value]);
		}
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI\Extensions;


/**
 * DI extension.
 */
class DIExtension extends \PHPStanVendor\Nette\DI\CompilerExtension
{
	public $defaults = [
		'debugger' => true,
		'accessors' => false,
		'excluded' => [],
		'parentClass' => null,
	];

	/** @var bool */
	private $debugMode;

	/** @var int */
	private $time;


	public function __construct($debugMode = false)
	{
		$this->debugMode = $debugMode;
		$this->time = microtime(true);
	}


	public function loadConfiguration()
	{
		$config = $this->validateConfig($this->defaults);
		$builder = $this->getContainerBuilder();
		$builder->addExcludedClasses($config['excluded']);
	}


	public function afterCompile(\PHPStanVendor\Nette\PhpGenerator\ClassType $class)
	{
		if ($this->config['parentClass']) {
			$class->setExtends($this->config['parentClass']);
		}

		$initialize = $class->getMethod('initialize');
		$builder = $this->getContainerBuilder();

		if ($this->debugMode && $this->config['debugger']) {
			\PHPStanVendor\Nette\Bridges\DITracy\ContainerPanel::$compilationTime = $this->time;
			$initialize->addBody($builder->formatPhp('?;', [
				new \PHPStanVendor\Nette\DI\Statement('@\PHPStanVendor\Tracy\Bar::addPanel', [new \PHPStanVendor\Nette\DI\Statement(\PHPStanVendor\Nette\Bridges\DITracy\ContainerPanel::class)]),
			]));
		}

		foreach (array_filter($builder->findByTag('run')) as $name => $on) {
			$initialize->addBody('$this->getService(?);', [$name]);
		}
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI\Extensions;


/**
 * Decorators for services.
 */
class DecoratorExtension extends \PHPStanVendor\Nette\DI\CompilerExtension
{
	public $defaults = [
		'setup' => [],
		'tags' => [],
		'inject' => null,
	];


	public function beforeCompile()
	{
		foreach ($this->getConfig() as $type => $info) {
			$info = $this->validateConfig($this->defaults, $info, $this->prefix($type));
			if ($info['inject'] !== null) {
				$info['tags'][\PHPStanVendor\Nette\DI\Extensions\InjectExtension::TAG_INJECT] = $info['inject'];
			}
			$info = \PHPStanVendor\Nette\DI\Helpers::filterArguments($info);
			$this->addSetups($type, (array) $info['setup']);
			$this->addTags($type, (array) $info['tags']);
		}
	}


	public function addSetups($type, array $setups)
	{
		foreach ($this->findByType($type) as $def) {
			foreach ($setups as $setup) {
				if (is_array($setup)) {
					$setup = new \PHPStanVendor\Nette\DI\Statement(key($setup), array_values($setup));
				}
				$def->addSetup($setup);
			}
		}
	}


	public function addTags($type, array $tags)
	{
		$tags = \PHPStanVendor\Nette\Utils\Arrays::normalize($tags, true);
		foreach ($this->findByType($type) as $def) {
			$def->setTags($def->getTags() + $tags);
		}
	}


	private function findByType($type)
	{
		return array_filter($this->getContainerBuilder()->getDefinitions(), function ($def) use ($type) {
			return is_a($def->getType(), $type, true) || is_a($def->getImplement(), $type, true);
		});
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI\Extensions;


/**
 * Enables registration of other extensions in $config file
 */
class ExtensionsExtension extends \PHPStanVendor\Nette\DI\CompilerExtension
{
	public function loadConfiguration()
	{
		foreach ($this->getConfig() as $name => $class) {
			if (is_int($name)) {
				$name = null;
			}
			if ($class instanceof \PHPStanVendor\Nette\DI\Statement) {
				$rc = new \ReflectionClass($class->getEntity());
				$this->compiler->addExtension($name, $rc->newInstanceArgs($class->arguments));
			} else {
				$this->compiler->addExtension($name, new $class);
			}
		}
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI\Extensions;


/**
 * Calls inject methods and fills @inject properties.
 */
class InjectExtension extends \PHPStanVendor\Nette\DI\CompilerExtension
{
	const TAG_INJECT = 'inject';


	public function beforeCompile()
	{
		foreach ($this->getContainerBuilder()->getDefinitions() as $def) {
			if ($def->getTag(self::TAG_INJECT) && $def->getType()) {
				$this->updateDefinition($def);
			}
		}
	}


	private function updateDefinition(\PHPStanVendor\Nette\DI\ServiceDefinition $def)
	{
		$class = $def->getType();
		$setups = $def->getSetup();

		foreach (self::getInjectProperties($class) as $property => $type) {
			$builder = $this->getContainerBuilder();
			$inject = new \PHPStanVendor\Nette\DI\Statement('$' . $property, ['@\\' . ltrim($type, '\\')]);
			foreach ($setups as $key => $setup) {
				if ($setup->getEntity() === $inject->getEntity()) {
					$inject = $setup;
					$builder = null;
					unset($setups[$key]);
				}
			}
			self::checkType($class, $property, $type, $builder);
			array_unshift($setups, $inject);
		}

		foreach (array_reverse(self::getInjectMethods($def->getType())) as $method) {
			$inject = new \PHPStanVendor\Nette\DI\Statement($method);
			foreach ($setups as $key => $setup) {
				if ($setup->getEntity() === $inject->getEntity()) {
					$inject = $setup;
					unset($setups[$key]);
				}
			}
			array_unshift($setups, $inject);
		}

		$def->setSetup($setups);
	}


	/**
	 * Generates list of inject methods.
	 * @return array
	 * @internal
	 */
	public static function getInjectMethods($class)
	{
		$res = [];
		foreach (get_class_methods($class) as $name) {
			if (substr($name, 0, 6) === 'inject') {
				$res[$name] = (new \ReflectionMethod($class, $name))->getDeclaringClass()->getName();
			}
		}
		uksort($res, function ($a, $b) use ($res) {
			return $res[$a] === $res[$b]
				? strcmp($a, $b)
				: (is_a($res[$a], $res[$b], true) ? 1 : -1);
		});
		return array_keys($res);
	}


	/**
	 * Generates list of properties with annotation @inject.
	 * @return array
	 * @internal
	 */
	public static function getInjectProperties($class)
	{
		$res = [];
		foreach (get_class_vars($class) as $name => $foo) {
			$rp = new \ReflectionProperty($class, $name);
			if (\PHPStanVendor\Nette\DI\Helpers::parseAnnotation($rp, 'inject') !== null) {
				if ($type = \PHPStanVendor\Nette\DI\Helpers::parseAnnotation($rp, 'var')) {
					$type = \PHPStanVendor\Nette\Utils\Reflection::expandClassName($type, \PHPStanVendor\Nette\Utils\Reflection::getPropertyDeclaringClass($rp));
				}
				$res[$name] = $type;
			}
		}
		ksort($res);
		return $res;
	}


	/**
	 * Calls all methods starting with with "inject" using autowiring.
	 * @return void
	 */
	public static function callInjects(\PHPStanVendor\Nette\DI\Container $container, $service)
	{
		if (!is_object($service)) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException(sprintf('Service must be object, %s given.', gettype($service)));
		}

		foreach (self::getInjectMethods($service) as $method) {
			$container->callMethod([$service, $method]);
		}

		foreach (self::getInjectProperties(get_class($service)) as $property => $type) {
			self::checkType($service, $property, $type, $container);
			$service->$property = $container->getByType($type);
		}
	}


	/** @internal */
	private static function checkType($class, $name, $type, $container = null)
	{
		$propName = \PHPStanVendor\Nette\Utils\Reflection::toString(new \ReflectionProperty($class, $name));
		if (!$type) {
			throw new \PHPStanVendor\Nette\InvalidStateException("Property $propName has no @var annotation.");
		} elseif (!class_exists($type) && !interface_exists($type)) {
			throw new \PHPStanVendor\Nette\InvalidStateException("Class or interface '$type' used in @var annotation at $propName not found. Check annotation and 'use' statements.");
		} elseif ($container && !$container->getByType($type, false)) {
			throw new \PHPStanVendor\Nette\InvalidStateException("Service of type $type used in @var annotation at $propName not found. Did you register it in configuration file?");
		}
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI\Extensions;


/**
 * PHP directives definition.
 */
class PhpExtension extends \PHPStanVendor\Nette\DI\CompilerExtension
{
	public function afterCompile(\PHPStanVendor\Nette\PhpGenerator\ClassType $class)
	{
		$initialize = $class->getMethod('initialize');
		foreach ($this->getConfig() as $name => $value) {
			if ($value === null) {
				continue;

			} elseif (!is_scalar($value)) {
				throw new \PHPStanVendor\Nette\InvalidStateException("Configuration value for directive '$name' is not scalar.");

			} elseif ($name === 'include_path') {
				$initialize->addBody('set_include_path(?);', [str_replace(';', PATH_SEPARATOR, $value)]);

			} elseif ($name === 'ignore_user_abort') {
				$initialize->addBody('ignore_user_abort(?);', [$value]);

			} elseif ($name === 'max_execution_time') {
				$initialize->addBody('set_time_limit(?);', [$value]);

			} elseif ($name === 'date.timezone') {
				$initialize->addBody('date_default_timezone_set(?);', [$value]);

			} elseif (function_exists('ini_set')) {
				$initialize->addBody('ini_set(?, ?);', [$name, $value]);

			} elseif (ini_get($name) != $value) { // intentionally ==
				throw new \PHPStanVendor\Nette\NotSupportedException('Required function ini_set() is disabled.');
			}
		}
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI;


/**
 * The DI helpers.
 * @internal
 */
class Helpers
{
	use \PHPStanVendor\Nette\StaticClass;

	/**
	 * Expands %placeholders%.
	 * @param  mixed
	 * @param  array
	 * @param  bool|array
	 * @return mixed
	 * @throws Nette\InvalidArgumentException
	 */
	public static function expand($var, array $params, $recursive = false)
	{
		if (is_array($var)) {
			$res = [];
			foreach ($var as $key => $val) {
				$res[$key] = self::expand($val, $params, $recursive);
			}
			return $res;

		} elseif ($var instanceof \PHPStanVendor\Nette\DI\Statement) {
			return new \PHPStanVendor\Nette\DI\Statement(self::expand($var->getEntity(), $params, $recursive), self::expand($var->arguments, $params, $recursive));

		} elseif (!is_string($var)) {
			return $var;
		}

		$parts = preg_split('#%([\w.-]*)%#i', $var, -1, PREG_SPLIT_DELIM_CAPTURE);
		$res = [];
		$php = false;
		foreach ($parts as $n => $part) {
			if ($n % 2 === 0) {
				$res[] = $part;

			} elseif ($part === '') {
				$res[] = '%';

			} elseif (isset($recursive[$part])) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException(sprintf('Circular reference detected for variables: %s.', implode(', ', array_keys($recursive))));

			} else {
				try {
					$val = \PHPStanVendor\Nette\Utils\Arrays::get($params, explode('.', $part));
				} catch (\PHPStanVendor\Nette\InvalidArgumentException $e) {
					throw new \PHPStanVendor\Nette\InvalidArgumentException("Missing parameter '$part'.", 0, $e);
				}
				if ($recursive) {
					$val = self::expand($val, $params, (is_array($recursive) ? $recursive : []) + [$part => 1]);
				}
				if (strlen($part) + 2 === strlen($var)) {
					return $val;
				}
				if ($val instanceof \PHPStanVendor\Nette\PhpGenerator\PhpLiteral) {
					$php = true;
				} elseif (!is_scalar($val)) {
					throw new \PHPStanVendor\Nette\InvalidArgumentException("Unable to concatenate non-scalar parameter '$part' into '$var'.");
				}
				$res[] = $val;
			}
		}
		if ($php) {
			$res = array_filter($res, function ($val) { return $val !== ''; });
			$res = array_map(function ($val) { return $val instanceof \PHPStanVendor\Nette\PhpGenerator\PhpLiteral ? "($val)" : var_export((string) $val, true); }, $res);
			return new \PHPStanVendor\Nette\PhpGenerator\PhpLiteral(implode(' . ', $res));
		}
		return implode('', $res);
	}


	/**
	 * Generates list of arguments using autowiring.
	 * @return array
	 */
	public static function autowireArguments(\ReflectionFunctionAbstract $method, array $arguments, $container)
	{
		$optCount = 0;
		$num = -1;
		$res = [];
		$methodName = \PHPStanVendor\Nette\Utils\Reflection::toString($method) . '()';

		foreach ($method->getParameters() as $num => $parameter) {
			if (!$parameter->isVariadic() && array_key_exists($parameter->getName(), $arguments)) {
				$res[$num] = $arguments[$parameter->getName()];
				unset($arguments[$parameter->getName()], $arguments[$num]);
				$optCount = 0;

			} elseif (array_key_exists($num, $arguments)) {
				$res[$num] = $arguments[$num];
				unset($arguments[$num]);
				$optCount = 0;

			} elseif (($type = \PHPStanVendor\Nette\Utils\Reflection::getParameterType($parameter)) && !\PHPStanVendor\Nette\Utils\Reflection::isBuiltinType($type)) {
				$res[$num] = $container->getByType($type, false);
				if ($res[$num] === null) {
					if ($parameter->allowsNull()) {
						$optCount++;
					} elseif (class_exists($type) || interface_exists($type)) {
						throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Service of type $type needed by $methodName not found. Did you register it in configuration file?");
					} else {
						throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Class $type needed by $methodName not found. Check type hint and 'use' statements.");
					}
				} else {
					if ($container instanceof \PHPStanVendor\Nette\DI\ContainerBuilder) {
						$res[$num] = '@' . $res[$num];
					}
					$optCount = 0;
				}

			} elseif (($type && $parameter->allowsNull()) || $parameter->isOptional() || $parameter->isDefaultValueAvailable()) {
				// !optional + defaultAvailable = func($a = null, $b) since 5.4.7
				// optional + !defaultAvailable = i.e. Exception::__construct, mysqli::mysqli, ...
				$res[$num] = $parameter->isDefaultValueAvailable() ? \PHPStanVendor\Nette\Utils\Reflection::getParameterDefaultValue($parameter) : null;
				$optCount++;

			} else {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Parameter \${$parameter->getName()} in $methodName has no class type hint or default value, so its value must be specified.");
			}
		}

		// extra parameters
		while (array_key_exists(++$num, $arguments)) {
			$res[$num] = $arguments[$num];
			unset($arguments[$num]);
			$optCount = 0;
		}
		if ($arguments) {
			throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Unable to pass specified arguments to $methodName.");
		}

		return $optCount ? array_slice($res, 0, -$optCount) : $res;
	}


	/**
	 * Removes ... and process constants recursively.
	 * @return array
	 */
	public static function filterArguments(array $args)
	{
		foreach ($args as $k => $v) {
			if ($v === '...') {
				unset($args[$k]);
			} elseif (is_string($v) && preg_match('#^[\w\\\\]*::[A-Z][A-Z0-9_]*\z#', $v, $m)) {
				$args[$k] = constant(ltrim($v, ':'));
			} elseif (is_array($v)) {
				$args[$k] = self::filterArguments($v);
			} elseif ($v instanceof \PHPStanVendor\Nette\DI\Statement) {
				$tmp = self::filterArguments([$v->getEntity()]);
				$args[$k] = new \PHPStanVendor\Nette\DI\Statement($tmp[0], self::filterArguments($v->arguments));
			}
		}
		return $args;
	}


	/**
	 * Replaces @extension with real extension name in service definition.
	 * @param  mixed
	 * @param  string
	 * @return mixed
	 */
	public static function prefixServiceName($config, $namespace)
	{
		if (is_string($config)) {
			if (strncmp($config, '@extension.', 10) === 0) {
				$config = '@' . $namespace . '.' . substr($config, 11);
			}
		} elseif ($config instanceof \PHPStanVendor\Nette\DI\Statement) {
			return new \PHPStanVendor\Nette\DI\Statement(
				self::prefixServiceName($config->getEntity(), $namespace),
				self::prefixServiceName($config->arguments, $namespace)
			);
		} elseif (is_array($config)) {
			foreach ($config as &$val) {
				$val = self::prefixServiceName($val, $namespace);
			}
		}
		return $config;
	}


	/**
	 * Returns an annotation value.
	 * @return string|null
	 */
	public static function parseAnnotation(\Reflector $ref, $name)
	{
		if (!\PHPStanVendor\Nette\Utils\Reflection::areCommentsAvailable()) {
			throw new \PHPStanVendor\Nette\InvalidStateException('You have to enable phpDoc comments in opcode cache.');
		}
		$name = preg_quote($name, '#');
		if ($ref->getDocComment() && preg_match("#[\\s*]@$name(?:\\s++([^@]\\S*)?|$)#", trim($ref->getDocComment(), '/*'), $m)) {
			return isset($m[1]) ? $m[1] : '';
		}
	}


	/**
	 * @return string|null
	 */
	public static function getReturnType(\ReflectionFunctionAbstract $func)
	{
		if ($type = \PHPStanVendor\Nette\Utils\Reflection::getReturnType($func)) {
			return $type;
		} elseif ($type = preg_replace('#[|\s].*#', '', (string) self::parseAnnotation($func, 'return'))) {
			if ($type === 'object' || $type === 'mixed') {
				return null;
			} elseif ($func instanceof \ReflectionMethod) {
				return $type === 'static' || $type === '$this'
					? $func->getDeclaringClass()->getName()
					: \PHPStanVendor\Nette\Utils\Reflection::expandClassName($type, $func->getDeclaringClass());
			} else {
				return $type;
			}
		}
	}


	public static function normalizeClass($type)
	{
		return class_exists($type) || interface_exists($type)
			? (new \ReflectionClass($type))->getName()
			: $type;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI;


/**
 * Container PHP code generator.
 */
class PhpGenerator
{
	/** @var ContainerBuilder */
	private $builder;

	/** @var string */
	private $className;

	/** @var Nette\PhpGenerator\ClassType[] */
	private $generatedClasses = [];

	/** @var string */
	private $currentService;


	public function __construct(\PHPStanVendor\Nette\DI\ContainerBuilder $builder)
	{
		$this->builder = $builder;
	}


	/**
	 * Generates PHP classes. First class is the container.
	 * @return Nette\PhpGenerator\ClassType[]
	 */
	public function generate($className)
	{
		$this->builder->complete();

		$this->generatedClasses = [];
		$this->className = $className;
		$containerClass = $this->generatedClasses[] = new \PHPStanVendor\Nette\PhpGenerator\ClassType($this->className);
		$containerClass->setExtends(\PHPStanVendor\Nette\DI\Container::class);
		$containerClass->addMethod('__construct')
			->addBody('$this->parameters = $params;')
			->addBody('$this->parameters += ?;', [$this->builder->parameters])
			->addParameter('params', [])
				->setTypeHint('array');

		$definitions = $this->builder->getDefinitions();
		ksort($definitions);

		$meta = $containerClass->addProperty('meta')
			->setVisibility('protected')
			->setValue([\PHPStanVendor\Nette\DI\Container::TYPES => $this->builder->getClassList()]);

		foreach ($definitions as $name => $def) {
			$meta->value[\PHPStanVendor\Nette\DI\Container::SERVICES][$name] = $def->getType() ?: null;
			foreach ($def->getTags() as $tag => $value) {
				$meta->value[\PHPStanVendor\Nette\DI\Container::TAGS][$tag][$name] = $value;
			}
		}

		foreach ($definitions as $name => $def) {
			try {
				$name = (string) $name;
				$methodName = \PHPStanVendor\Nette\DI\Container::getMethodName($name);
				if (!\PHPStanVendor\Nette\PhpGenerator\Helpers::isIdentifier($methodName)) {
					throw new \PHPStanVendor\Nette\DI\ServiceCreationException('Name contains invalid characters.');
				}
				$containerClass->addMethod($methodName)
					->addComment(PHP_VERSION_ID < 70000 ? '@return ' . ($def->getImplement() ?: $def->getType()) : '')
					->setReturnType(PHP_VERSION_ID >= 70000 ? ($def->getImplement() ?: $def->getType()) : null)
					->setBody($name === \PHPStanVendor\Nette\DI\ContainerBuilder::THIS_CONTAINER ? 'return $this;' : $this->generateService($name))
					->setParameters($def->getImplement() ? [] : $this->convertParameters($def->parameters));
			} catch (\Exception $e) {
				throw new \PHPStanVendor\Nette\DI\ServiceCreationException("Service '$name': " . $e->getMessage(), 0, $e);
			}
		}

		$aliases = $this->builder->getAliases();
		ksort($aliases);
		$meta->value[\PHPStanVendor\Nette\DI\Container::ALIASES] = $aliases;

		return $this->generatedClasses;
	}


	/**
	 * Generates body of service method.
	 * @return string
	 */
	private function generateService($name)
	{
		$def = $this->builder->getDefinition($name);

		if ($def->isDynamic()) {
			return \PHPStanVendor\Nette\PhpGenerator\Helpers::formatArgs('throw new Nette\\DI\\ServiceCreationException(?);',
				["Unable to create dynamic service '$name', it must be added using addService()"]
			);
		}

		$entity = $def->getFactory()->getEntity();
		$serviceRef = $this->builder->getServiceName($entity);
		$factory = $serviceRef && !$def->getFactory()->arguments && !$def->getSetup() && $def->getImplementMode() !== $def::IMPLEMENT_MODE_CREATE
			? new \PHPStanVendor\Nette\DI\Statement(['@' . \PHPStanVendor\Nette\DI\ContainerBuilder::THIS_CONTAINER, 'getService'], [$serviceRef])
			: $def->getFactory();

		$this->currentService = null;
		$code = '$service = ' . $this->formatStatement($factory) . ";\n";

		if ((PHP_VERSION_ID < 70000 || $def->getSetup()) && ($type = $def->getType()) && !$serviceRef && $type !== $entity
			&& !(is_string($entity) && preg_match('#^[\w\\\\]+\z#', $entity) && is_subclass_of($entity, $type))
		) {
			$code .= \PHPStanVendor\Nette\PhpGenerator\Helpers::formatArgs("if (!\$service instanceof $type) {\n"
				. "\tthrow new \\PHPStanVendor\\Nette\\UnexpectedValueException(?);\n}\n",
				["Unable to create service '$name', value returned by factory is not $type type."]
			);
		}

		$this->currentService = $name;
		foreach ($def->getSetup() as $setup) {
			$code .= $this->formatStatement($setup) . ";\n";
		}

		$code .= 'return $service;';

		if (!$def->getImplement()) {
			return $code;
		}

		$factoryClass = (new \PHPStanVendor\Nette\PhpGenerator\ClassType)
			->addImplement($def->getImplement());

		$factoryClass->addProperty('container')
			->setVisibility('private');

		$factoryClass->addMethod('__construct')
			->addBody('$this->container = $container;')
			->addParameter('container')
				->setTypeHint($this->className);

		$rm = new \ReflectionMethod($def->getImplement(), $def->getImplementMode());

		$factoryClass->addMethod($def->getImplementMode())
			->setParameters($this->convertParameters($def->parameters))
			->setBody(str_replace('$this', '$this->container', $code))
			->setReturnType(PHP_VERSION_ID >= 70000 ? (\PHPStanVendor\Nette\Utils\Reflection::getReturnType($rm) ?: $def->getType()) : null);

		if (PHP_VERSION_ID < 70000) {
			$this->generatedClasses[] = $factoryClass;
			$factoryClass->setName(str_replace(['\\', '.'], '_', "{$this->className}_{$def->getImplement()}Impl_{$name}"));
			return "return new {$factoryClass->getName()}(\$this);";
		}

		return 'return new class ($this) ' . $factoryClass . ';';
	}


	/**
	 * Formats PHP code for class instantiating, function calling or property setting in PHP.
	 * @return string
	 */
	private function formatStatement(\PHPStanVendor\Nette\DI\Statement $statement)
	{
		$entity = $statement->getEntity();
		$arguments = $statement->arguments;

		if (is_string($entity) && \PHPStanVendor\Nette\Utils\Strings::contains($entity, '?')) { // PHP literal
			return $this->formatPhp($entity, $arguments);

		} elseif ($service = $this->builder->getServiceName($entity)) { // factory calling
			return $this->formatPhp('$this->?(...?)', [\PHPStanVendor\Nette\DI\Container::getMethodName($service), $arguments]);

		} elseif ($entity === 'not') { // operator
			return $this->formatPhp('!?', [$arguments[0]]);

		} elseif (is_string($entity)) { // class name
			return $this->formatPhp("new $entity" . ($arguments ? '(...?)' : ''), $arguments ? [$arguments] : []);

		} elseif ($entity[0] === '') { // globalFunc
			return $this->formatPhp("$entity[1](...?)", [$arguments]);

		} elseif ($entity[0] instanceof \PHPStanVendor\Nette\DI\Statement) {
			$inner = $this->formatPhp('?', [$entity[0]]);
			if (substr($inner, 0, 4) === 'new ') {
				$inner = "($inner)";
			}
			return $this->formatPhp("$inner->?(...?)", [$entity[1], $arguments]);

		} elseif ($entity[1][0] === '$') { // property getter, setter or appender
			$name = substr($entity[1], 1);
			if ($append = (substr($name, -2) === '[]')) {
				$name = substr($name, 0, -2);
			}
			if ($this->builder->getServiceName($entity[0])) {
				$prop = $this->formatPhp('?->?', [$entity[0], $name]);
			} else {
				$prop = $this->formatPhp($entity[0] . '::$?', [$name]);
			}
			return $arguments
				? $this->formatPhp($prop . ($append ? '[]' : '') . ' = ?', [$arguments[0]])
				: $prop;

		} elseif ($service = $this->builder->getServiceName($entity[0])) { // service method
			return $this->formatPhp('?->?(...?)', [$entity[0], $entity[1], $arguments]);

		} else { // static method
			return $this->formatPhp("$entity[0]::$entity[1](...?)", [$arguments]);
		}
	}


	/**
	 * Formats PHP statement.
	 * @return string
	 * @internal
	 */
	public function formatPhp($statement, $args)
	{
		array_walk_recursive($args, function (&$val) {
			if ($val instanceof \PHPStanVendor\Nette\DI\Statement) {
				$val = new \PHPStanVendor\Nette\PhpGenerator\PhpLiteral($this->formatStatement($val));

			} elseif (is_string($val) && substr($val, 0, 2) === '@@') { // escaped text @@
				$val = substr($val, 1);

			} elseif (is_string($val) && substr($val, 0, 1) === '@' && strlen($val) > 1) { // service reference
				$name = substr($val, 1);
				if ($name === \PHPStanVendor\Nette\DI\ContainerBuilder::THIS_CONTAINER) {
					$val = new \PHPStanVendor\Nette\PhpGenerator\PhpLiteral('$this');
				} elseif ($name === $this->currentService) {
					$val = new \PHPStanVendor\Nette\PhpGenerator\PhpLiteral('$service');
				} else {
					$val = new \PHPStanVendor\Nette\PhpGenerator\PhpLiteral($this->formatStatement(new \PHPStanVendor\Nette\DI\Statement(['@' . \PHPStanVendor\Nette\DI\ContainerBuilder::THIS_CONTAINER, 'getService'], [$name])));
				}
			}
		});
		return \PHPStanVendor\Nette\PhpGenerator\Helpers::formatArgs($statement, $args);
	}


	/**
	 * Converts parameters from ServiceDefinition to PhpGenerator.
	 * @return Nette\PhpGenerator\Parameter[]
	 */
	private function convertParameters(array $parameters)
	{
		$res = [];
		foreach ($parameters as $k => $v) {
			$tmp = explode(' ', is_int($k) ? $v : $k);
			$param = $res[] = new \PHPStanVendor\Nette\PhpGenerator\Parameter(end($tmp));
			if (!is_int($k)) {
				$param->setOptional(true)->setDefaultValue($v);
			}
			if (isset($tmp[1])) {
				$param->setTypeHint($tmp[0]);
			}
		}
		return $res;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI;


/**
 * PHP reflection helpers.
 * @internal
 * @deprecated
 */
class PhpReflection
{
	use \PHPStanVendor\Nette\StaticClass;

	/**
	 * Returns an annotation value.
	 * @return string|null
	 */
	public static function parseAnnotation(\Reflector $ref, $name)
	{
		static $ok;
		if (!$ok) {
			if (!(new \ReflectionMethod(__METHOD__))->getDocComment()) {
				throw new \PHPStanVendor\Nette\InvalidStateException('You have to enable phpDoc comments in opcode cache.');
			}
			$ok = true;
		}
		$name = preg_quote($name, '#');
		if ($ref->getDocComment() && preg_match("#[\\s*]@$name(?:\\s++([^@]\\S*)?|$)#", trim($ref->getDocComment(), '/*'), $m)) {
			return isset($m[1]) ? $m[1] : '';
		}
	}


	/**
	 * Returns declaring class or trait.
	 * @return \ReflectionClass
	 */
	public static function getDeclaringClass(\ReflectionProperty $prop)
	{
		foreach ($prop->getDeclaringClass()->getTraits() as $trait) {
			if ($trait->hasProperty($prop->getName())) {
				return self::getDeclaringClass($trait->getProperty($prop->getName()));
			}
		}
		return $prop->getDeclaringClass();
	}


	/**
	 * @return string|null
	 */
	public static function getParameterType(\ReflectionParameter $param)
	{
		if (PHP_VERSION_ID >= 70000) {
			$type = $param->hasType() ? (string) $param->getType() : null;
			return strtolower($type) === 'self' ? $param->getDeclaringClass()->getName() : $type;
		} elseif ($param->isArray() || $param->isCallable()) {
			return $param->isArray() ? 'array' : 'callable';
		} else {
			try {
				return ($ref = $param->getClass()) ? $ref->getName() : null;
			} catch (\ReflectionException $e) {
				if (preg_match('#Class (.+) does not exist#', $e->getMessage(), $m)) {
					return $m[1];
				}
				throw $e;
			}
		}
	}


	/**
	 * @return string|null
	 */
	public static function getReturnType(\ReflectionFunctionAbstract $func)
	{
		if (PHP_VERSION_ID >= 70000 && $func->hasReturnType()) {
			$type = (string) $func->getReturnType();
			return strtolower($type) === 'self' ? $func->getDeclaringClass()->getName() : $type;
		}
		$type = preg_replace('#[|\s].*#', '', (string) self::parseAnnotation($func, 'return'));
		if ($type) {
			return $func instanceof \ReflectionMethod
				? self::expandClassName($type, $func->getDeclaringClass())
				: ltrim($type, '\\');
		}
	}


	/**
	 * @param  string
	 * @return bool
	 */
	public static function isBuiltinType($type)
	{
		return in_array(strtolower($type), ['string', 'int', 'float', 'bool', 'array', 'callable'], true);
	}


	/**
	 * Returns class and all its descendants.
	 * @return string[]
	 */
	public static function getClassTree(\ReflectionClass $class)
	{
		$addTraits = function ($types) use (&$addTraits) {
			if ($traits = array_merge(...array_map('class_uses', array_values($types)))) {
				$types += $traits + $addTraits($traits);
			}
			return $types;
		};
		$class = $class->getName();
		return array_values($addTraits([$class] + class_parents($class) + class_implements($class)));
	}


	/**
	 * Expands class name into full name.
	 * @param  string
	 * @return string  full name
	 * @throws Nette\InvalidArgumentException
	 */
	public static function expandClassName($name, \ReflectionClass $rc)
	{
		$lower = strtolower($name);
		if (empty($name)) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException('Class name must not be empty.');

		} elseif (self::isBuiltinType($lower)) {
			return $lower;

		} elseif ($lower === 'self' || $lower === 'static' || $lower === '$this') {
			return $rc->getName();

		} elseif ($name[0] === '\\') { // fully qualified name
			return ltrim($name, '\\');
		}

		$uses = self::getUseStatements($rc);
		$parts = explode('\\', $name, 2);
		if (isset($uses[$parts[0]])) {
			$parts[0] = $uses[$parts[0]];
			return implode('\\', $parts);

		} elseif ($rc->inNamespace()) {
			return $rc->getNamespaceName() . '\\' . $name;

		} else {
			return $name;
		}
	}


	/**
	 * @return array of [alias => class]
	 */
	public static function getUseStatements(\ReflectionClass $class)
	{
		static $cache = [];
		if (!isset($cache[$name = $class->getName()])) {
			if ($class->isInternal()) {
				$cache[$name] = [];
			} else {
				$code = file_get_contents($class->getFileName());
				$cache = self::parseUseStatements($code, $name) + $cache;
			}
		}
		return $cache[$name];
	}


	/**
	 * Parses PHP code.
	 * @param  string
	 * @return array of [class => [alias => class, ...]]
	 */
	public static function parseUseStatements($code, $forClass = null)
	{
		$tokens = token_get_all($code);
		$namespace = $class = $classLevel = $level = null;
		$res = $uses = [];

		while ($token = current($tokens)) {
			next($tokens);
			switch (is_array($token) ? $token[0] : $token) {
				case T_NAMESPACE:
					$namespace = ltrim(self::fetch($tokens, [T_STRING, T_NS_SEPARATOR]) . '\\', '\\');
					$uses = [];
					break;

				case T_CLASS:
				case T_INTERFACE:
				case T_TRAIT:
					if ($name = self::fetch($tokens, T_STRING)) {
						$class = $namespace . $name;
						$classLevel = $level + 1;
						$res[$class] = $uses;
						if ($class === $forClass) {
							return $res;
						}
					}
					break;

				case T_USE:
					while (!$class && ($name = self::fetch($tokens, [T_STRING, T_NS_SEPARATOR]))) {
						$name = ltrim($name, '\\');
						if (self::fetch($tokens, '{')) {
							while ($suffix = self::fetch($tokens, [T_STRING, T_NS_SEPARATOR])) {
								if (self::fetch($tokens, T_AS)) {
									$uses[self::fetch($tokens, T_STRING)] = $name . $suffix;
								} else {
									$tmp = explode('\\', $suffix);
									$uses[end($tmp)] = $name . $suffix;
								}
								if (!self::fetch($tokens, ',')) {
									break;
								}
							}

						} elseif (self::fetch($tokens, T_AS)) {
							$uses[self::fetch($tokens, T_STRING)] = $name;

						} else {
							$tmp = explode('\\', $name);
							$uses[end($tmp)] = $name;
						}
						if (!self::fetch($tokens, ',')) {
							break;
						}
					}
					break;

				case T_CURLY_OPEN:
				case T_DOLLAR_OPEN_CURLY_BRACES:
				case '{':
					$level++;
					break;

				case '}':
					if ($level === $classLevel) {
						$class = $classLevel = null;
					}
					$level--;
			}
		}

		return $res;
	}


	private static function fetch(&$tokens, $take)
	{
		$res = null;
		while ($token = current($tokens)) {
			list($token, $s) = is_array($token) ? $token : [$token, $token];
			if (in_array($token, (array) $take, true)) {
				$res .= $s;
			} elseif (!in_array($token, [T_DOC_COMMENT, T_WHITESPACE, T_COMMENT], true)) {
				break;
			}
			next($tokens);
		}
		return $res;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI;


/**
 * Definition used by ContainerBuilder.
 *
 * @property string|null $class
 * @property Statement|null $factory
 * @property Statement[] $setup
 */
class ServiceDefinition
{
	use \PHPStanVendor\Nette\SmartObject;

	const
		IMPLEMENT_MODE_CREATE = 'create',
		IMPLEMENT_MODE_GET = 'get';

	/** @var array */
	public $parameters = [];

	/** @var string|null  class or interface name */
	private $type;

	/** @var Statement|null */
	private $factory;

	/** @var Statement[] */
	private $setup = [];

	/** @var array */
	private $tags = [];

	/** @var bool|string[] */
	private $autowired = true;

	/** @var bool */
	private $dynamic = false;

	/** @var string|null  interface name */
	private $implement;

	/** @var string|null  create | get */
	private $implementMode;

	/** @var callable */
	private $notifier = 'pi'; // = noop


	/**
	 * @param  string|null
	 * @return static
	 * @deprecated
	 */
	public function setClass($type, array $args = [])
	{
		call_user_func($this->notifier);
		$this->type = $type;
		if ($args) {
			$this->setFactory($type, $args);
		}
		return $this;
	}


	/**
	 * @return string|null
	 * @deprecated
	 */
	public function getClass()
	{
		return $this->type;
	}


	/**
	 * @param  string|null
	 * @return static
	 */
	public function setType($type)
	{
		call_user_func($this->notifier);
		$this->type = $type;
		return $this;
	}


	/**
	 * @return string|null
	 */
	public function getType()
	{
		return $this->type;
	}


	/**
	 * @return static
	 */
	public function setFactory($factory, array $args = [])
	{
		call_user_func($this->notifier);
		$this->factory = $factory instanceof \PHPStanVendor\Nette\DI\Statement ? $factory : new \PHPStanVendor\Nette\DI\Statement($factory, $args);
		return $this;
	}


	/**
	 * @return Statement|null
	 */
	public function getFactory()
	{
		return $this->factory;
	}


	/**
	 * @return string|array|ServiceDefinition|null
	 */
	public function getEntity()
	{
		return $this->factory ? $this->factory->getEntity() : null;
	}


	/**
	 * @return static
	 */
	public function setArguments(array $args = [])
	{
		if (!$this->factory) {
			$this->factory = new \PHPStanVendor\Nette\DI\Statement($this->type);
		}
		$this->factory->arguments = $args;
		return $this;
	}


	/**
	 * @param  Statement[]
	 * @return static
	 */
	public function setSetup(array $setup)
	{
		foreach ($setup as $v) {
			if (!$v instanceof \PHPStanVendor\Nette\DI\Statement) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException('Argument must be \PHPStanVendor\Nette\DI\Statement[].');
			}
		}
		$this->setup = $setup;
		return $this;
	}


	/**
	 * @return Statement[]
	 */
	public function getSetup()
	{
		return $this->setup;
	}


	/**
	 * @return static
	 */
	public function addSetup($entity, array $args = [])
	{
		$this->setup[] = $entity instanceof \PHPStanVendor\Nette\DI\Statement ? $entity : new \PHPStanVendor\Nette\DI\Statement($entity, $args);
		return $this;
	}


	/**
	 * @return static
	 */
	public function setParameters(array $params)
	{
		$this->parameters = $params;
		return $this;
	}


	/**
	 * @return array
	 */
	public function getParameters()
	{
		return $this->parameters;
	}


	/**
	 * @return static
	 */
	public function setTags(array $tags)
	{
		$this->tags = $tags;
		return $this;
	}


	/**
	 * @return array
	 */
	public function getTags()
	{
		return $this->tags;
	}


	/**
	 * @return static
	 */
	public function addTag($tag, $attr = true)
	{
		$this->tags[$tag] = $attr;
		return $this;
	}


	/**
	 * @return mixed
	 */
	public function getTag($tag)
	{
		return isset($this->tags[$tag]) ? $this->tags[$tag] : null;
	}


	/**
	 * @param  bool|string|string[]
	 * @return static
	 */
	public function setAutowired($state = true)
	{
		call_user_func($this->notifier);
		$this->autowired = is_string($state) || is_array($state) ? (array) $state : (bool) $state;
		return $this;
	}


	/**
	 * @return bool|string[]
	 */
	public function isAutowired()
	{
		return $this->autowired;
	}


	/**
	 * @return bool|string[]
	 */
	public function getAutowired()
	{
		return $this->autowired;
	}


	/**
	 * @param  bool
	 * @return static
	 */
	public function setDynamic($state = true)
	{
		$this->dynamic = (bool) $state;
		return $this;
	}


	/**
	 * @return bool
	 */
	public function isDynamic()
	{
		return $this->dynamic;
	}


	/**
	 * @param  string
	 * @return static
	 */
	public function setImplement($interface)
	{
		call_user_func($this->notifier);
		$this->implement = $interface;
		return $this;
	}


	/**
	 * @return string|null
	 */
	public function getImplement()
	{
		return $this->implement;
	}


	/**
	 * @param  string
	 * @return static
	 */
	public function setImplementMode($mode)
	{
		if (!in_array($mode, [self::IMPLEMENT_MODE_CREATE, self::IMPLEMENT_MODE_GET], true)) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException('Argument must be get|create.');
		}
		$this->implementMode = $mode;
		return $this;
	}


	/**
	 * @return string|null
	 */
	public function getImplementMode()
	{
		return $this->implementMode;
	}


	/** @deprecated */
	public function setImplementType($type)
	{
		trigger_error(__METHOD__ . '() is deprecated, use setImplementMode()', E_USER_DEPRECATED);
		return $this->setImplementMode($type);
	}


	/** @deprecated */
	public function getImplementType()
	{
		trigger_error(__METHOD__ . '() is deprecated, use getImplementMode()', E_USER_DEPRECATED);
		return $this->implementMode;
	}


	/** @return static */
	public function setInject($state = true)
	{
		//trigger_error(__METHOD__ . '() is deprecated.', E_USER_DEPRECATED);
		return $this->addTag(\PHPStanVendor\Nette\DI\Extensions\InjectExtension::TAG_INJECT, $state);
	}


	/** @return bool|null */
	public function getInject()
	{
		//trigger_error(__METHOD__ . '() is deprecated.', E_USER_DEPRECATED);
		return $this->getTag(\PHPStanVendor\Nette\DI\Extensions\InjectExtension::TAG_INJECT);
	}


	/**
	 * @internal
	 */
	public function setNotifier(callable $notifier)
	{
		$this->notifier = $notifier;
	}


	public function __clone()
	{
		$this->factory = unserialize(serialize($this->factory));
		$this->setup = unserialize(serialize($this->setup));
		$this->notifier = 'pi';
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI;


/**
 * Assignment or calling statement.
 *
 * @property string|array|ServiceDefinition|null $entity
 */
class Statement
{
	use \PHPStanVendor\Nette\SmartObject;

	/** @var array */
	public $arguments;

	/** @var string|array|ServiceDefinition|null  class|method|$property */
	private $entity;


	/**
	 * @param  string|array|ServiceDefinition|null
	 */
	public function __construct($entity, array $arguments = [])
	{
		if (!is_string($entity) && !(is_array($entity) && isset($entity[0], $entity[1]))
			&& !$entity instanceof \PHPStanVendor\Nette\DI\ServiceDefinition && $entity !== null
		) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException('Argument is not valid Statement entity.');
		}
		$this->entity = $entity;
		$this->arguments = $arguments;
	}


	/** @deprecated */
	public function setEntity($entity)
	{
		trigger_error(__METHOD__ . ' is deprecated, change Statement object itself.', E_USER_DEPRECATED);
		$this->__construct($entity, $this->arguments);
		return $this;
	}


	public function getEntity()
	{
		return $this->entity;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\DI;


/**
 * Service not found exception.
 */
class MissingServiceException extends \PHPStanVendor\Nette\InvalidStateException
{
}


/**
 * Service creation exception.
 */
class ServiceCreationException extends \PHPStanVendor\Nette\InvalidStateException
{
}
{
	"name": "nette/finder",
	"description": "Nette Finder: Files Searching",
	"homepage": "https://nette.org",
	"license": ["BSD-3-Clause", "GPL-2.0", "GPL-3.0"],
	"authors": [
		{
			"name": "David Grudl",
			"homepage": "https://davidgrudl.com"
		},
		{
			"name": "Nette Community",
			"homepage": "https://nette.org/contributors"
		}
	],
	"require": {
		"php": ">=5.6.0",
		"nette/utils": "^2.4 || ~3.0.0"
	},
	"require-dev": {
		"nette/tester": "^2.0",
		"tracy/tracy": "^2.3"
	},
	"conflict": {
		"nette/nette": "<2.2"
	},
	"autoload": {
		"classmap": ["src/"]
	},
	"minimum-stability": "dev",
	"extra": {
		"branch-alias": {
			"dev-master": "2.4-dev"
		}
	}
}
Licenses
========

Good news! You may use Nette Framework under the terms of either
the New BSD License or the GNU General Public License (GPL) version 2 or 3.

The BSD License is recommended for most projects. It is easy to understand and it
places almost no restrictions on what you can do with the framework. If the GPL
fits better to your project, you can use the framework under this license.

You don't have to notify anyone which license you are using. You can freely
use Nette Framework in commercial projects as long as the copyright header
remains intact.

Please be advised that the name "Nette Framework" is a protected trademark and its
usage has some limitations. So please do not use word "Nette" in the name of your
project or top-level domain, and choose a name that stands on its own merits.
If your stuff is good, it will not take long to establish a reputation for yourselves.


New BSD License
---------------

Copyright (c) 2004, 2014 David Grudl (https://davidgrudl.com)
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

	* Redistributions of source code must retain the above copyright notice,
	this list of conditions and the following disclaimer.

	* Redistributions in binary form must reproduce the above copyright notice,
	this list of conditions and the following disclaimer in the documentation
	and/or other materials provided with the distribution.

	* Neither the name of "Nette Framework" nor the names of its contributors
	may be used to endorse or promote products derived from this software
	without specific prior written permission.

This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall the copyright owner or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused and on
any theory of liability, whether in contract, strict liability, or tort
(including negligence or otherwise) arising in any way out of the use of this
software, even if advised of the possibility of such damage.


GNU General Public License
--------------------------

GPL licenses are very very long, so instead of including them here we offer
you URLs with full text:

- [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html)
- [GPL version 3](http://www.gnu.org/licenses/gpl-3.0.html)
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Utils;


/**
 * Finder allows searching through directory trees using iterator.
 *
 * <code>
 * Finder::findFiles('*.php')
 *     ->size('> 10kB')
 *     ->from('.')
 *     ->exclude('temp');
 * </code>
 */
class Finder implements \IteratorAggregate, \Countable
{
	use \PHPStanVendor\Nette\SmartObject;

	/** @var array */
	private $paths = [];

	/** @var array of filters */
	private $groups = [];

	/** @var array filter for recursive traversing */
	private $exclude = [];

	/** @var int */
	private $order = \RecursiveIteratorIterator::SELF_FIRST;

	/** @var int */
	private $maxDepth = -1;

	/** @var array */
	private $cursor;


	/**
	 * Begins search for files matching mask and all directories.
	 * @param  mixed
	 * @return static
	 */
	public static function find(...$masks)
	{
		$masks = $masks && is_array($masks[0]) ? $masks[0] : $masks;
		return (new static)->select($masks, 'isDir')->select($masks, 'isFile');
	}


	/**
	 * Begins search for files matching mask.
	 * @param  mixed
	 * @return static
	 */
	public static function findFiles(...$masks)
	{
		$masks = $masks && is_array($masks[0]) ? $masks[0] : $masks;
		return (new static)->select($masks, 'isFile');
	}


	/**
	 * Begins search for directories matching mask.
	 * @param  mixed
	 * @return static
	 */
	public static function findDirectories(...$masks)
	{
		$masks = $masks && is_array($masks[0]) ? $masks[0] : $masks;
		return (new static)->select($masks, 'isDir');
	}


	/**
	 * Creates filtering group by mask & type selector.
	 * @param  array
	 * @param  string
	 * @return static
	 */
	private function select($masks, $type)
	{
		$this->cursor = &$this->groups[];
		$pattern = self::buildPattern($masks);
		if ($type || $pattern) {
			$this->filter(function (\RecursiveDirectoryIterator $file) use ($type, $pattern) {
				return !$file->isDot()
					&& (!$type || $file->$type())
					&& (!$pattern || preg_match($pattern, '/' . strtr($file->getSubPathName(), '\\', '/')));
			});
		}
		return $this;
	}


	/**
	 * Searchs in the given folder(s).
	 * @param  string|array
	 * @return static
	 */
	public function in(...$paths)
	{
		$this->maxDepth = 0;
		return $this->from(...$paths);
	}


	/**
	 * Searchs recursively from the given folder(s).
	 * @param  string|array
	 * @return static
	 */
	public function from(...$paths)
	{
		if ($this->paths) {
			throw new \PHPStanVendor\Nette\InvalidStateException('Directory to search has already been specified.');
		}
		$this->paths = is_array($paths[0]) ? $paths[0] : $paths;
		$this->cursor = &$this->exclude;
		return $this;
	}


	/**
	 * Shows folder content prior to the folder.
	 * @return static
	 */
	public function childFirst()
	{
		$this->order = \RecursiveIteratorIterator::CHILD_FIRST;
		return $this;
	}


	/**
	 * Converts Finder pattern to regular expression.
	 * @param  array
	 * @return string|null
	 */
	private static function buildPattern($masks)
	{
		$pattern = [];
		foreach ($masks as $mask) {
			$mask = rtrim(strtr($mask, '\\', '/'), '/');
			$prefix = '';
			if ($mask === '') {
				continue;

			} elseif ($mask === '*') {
				return null;

			} elseif ($mask[0] === '/') { // absolute fixing
				$mask = ltrim($mask, '/');
				$prefix = '(?<=^/)';
			}
			$pattern[] = $prefix . strtr(preg_quote($mask, '#'),
				['\*\*' => '.*', '\*' => '[^/]*', '\?' => '[^/]', '\[\!' => '[^', '\[' => '[', '\]' => ']', '\-' => '-']);
		}
		return $pattern ? '#/(' . implode('|', $pattern) . ')\z#i' : null;
	}


	/********************* iterator generator ****************d*g**/


	/**
	 * Get the number of found files and/or directories.
	 * @return int
	 */
	public function count()
	{
		return iterator_count($this->getIterator());
	}


	/**
	 * Returns iterator.
	 * @return \Iterator
	 */
	public function getIterator()
	{
		if (!$this->paths) {
			throw new \PHPStanVendor\Nette\InvalidStateException('Call in() or from() to specify directory to search.');

		} elseif (count($this->paths) === 1) {
			return $this->buildIterator($this->paths[0]);

		} else {
			$iterator = new \AppendIterator();
			$iterator->append($workaround = new \ArrayIterator(['workaround PHP bugs #49104, #63077']));
			foreach ($this->paths as $path) {
				$iterator->append($this->buildIterator($path));
			}
			unset($workaround[0]);
			return $iterator;
		}
	}


	/**
	 * Returns per-path iterator.
	 * @param  string
	 * @return \Iterator
	 */
	private function buildIterator($path)
	{
		$iterator = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS);

		if ($this->exclude) {
			$iterator = new \RecursiveCallbackFilterIterator($iterator, function ($foo, $bar, \RecursiveDirectoryIterator $file) {
				if (!$file->isDot() && !$file->isFile()) {
					foreach ($this->exclude as $filter) {
						if (!call_user_func($filter, $file)) {
							return false;
						}
					}
				}
				return true;
			});
		}

		if ($this->maxDepth !== 0) {
			$iterator = new \RecursiveIteratorIterator($iterator, $this->order);
			$iterator->setMaxDepth($this->maxDepth);
		}

		$iterator = new \CallbackFilterIterator($iterator, function ($foo, $bar, \Iterator $file) {
			while ($file instanceof \OuterIterator) {
				$file = $file->getInnerIterator();
			}

			foreach ($this->groups as $filters) {
				foreach ($filters as $filter) {
					if (!call_user_func($filter, $file)) {
						continue 2;
					}
				}
				return true;
			}
			return false;
		});

		return $iterator;
	}


	/********************* filtering ****************d*g**/


	/**
	 * Restricts the search using mask.
	 * Excludes directories from recursive traversing.
	 * @param  mixed
	 * @return static
	 */
	public function exclude(...$masks)
	{
		$masks = $masks && is_array($masks[0]) ? $masks[0] : $masks;
		$pattern = self::buildPattern($masks);
		if ($pattern) {
			$this->filter(function (\RecursiveDirectoryIterator $file) use ($pattern) {
				return !preg_match($pattern, '/' . strtr($file->getSubPathName(), '\\', '/'));
			});
		}
		return $this;
	}


	/**
	 * Restricts the search using callback.
	 * @param  callable  function (RecursiveDirectoryIterator $file)
	 * @return static
	 */
	public function filter($callback)
	{
		$this->cursor[] = $callback;
		return $this;
	}


	/**
	 * Limits recursion level.
	 * @param  int
	 * @return static
	 */
	public function limitDepth($depth)
	{
		$this->maxDepth = $depth;
		return $this;
	}


	/**
	 * Restricts the search by size.
	 * @param  string  "[operator] [size] [unit]" example: >=10kB
	 * @param  int
	 * @return static
	 */
	public function size($operator, $size = null)
	{
		if (func_num_args() === 1) { // in $operator is predicate
			if (!preg_match('#^(?:([=<>!]=?|<>)\s*)?((?:\d*\.)?\d+)\s*(K|M|G|)B?\z#i', $operator, $matches)) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException('Invalid size predicate format.');
			}
			list(, $operator, $size, $unit) = $matches;
			static $units = ['' => 1, 'k' => 1e3, 'm' => 1e6, 'g' => 1e9];
			$size *= $units[strtolower($unit)];
			$operator = $operator ? $operator : '=';
		}
		return $this->filter(function (\RecursiveDirectoryIterator $file) use ($operator, $size) {
			return self::compare($file->getSize(), $operator, $size);
		});
	}


	/**
	 * Restricts the search by modified time.
	 * @param  string  "[operator] [date]" example: >1978-01-23
	 * @param  mixed
	 * @return static
	 */
	public function date($operator, $date = null)
	{
		if (func_num_args() === 1) { // in $operator is predicate
			if (!preg_match('#^(?:([=<>!]=?|<>)\s*)?(.+)\z#i', $operator, $matches)) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException('Invalid date predicate format.');
			}
			list(, $operator, $date) = $matches;
			$operator = $operator ? $operator : '=';
		}
		$date = \PHPStanVendor\Nette\Utils\DateTime::from($date)->format('U');
		return $this->filter(function (\RecursiveDirectoryIterator $file) use ($operator, $date) {
			return self::compare($file->getMTime(), $operator, $date);
		});
	}


	/**
	 * Compares two values.
	 * @param  mixed
	 * @param  mixed
	 * @return bool
	 */
	public static function compare($l, $operator, $r)
	{
		switch ($operator) {
			case '>':
				return $l > $r;
			case '>=':
				return $l >= $r;
			case '<':
				return $l < $r;
			case '<=':
				return $l <= $r;
			case '=':
			case '==':
				return $l == $r;
			case '!':
			case '!=':
			case '<>':
				return $l != $r;
			default:
				throw new \PHPStanVendor\Nette\InvalidArgumentException("Unknown operator $operator.");
		}
	}


	/********************* extension methods ****************d*g**/


	public function __call($name, $args)
	{
		if ($callback = \PHPStanVendor\Nette\Utils\ObjectMixin::getExtensionMethod(__CLASS__, $name)) {
			return $callback($this, ...$args);
		}
		\PHPStanVendor\Nette\Utils\ObjectMixin::strictCall(__CLASS__, $name);
	}


	public static function extensionMethod($name, $callback)
	{
		\PHPStanVendor\Nette\Utils\ObjectMixin::setExtensionMethod(__CLASS__, $name, $callback);
	}
}
{
	"name": "nette/neon",
	"description": "Nette NEON: parser & generator for Nette Object Notation",
	"homepage": "http://ne-on.org",
	"license": ["BSD-3-Clause", "GPL-2.0", "GPL-3.0"],
	"authors": [
		{
			"name": "David Grudl",
			"homepage": "https://davidgrudl.com"
		},
		{
			"name": "Nette Community",
			"homepage": "https://nette.org/contributors"
		}
	],
	"require": {
		"php": ">=5.6.0",
		"ext-iconv": "*",
		"ext-json": "*"
	},
	"require-dev": {
		"nette/tester": "~2.0",
		"tracy/tracy": "^2.3"
	},
	"autoload": {
		"classmap": ["src/"]
	},
	"minimum-stability": "dev",
	"extra": {
		"branch-alias": {
			"dev-master": "2.4-dev"
		}
	}
}
Licenses
========

Good news! You may use Nette Framework under the terms of either
the New BSD License or the GNU General Public License (GPL) version 2 or 3.

The BSD License is recommended for most projects. It is easy to understand and it
places almost no restrictions on what you can do with the framework. If the GPL
fits better to your project, you can use the framework under this license.

You don't have to notify anyone which license you are using. You can freely
use Nette Framework in commercial projects as long as the copyright header
remains intact.

Please be advised that the name "Nette Framework" is a protected trademark and its
usage has some limitations. So please do not use word "Nette" in the name of your
project or top-level domain, and choose a name that stands on its own merits.
If your stuff is good, it will not take long to establish a reputation for yourselves.


New BSD License
---------------

Copyright (c) 2004, 2014 David Grudl (https://davidgrudl.com)
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

	* Redistributions of source code must retain the above copyright notice,
	this list of conditions and the following disclaimer.

	* Redistributions in binary form must reproduce the above copyright notice,
	this list of conditions and the following disclaimer in the documentation
	and/or other materials provided with the distribution.

	* Neither the name of "Nette Framework" nor the names of its contributors
	may be used to endorse or promote products derived from this software
	without specific prior written permission.

This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall the copyright owner or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused and on
any theory of liability, whether in contract, strict liability, or tort
(including negligence or otherwise) arising in any way out of the use of this
software, even if advised of the possibility of such damage.


GNU General Public License
--------------------------

GPL licenses are very very long, so instead of including them here we offer
you URLs with full text:

- [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html)
- [GPL version 3](http://www.gnu.org/licenses/gpl-3.0.html)
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Neon;


/**
 * Parser for Nette Object Notation.
 * @internal
 */
class Decoder
{
	const PATTERNS = [
		'
			\'\'\'\n (?:(?: [^\n] | \n(?![\t\ ]*+\'\'\') )*+ \n)?[\t\ ]*+\'\'\' |
			"""\n (?:(?: [^\n] | \n(?![\t\ ]*+""") )*+ \n)?[\t\ ]*+""" |
			\'[^\'\n]*+\' |
			" (?: \\\\. | [^"\\\\\n] )*+ "
		', // string
		'
			(?: [^#"\',:=[\]{}()\x00-\x20!`-] | [:-][^"\',\]})\s] )
			(?:
				[^,:=\]})(\x00-\x20]++ |
				:(?! [\s,\]})] | $ ) |
				[\ \t]++ [^#,:=\]})(\x00-\x20]
			)*+
		', // literal / boolean / integer / float
		'
			[,:=[\]{}()-]
		', // symbol
		'?:\#.*+', // comment
		'\n[\t\ ]*+', // new line + indent
		'?:[\t\ ]++', // whitespace
	];

	const PATTERN_DATETIME = '#\d\d\d\d-\d\d?-\d\d?(?:(?:[Tt]| ++)\d\d?:\d\d:\d\d(?:\.\d*+)? *+(?:Z|[-+]\d\d?(?::?\d\d)?)?)?\z#A';

	const PATTERN_HEX = '#0x[0-9a-fA-F]++\z#A';

	const PATTERN_OCTAL = '#0o[0-7]++\z#A';

	const PATTERN_BINARY = '#0b[0-1]++\z#A';

	const SIMPLE_TYPES = [
		'true' => 'TRUE', 'True' => 'TRUE', 'TRUE' => 'TRUE', 'yes' => 'TRUE', 'Yes' => 'TRUE', 'YES' => 'TRUE', 'on' => 'TRUE', 'On' => 'TRUE', 'ON' => 'TRUE',
		'false' => 'FALSE', 'False' => 'FALSE', 'FALSE' => 'FALSE', 'no' => 'FALSE', 'No' => 'FALSE', 'NO' => 'FALSE', 'off' => 'FALSE', 'Off' => 'FALSE', 'OFF' => 'FALSE',
		'null' => 'NULL', 'Null' => 'NULL', 'NULL' => 'NULL',
	];

	const ESCAPE_SEQUENCES = [
		't' => "\t", 'n' => "\n", 'r' => "\r", 'f' => "\x0C", 'b' => "\x08", '"' => '"', '\\' => '\\', '/' => '/', '_' => "\xc2\xa0",
	];

	const BRACKETS = [
		'[' => ']',
		'{' => '}',
		'(' => ')',
	];

	/** @deprecated */
	public static $patterns = self::PATTERNS;

	/** @var string */
	private $input;

	/** @var array */
	private $tokens;

	/** @var int */
	private $pos;


	/**
	 * Decodes a NEON string.
	 * @param  string
	 * @return mixed
	 */
	public function decode($input)
	{
		if (!is_string($input)) {
			throw new \InvalidArgumentException(sprintf('Argument must be a string, %s given.', gettype($input)));

		} elseif (substr($input, 0, 3) === "\xEF\xBB\xBF") { // BOM
			$input = substr($input, 3);
		}
		$this->input = "\n" . str_replace("\r", '', $input); // \n forces indent detection

		$pattern = '~(' . implode(')|(', self::PATTERNS) . ')~Amix';
		$this->tokens = preg_split($pattern, $this->input, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE | PREG_SPLIT_DELIM_CAPTURE);

		$last = end($this->tokens);
		if ($this->tokens && !preg_match($pattern, $last[0])) {
			$this->pos = count($this->tokens) - 1;
			$this->error();
		}

		$this->pos = 0;
		$res = $this->parse(null);

		while (isset($this->tokens[$this->pos])) {
			if ($this->tokens[$this->pos][0][0] === "\n") {
				$this->pos++;
			} else {
				$this->error();
			}
		}
		return $res;
	}


	/**
	 * @param  string  indentation (for block-parser)
	 * @param  mixed
	 * @return array
	 */
	private function parse($indent, $result = null, $key = null, $hasKey = false)
	{
		$inlineParser = $indent === false;
		$value = null;
		$hasValue = false;
		$tokens = $this->tokens;
		$n = &$this->pos;
		$count = count($tokens);
		$mainResult = &$result;

		for (; $n < $count; $n++) {
			$t = $tokens[$n][0];

			if ($t === ',') { // ArrayEntry separator
				if ((!$hasKey && !$hasValue) || !$inlineParser) {
					$this->error();
				}
				$this->addValue($result, $hasKey ? $key : null, $hasValue ? $value : null);
				$hasKey = $hasValue = false;

			} elseif ($t === ':' || $t === '=') { // KeyValuePair separator
				if ($hasValue && (is_array($value) || is_object($value))) {
					$this->error('Unacceptable key');

				} elseif ($hasKey && $key === null && $hasValue && !$inlineParser) {
					$n++;
					$result[] = $this->parse($indent . '  ', [], $value, true);
					$newIndent = isset($tokens[$n], $tokens[$n + 1]) ? (string) substr($tokens[$n][0], 1) : ''; // not last
					if (strlen($newIndent) > strlen($indent)) {
						$n++;
						$this->error('Bad indentation');
					} elseif (strlen($newIndent) < strlen($indent)) {
						return $mainResult; // block parser exit point
					}
					$hasKey = $hasValue = false;

				} elseif ($hasKey || !$hasValue) {
					$this->error();

				} else {
					$key = (string) $value;
					$hasKey = true;
					$hasValue = false;
					$result = &$mainResult;
				}

			} elseif ($t === '-') { // BlockArray bullet
				if ($hasKey || $hasValue || $inlineParser) {
					$this->error();
				}
				$key = null;
				$hasKey = true;

			} elseif (($tmp = self::BRACKETS) && isset($tmp[$t])) { // Opening bracket [ ( {
				if ($hasValue) {
					if ($t !== '(') {
						$this->error();
					}
					$n++;
					if ($value instanceof \PHPStanVendor\Nette\Neon\Entity && $value->value === \PHPStanVendor\Nette\Neon\Neon::CHAIN) {
						end($value->attributes)->attributes = $this->parse(false, []);
					} else {
						$value = new \PHPStanVendor\Nette\Neon\Entity($value, $this->parse(false, []));
					}
				} else {
					$n++;
					$value = $this->parse(false, []);
				}
				$hasValue = true;
				if (!isset($tokens[$n]) || $tokens[$n][0] !== self::BRACKETS[$t]) { // unexpected type of bracket or block-parser
					$this->error();
				}

			} elseif ($t === ']' || $t === '}' || $t === ')') { // Closing bracket ] ) }
				if (!$inlineParser) {
					$this->error();
				}
				break;

			} elseif ($t[0] === "\n") { // Indent
				if ($inlineParser) {
					if ($hasKey || $hasValue) {
						$this->addValue($result, $hasKey ? $key : null, $hasValue ? $value : null);
						$hasKey = $hasValue = false;
					}

				} else {
					while (isset($tokens[$n + 1]) && $tokens[$n + 1][0][0] === "\n") {
						$n++; // skip to last indent
					}
					if (!isset($tokens[$n + 1])) {
						break;
					}

					$newIndent = (string) substr($tokens[$n][0], 1);
					if ($indent === null) { // first iteration
						$indent = $newIndent;
					}
					$minlen = min(strlen($newIndent), strlen($indent));
					if ($minlen && (string) substr($newIndent, 0, $minlen) !== (string) substr($indent, 0, $minlen)) {
						$n++;
						$this->error('Invalid combination of tabs and spaces');
					}

					if (strlen($newIndent) > strlen($indent)) { // open new block-array or hash
						if ($hasValue || !$hasKey) {
							$n++;
							$this->error('Bad indentation');
						}
						$this->addValue($result, $key, $this->parse($newIndent));
						$newIndent = isset($tokens[$n], $tokens[$n + 1]) ? (string) substr($tokens[$n][0], 1) : ''; // not last
						if (strlen($newIndent) > strlen($indent)) {
							$n++;
							$this->error('Bad indentation');
						}
						$hasKey = false;

					} else {
						if ($hasValue && !$hasKey) { // block items must have "key"; null key means list item
							break;

						} elseif ($hasKey) {
							$this->addValue($result, $key, $hasValue ? $value : null);
							if ($key !== null && !$hasValue && $newIndent === $indent && isset($tokens[$n + 1]) && $tokens[$n + 1][0] === '-') {
								$result = &$result[$key];
							}
							$hasKey = $hasValue = false;
						}
					}

					if (strlen($newIndent) < strlen($indent)) { // close block
						return $mainResult; // block parser exit point
					}
				}

			} else { // Value
				if ($t[0] === '"' || $t[0] === "'") {
					if (preg_match('#^...\n++([\t ]*+)#', $t, $m)) {
						$converted = substr($t, 3, -3);
						$converted = str_replace("\n" . $m[1], "\n", $converted);
						$converted = preg_replace('#^\n|\n[\t ]*+\z#', '', $converted);
					} else {
						$converted = substr($t, 1, -1);
					}
					if ($t[0] === '"') {
						$converted = preg_replace_callback('#\\\\(?:ud[89ab][0-9a-f]{2}\\\\ud[c-f][0-9a-f]{2}|u[0-9a-f]{4}|x[0-9a-f]{2}|.)#i', [$this, 'cbString'], $converted);
					}
				} elseif (($fix56 = self::SIMPLE_TYPES) && isset($fix56[$t]) && (!isset($tokens[$n + 1][0]) || ($tokens[$n + 1][0] !== ':' && $tokens[$n + 1][0] !== '='))) {
					$converted = constant(self::SIMPLE_TYPES[$t]);
				} elseif (is_numeric($t)) {
					$converted = $t * 1;
				} elseif (preg_match(self::PATTERN_HEX, $t)) {
					$converted = hexdec($t);
				} elseif (preg_match(self::PATTERN_OCTAL, $t)) {
					$converted = octdec($t);
				} elseif (preg_match(self::PATTERN_BINARY, $t)) {
					$converted = bindec($t);
				} elseif (preg_match(self::PATTERN_DATETIME, $t)) {
					$converted = new \DateTimeImmutable($t);
				} else { // literal
					$converted = $t;
				}
				if ($hasValue) {
					if ($value instanceof \PHPStanVendor\Nette\Neon\Entity) { // Entity chaining
						if ($value->value !== \PHPStanVendor\Nette\Neon\Neon::CHAIN) {
							$value = new \PHPStanVendor\Nette\Neon\Entity(\PHPStanVendor\Nette\Neon\Neon::CHAIN, [$value]);
						}
						$value->attributes[] = new \PHPStanVendor\Nette\Neon\Entity($converted);
					} else {
						$this->error();
					}
				} else {
					$value = $converted;
					$hasValue = true;
				}
			}
		}

		if ($inlineParser) {
			if ($hasKey || $hasValue) {
				$this->addValue($result, $hasKey ? $key : null, $hasValue ? $value : null);
			}
		} else {
			if ($hasValue && !$hasKey) { // block items must have "key"
				if ($result === null) {
					$result = $value; // simple value parser
				} else {
					$this->error();
				}
			} elseif ($hasKey) {
				$this->addValue($result, $key, $hasValue ? $value : null);
			}
		}
		return $mainResult;
	}


	private function addValue(&$result, $key, $value)
	{
		if ($key === null) {
			$result[] = $value;
		} elseif ($result && array_key_exists($key, $result)) {
			$this->error("Duplicated key '$key'");
		} else {
			$result[$key] = $value;
		}
	}


	private function cbString($m)
	{
		$sq = $m[0];
		if (($fix56 = self::ESCAPE_SEQUENCES) && isset($fix56[$sq[1]])) { // workaround for PHP 5.6
			return self::ESCAPE_SEQUENCES[$sq[1]];
		} elseif ($sq[1] === 'u' && strlen($sq) >= 6) {
			$lead = hexdec(substr($sq, 2, 4));
			$tail = hexdec(substr($sq, 8, 4));
			$code = $tail ? (0x2400 + (($lead - 0xD800) << 10) + $tail) : $lead;
			if ($code >= 0xD800 && $code <= 0xDFFF) {
				$this->error("Invalid UTF-8 (lone surrogate) $sq");
			}
			return iconv('UTF-32BE', 'UTF-8//IGNORE', pack('N', $code));
		} elseif ($sq[1] === 'x' && strlen($sq) === 4) {
			return chr(hexdec(substr($sq, 2)));
		} else {
			$this->error("Invalid escaping sequence $sq");
		}
	}


	private function error($message = "Unexpected '%s'")
	{
		$last = isset($this->tokens[$this->pos]) ? $this->tokens[$this->pos] : null;
		$offset = $last ? $last[1] : strlen($this->input);
		$text = substr($this->input, 0, $offset);
		$line = substr_count($text, "\n");
		$col = $offset - strrpos("\n" . $text, "\n") + 1;
		$token = $last ? str_replace("\n", '<new line>', substr($last[0], 0, 40)) : 'end';
		throw new \PHPStanVendor\Nette\Neon\Exception(str_replace('%s', $token, $message) . " on line $line, column $col.");
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Neon;


/**
 * Simple generator for Nette Object Notation.
 */
class Encoder
{
	const BLOCK = 1;


	/**
	 * Returns the NEON representation of a value.
	 * @param  mixed
	 * @param  int
	 * @return string
	 */
	public function encode($var, $options = null)
	{
		if ($var instanceof \DateTimeInterface) {
			return $var->format('Y-m-d H:i:s O');

		} elseif ($var instanceof \PHPStanVendor\Nette\Neon\Entity) {
			if ($var->value === \PHPStanVendor\Nette\Neon\Neon::CHAIN) {
				return implode('', array_map([$this, 'encode'], $var->attributes));
			}
			return $this->encode($var->value) . '('
				. (is_array($var->attributes) ? substr($this->encode($var->attributes), 1, -1) : '') . ')';
		}

		if (is_object($var)) {
			$obj = $var;
			$var = [];
			foreach ($obj as $k => $v) {
				$var[$k] = $v;
			}
		}

		if (is_array($var)) {
			$isList = !$var || array_keys($var) === range(0, count($var) - 1);
			$s = '';
			if ($options & self::BLOCK) {
				if (count($var) === 0) {
					return '[]';
				}
				foreach ($var as $k => $v) {
					$v = $this->encode($v, self::BLOCK);
					$s .= ($isList ? '-' : $this->encode($k) . ':')
						. (strpos($v, "\n") === false
							? ' ' . $v . "\n"
							: "\n" . preg_replace('#^(?=.)#m', "\t", $v) . (substr($v, -2, 1) === "\n" ? '' : "\n"));
				}
				return $s;

			} else {
				foreach ($var as $k => $v) {
					$s .= ($isList ? '' : $this->encode($k) . ': ') . $this->encode($v) . ', ';
				}
				return ($isList ? '[' : '{') . substr($s, 0, -2) . ($isList ? ']' : '}');
			}

		} elseif (is_string($var) && !is_numeric($var)
			&& !preg_match('~[\x00-\x1F]|^\d{4}|^(true|false|yes|no|on|off|null)\z~i', $var)
			&& preg_match('~^' . \PHPStanVendor\Nette\Neon\Decoder::PATTERNS[1] . '\z~x', $var) // 1 = literals
		) {
			return $var;

		} elseif (is_float($var)) {
			$var = json_encode($var);
			return strpos($var, '.') === false ? $var . '.0' : $var;

		} else {
			return json_encode($var, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
		}
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Neon;


/**
 * Representation of 'foo(bar=1)' literal
 */
class Entity extends \stdClass
{
	/** @var mixed */
	public $value;

	/** @var array */
	public $attributes;


	public function __construct($value = null, array $attrs = null)
	{
		$this->value = $value;
		$this->attributes = (array) $attrs;
	}


	public static function __set_state(array $properties)
	{
		return new self($properties['value'], $properties['attributes']);
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Neon;


/**
 * The exception that indicates error of NEON processing.
 */
class Exception extends \Exception
{
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Neon;


/**
 * Simple parser & generator for Nette Object Notation.
 */
class Neon
{
	const BLOCK = \PHPStanVendor\Nette\Neon\Encoder::BLOCK;
	const CHAIN = '!!chain';


	/**
	 * Returns the NEON representation of a value.
	 * @param  mixed
	 * @param  int
	 * @return string
	 */
	public static function encode($var, $options = null)
	{
		$encoder = new \PHPStanVendor\Nette\Neon\Encoder;
		return $encoder->encode($var, $options);
	}


	/**
	 * Decodes a NEON string.
	 * @param  string
	 * @return mixed
	 */
	public static function decode($input)
	{
		$decoder = new \PHPStanVendor\Nette\Neon\Decoder;
		return $decoder->decode($input);
	}
}
<?php

require __DIR__ . '/Neon/Decoder.php';
require __DIR__ . '/Neon/Encoder.php';
require __DIR__ . '/Neon/Entity.php';
require __DIR__ . '/Neon/Exception.php';
require __DIR__ . '/Neon/Neon.php';
{
	"name": "nette/php-generator",
	"description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 7.1 features.",
	"keywords": ["nette", "php", "code", "scaffolding"],
	"homepage": "https://nette.org",
	"license": ["BSD-3-Clause", "GPL-2.0", "GPL-3.0"],
	"authors": [
		{
			"name": "David Grudl",
			"homepage": "https://davidgrudl.com"
		},
		{
			"name": "Nette Community",
			"homepage": "https://nette.org/contributors"
		}
	],
	"require": {
		"php": ">=7.0",
		"nette/utils": "^2.4.2 || ~3.0.0"
	},
	"require-dev": {
		"nette/tester": "^2.0",
		"tracy/tracy": "^2.3"
	},
	"conflict": {
		"nette/nette": "<2.2"
	},
	"autoload": {
		"classmap": ["src/"]
	},
	"minimum-stability": "dev",
	"extra": {
		"branch-alias": {
			"dev-master": "3.0-dev"
		}
	}
}
Licenses
========

Good news! You may use Nette Framework under the terms of either
the New BSD License or the GNU General Public License (GPL) version 2 or 3.

The BSD License is recommended for most projects. It is easy to understand and it
places almost no restrictions on what you can do with the framework. If the GPL
fits better to your project, you can use the framework under this license.

You don't have to notify anyone which license you are using. You can freely
use Nette Framework in commercial projects as long as the copyright header
remains intact.

Please be advised that the name "Nette Framework" is a protected trademark and its
usage has some limitations. So please do not use word "Nette" in the name of your
project or top-level domain, and choose a name that stands on its own merits.
If your stuff is good, it will not take long to establish a reputation for yourselves.


New BSD License
---------------

Copyright (c) 2004, 2014 David Grudl (https://davidgrudl.com)
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

	* Redistributions of source code must retain the above copyright notice,
	this list of conditions and the following disclaimer.

	* Redistributions in binary form must reproduce the above copyright notice,
	this list of conditions and the following disclaimer in the documentation
	and/or other materials provided with the distribution.

	* Neither the name of "Nette Framework" nor the names of its contributors
	may be used to endorse or promote products derived from this software
	without specific prior written permission.

This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall the copyright owner or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused and on
any theory of liability, whether in contract, strict liability, or tort
(including negligence or otherwise) arising in any way out of the use of this
software, even if advised of the possibility of such damage.


GNU General Public License
--------------------------

GPL licenses are very very long, so instead of including them here we offer
you URLs with full text:

- [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html)
- [GPL version 3](http://www.gnu.org/licenses/gpl-3.0.html)
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

declare(strict_types=1);

namespace PHPStanVendor\Nette\PhpGenerator;


/**
 * Class/Interface/Trait description.
 *
 * @property Method[] $methods
 * @property Property[] $properties
 */
final class ClassType
{
	use \PHPStanVendor\Nette\SmartObject;
	use \PHPStanVendor\Nette\PhpGenerator\Traits\CommentAware;

	const TYPE_CLASS = 'class';
	const TYPE_INTERFACE = 'interface';
	const TYPE_TRAIT = 'trait';

	/** @var PhpNamespace|null */
	private $namespace;

	/** @var string|null */
	private $name;

	/** @var string  class|interface|trait */
	private $type = 'class';

	/** @var bool */
	private $final = false;

	/** @var bool */
	private $abstract = false;

	/** @var string|string[] */
	private $extends = [];

	/** @var string[] */
	private $implements = [];

	/** @var string[] */
	private $traits = [];

	/** @var Constant[] name => Constant */
	private $consts = [];

	/** @var Property[] name => Property */
	private $properties = [];

	/** @var Method[] name => Method */
	private $methods = [];


	/**
	 * @param  string|object
	 * @return static
	 */
	public static function from($class): self
	{
		if ($class instanceof \ReflectionClass) {
			trigger_error(__METHOD__ . '() accepts only class name or object.', E_USER_DEPRECATED);
		}
		return (new \PHPStanVendor\Nette\PhpGenerator\Factory)->fromClassReflection(
			$class instanceof \ReflectionClass ? $class : new \ReflectionClass($class)
		);
	}


	public function __construct(string $name = null, \PHPStanVendor\Nette\PhpGenerator\PhpNamespace $namespace = null)
	{
		$this->setName($name);
		$this->namespace = $namespace;
	}


	public function __toString(): string
	{
		$traits = [];
		foreach ($this->traits as $trait => $resolutions) {
			$traits[] = 'use ' . ($this->namespace ? $this->namespace->unresolveName($trait) : $trait)
				. ($resolutions ? " {\n\t" . implode(";\n\t", $resolutions) . ";\n}" : ';');
		}

		$consts = [];
		foreach ($this->consts as $const) {
			$consts[] = \PHPStanVendor\Nette\PhpGenerator\Helpers::formatDocComment((string) $const->getComment())
				. ($const->getVisibility() ? $const->getVisibility() . ' ' : '')
				. 'const ' . $const->getName() . ' = ' . \PHPStanVendor\Nette\PhpGenerator\Helpers::dump($const->getValue()) . ';';
		}

		$properties = [];
		foreach ($this->properties as $property) {
			$properties[] = \PHPStanVendor\Nette\PhpGenerator\Helpers::formatDocComment((string) $property->getComment())
				. ($property->getVisibility() ?: 'public') . ($property->isStatic() ? ' static' : '') . ' $' . $property->getName()
				. ($property->getValue() === null ? '' : ' = ' . \PHPStanVendor\Nette\PhpGenerator\Helpers::dump($property->getValue()))
				. ';';
		}

		$mapper = function (array $arr) {
			return $this->namespace ? array_map([$this->namespace, 'unresolveName'], $arr) : $arr;
		};

		return \PHPStanVendor\Nette\Utils\Strings::normalize(
			\PHPStanVendor\Nette\PhpGenerator\Helpers::formatDocComment($this->comment . "\n")
			. ($this->abstract ? 'abstract ' : '')
			. ($this->final ? 'final ' : '')
			. ($this->name ? "$this->type $this->name " : '')
			. ($this->extends ? 'extends ' . implode(', ', $mapper((array) $this->extends)) . ' ' : '')
			. ($this->implements ? 'implements ' . implode(', ', $mapper($this->implements)) . ' ' : '')
			. ($this->name ? "\n" : '') . "{\n"
			. \PHPStanVendor\Nette\Utils\Strings::indent(
				($this->traits ? implode("\n", $traits) . "\n\n" : '')
				. ($this->consts ? implode("\n", $consts) . "\n\n" : '')
				. ($this->properties ? implode("\n\n", $properties) . "\n\n\n" : '')
				. ($this->methods ? implode("\n\n\n", $this->methods) . "\n" : ''), 1)
			. '}'
		) . ($this->name ? "\n" : '');
	}


	/**
	 * @return PhpNamespace|null
	 */
	public function getNamespace()
	{
		return $this->namespace;
	}


	/**
	 * @param  string|null
	 * @return static
	 */
	public function setName($name): self
	{
		if ($name !== null && !\PHPStanVendor\Nette\PhpGenerator\Helpers::isIdentifier($name)) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException("Value '$name' is not valid class name.");
		}
		$this->name = $name;
		return $this;
	}


	/**
	 * @return string|null
	 */
	public function getName()
	{
		return $this->name;
	}


	/**
	 * @return static
	 */
	public function setType(string $type): self
	{
		if (!in_array($type, ['class', 'interface', 'trait'], true)) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException('Argument must be class|interface|trait.');
		}
		$this->type = $type;
		return $this;
	}


	public function getType(): string
	{
		return $this->type;
	}


	/**
	 * @return static
	 */
	public function setFinal(bool $state = true): self
	{
		$this->final = $state;
		return $this;
	}


	public function isFinal(): bool
	{
		return $this->final;
	}


	/**
	 * @return static
	 */
	public function setAbstract(bool $state = true): self
	{
		$this->abstract = $state;
		return $this;
	}


	public function isAbstract(): bool
	{
		return $this->abstract;
	}


	/**
	 * @param  string|string[]
	 * @return static
	 */
	public function setExtends($names): self
	{
		if (!is_string($names) && !is_array($names)) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException('Argument must be string or string[].');
		}
		$this->validate((array) $names);
		$this->extends = $names;
		return $this;
	}


	/**
	 * @return string|string[]
	 */
	public function getExtends()
	{
		return $this->extends;
	}


	/**
	 * @return static
	 */
	public function addExtend(string $name): self
	{
		$this->validate([$name]);
		$this->extends = (array) $this->extends;
		$this->extends[] = $name;
		return $this;
	}


	/**
	 * @param  string[]
	 * @return static
	 */
	public function setImplements(array $names): self
	{
		$this->validate($names);
		$this->implements = $names;
		return $this;
	}


	/**
	 * @return string[]
	 */
	public function getImplements(): array
	{
		return $this->implements;
	}


	/**
	 * @return static
	 */
	public function addImplement(string $name): self
	{
		$this->validate([$name]);
		$this->implements[] = $name;
		return $this;
	}


	/**
	 * @param  string[]
	 * @return static
	 */
	public function setTraits(array $names): self
	{
		$this->validate($names);
		$this->traits = array_fill_keys($names, []);
		return $this;
	}


	/**
	 * @return string[]
	 */
	public function getTraits(): array
	{
		return array_keys($this->traits);
	}


	/**
	 * @return static
	 */
	public function addTrait(string $name, array $resolutions = []): self
	{
		$this->validate([$name]);
		$this->traits[$name] = $resolutions;
		return $this;
	}


	/**
	 * @deprecated  use setConstants()
	 * @return static
	 */
	public function setConsts(array $consts): self
	{
		trigger_error(__METHOD__ . '() is deprecated, use setConstants()', E_USER_DEPRECATED);
		return $this->setConstants($consts);
	}


	/**
	 * @deprecated  use getConstants()
	 */
	public function getConsts(): array
	{
		trigger_error(__METHOD__ . '() is deprecated, use similar getConstants()', E_USER_DEPRECATED);
		return array_map(function ($const) { return $const->getValue(); }, $this->consts);
	}


	/**
	 * @deprecated  use addConstant()
	 * @return static
	 */
	public function addConst(string $name, $value): self
	{
		trigger_error(__METHOD__ . '() is deprecated, use similar addConstant()', E_USER_DEPRECATED);
		$this->addConstant($name, $value);
		return $this;
	}


	/**
	 * @param  Constant[]|mixed[]
	 * @return static
	 */
	public function setConstants(array $consts): self
	{
		$this->consts = [];
		foreach ($consts as $k => $v) {
			$const = $v instanceof \PHPStanVendor\Nette\PhpGenerator\Constant ? $v : (new \PHPStanVendor\Nette\PhpGenerator\Constant($k))->setValue($v);
			$this->consts[$const->getName()] = $const;
		}
		return $this;
	}


	/**
	 * @return Constant[]
	 */
	public function getConstants(): array
	{
		return $this->consts;
	}


	public function addConstant(string $name, $value): \PHPStanVendor\Nette\PhpGenerator\Constant
	{
		return $this->consts[$name] = (new \PHPStanVendor\Nette\PhpGenerator\Constant($name))->setValue($value);
	}


	/**
	 * @param  Property[]
	 * @return static
	 */
	public function setProperties(array $props): self
	{
		$this->properties = [];
		foreach ($props as $v) {
			if (!$v instanceof \PHPStanVendor\Nette\PhpGenerator\Property) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException('Argument must be \PHPStanVendor\Nette\PhpGenerator\Property[].');
			}
			$this->properties[$v->getName()] = $v;
		}
		return $this;
	}


	/**
	 * @return Property[]
	 */
	public function getProperties(): array
	{
		return $this->properties;
	}


	public function getProperty($name): \PHPStanVendor\Nette\PhpGenerator\Property
	{
		if (!isset($this->properties[$name])) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException("Property '$name' not found.");
		}
		return $this->properties[$name];
	}


	/**
	 * @param  string  without $
	 */
	public function addProperty(string $name, $value = null): \PHPStanVendor\Nette\PhpGenerator\Property
	{
		return $this->properties[$name] = (new \PHPStanVendor\Nette\PhpGenerator\Property($name))->setValue($value);
	}


	/**
	 * @param  Method[]
	 * @return static
	 */
	public function setMethods(array $methods): self
	{
		$this->methods = [];
		foreach ($methods as $v) {
			if (!$v instanceof \PHPStanVendor\Nette\PhpGenerator\Method) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException('Argument must be \PHPStanVendor\Nette\PhpGenerator\Method[].');
			}
			$this->methods[$v->getName()] = $v->setNamespace($this->namespace);
		}
		return $this;
	}


	/**
	 * @return Method[]
	 */
	public function getMethods(): array
	{
		return $this->methods;
	}


	public function getMethod($name): \PHPStanVendor\Nette\PhpGenerator\Method
	{
		if (!isset($this->methods[$name])) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException("Method '$name' not found.");
		}
		return $this->methods[$name];
	}


	public function addMethod(string $name): \PHPStanVendor\Nette\PhpGenerator\Method
	{
		$method = (new \PHPStanVendor\Nette\PhpGenerator\Method($name))->setNamespace($this->namespace);
		if ($this->type === 'interface') {
			$method->setBody(null);
		} else {
			$method->setVisibility('public');
		}
		return $this->methods[$name] = $method;
	}


	private function validate(array $names)
	{
		foreach ($names as $name) {
			if (!\PHPStanVendor\Nette\PhpGenerator\Helpers::isNamespaceIdentifier($name, true)) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException("Value '$name' is not valid class name.");
			}
		}
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

declare(strict_types=1);

namespace PHPStanVendor\Nette\PhpGenerator;


/**
 * Closure.
 *
 * @property string $body
 */
final class Closure
{
	use \PHPStanVendor\Nette\SmartObject;
	use \PHPStanVendor\Nette\PhpGenerator\Traits\FunctionLike;

	/** @var Parameter[] */
	private $uses = [];


	/**
	 * @return static
	 */
	public static function from(\Closure $closure): self
	{
		return (new \PHPStanVendor\Nette\PhpGenerator\Factory)->fromFunctionReflection(new \ReflectionFunction($closure));
	}


	public function __toString(): string
	{
		$uses = [];
		foreach ($this->uses as $param) {
			$uses[] = ($param->isReference() ? '&' : '') . '$' . $param->getName();
		}
		return 'function '
			. ($this->returnReference ? '&' : '')
			. $this->parametersToString()
			. ($this->uses ? ' use (' . implode(', ', $uses) . ')' : '')
			. $this->returnTypeToString()
			. " {\n" . \PHPStanVendor\Nette\Utils\Strings::indent(ltrim(rtrim($this->body) . "\n"), 1) . '}';
	}


	/**
	 * @param  Parameter[]
	 * @return static
	 */
	public function setUses(array $uses): self
	{
		(function (\PHPStanVendor\Nette\PhpGenerator\Parameter ...$uses) {})(...$uses);
		$this->uses = $uses;
		return $this;
	}


	public function getUses(): array
	{
		return $this->uses;
	}


	public function addUse($name): \PHPStanVendor\Nette\PhpGenerator\Parameter
	{
		return $this->uses[] = new \PHPStanVendor\Nette\PhpGenerator\Parameter($name);
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

declare(strict_types=1);

namespace PHPStanVendor\Nette\PhpGenerator;


/**
 * Class constant.
 */
final class Constant
{
	use \PHPStanVendor\Nette\SmartObject;
	use \PHPStanVendor\Nette\PhpGenerator\Traits\NameAware;
	use \PHPStanVendor\Nette\PhpGenerator\Traits\VisibilityAware;
	use \PHPStanVendor\Nette\PhpGenerator\Traits\CommentAware;

	/** @var mixed */
	private $value;


	/**
	 * @return static
	 */
	public function setValue($val): self
	{
		$this->value = $val;
		return $this;
	}


	public function getValue()
	{
		return $this->value;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

declare(strict_types=1);

namespace PHPStanVendor\Nette\PhpGenerator;


/**
 * Creates a representation based on reflection.
 */
final class Factory
{
	use \PHPStanVendor\Nette\SmartObject;

	public function fromClassReflection(\ReflectionClass $from): \PHPStanVendor\Nette\PhpGenerator\ClassType
	{
		$class = $from->isAnonymous()
			? new \PHPStanVendor\Nette\PhpGenerator\ClassType
			: new \PHPStanVendor\Nette\PhpGenerator\ClassType($from->getShortName(), new \PHPStanVendor\Nette\PhpGenerator\PhpNamespace($from->getNamespaceName()));
		$class->setType($from->isInterface() ? 'interface' : ($from->isTrait() ? 'trait' : 'class'));
		$class->setFinal($from->isFinal() && $class->getType() === 'class');
		$class->setAbstract($from->isAbstract() && $class->getType() === 'class');
		$class->setImplements($from->getInterfaceNames());
		$class->setComment(\PHPStanVendor\Nette\PhpGenerator\Helpers::unformatDocComment((string) $from->getDocComment()));
		if ($from->getParentClass()) {
			$class->setExtends($from->getParentClass()->getName());
			$class->setImplements(array_diff($class->getImplements(), $from->getParentClass()->getInterfaceNames()));
		}
		$props = $methods = [];
		foreach ($from->getProperties() as $prop) {
			if ($prop->isDefault() && $prop->getDeclaringClass()->getName() === $from->getName()) {
				$props[] = $this->fromPropertyReflection($prop);
			}
		}
		$class->setProperties($props);
		foreach ($from->getMethods() as $method) {
			if ($method->getDeclaringClass()->getName() === $from->getName()) {
				$methods[] = $this->fromMethodReflection($method)->setNamespace($class->getNamespace());
			}
		}
		$class->setMethods($methods);
		$class->setConstants($from->getConstants());
		return $class;
	}


	public function fromMethodReflection(\ReflectionMethod $from): \PHPStanVendor\Nette\PhpGenerator\Method
	{
		$method = new \PHPStanVendor\Nette\PhpGenerator\Method($from->getName());
		$method->setParameters(array_map([$this, 'fromParameterReflection'], $from->getParameters()));
		$method->setStatic($from->isStatic());
		$isInterface = $from->getDeclaringClass()->isInterface();
		$method->setVisibility($from->isPrivate() ? 'private' : ($from->isProtected() ? 'protected' : ($isInterface ? null : 'public')));
		$method->setFinal($from->isFinal());
		$method->setAbstract($from->isAbstract() && !$isInterface);
		$method->setBody($from->isAbstract() ? null : '');
		$method->setReturnReference($from->returnsReference());
		$method->setVariadic($from->isVariadic());
		$method->setComment(\PHPStanVendor\Nette\PhpGenerator\Helpers::unformatDocComment((string) $from->getDocComment()));
		if ($from->hasReturnType()) {
			$method->setReturnType((string) $from->getReturnType());
			$method->setReturnNullable($from->getReturnType()->allowsNull());
		}
		return $method;
	}


	/**
	 * @return GlobalFunction|Closure
	 */
	public function fromFunctionReflection(\ReflectionFunction $from)
	{
		$function = $from->isClosure() ? new \PHPStanVendor\Nette\PhpGenerator\Closure : new \PHPStanVendor\Nette\PhpGenerator\GlobalFunction($from->getName());
		$function->setParameters(array_map([$this, 'fromParameterReflection'], $from->getParameters()));
		$function->setReturnReference($from->returnsReference());
		$function->setVariadic($from->isVariadic());
		if (!$from->isClosure()) {
			$function->setComment(\PHPStanVendor\Nette\PhpGenerator\Helpers::unformatDocComment((string) $from->getDocComment()));
		}
		if ($from->hasReturnType()) {
			$function->setReturnType((string) $from->getReturnType());
			$function->setReturnNullable($from->getReturnType()->allowsNull());
		}
		return $function;
	}


	public function fromParameterReflection(\ReflectionParameter $from): \PHPStanVendor\Nette\PhpGenerator\Parameter
	{
		$param = new \PHPStanVendor\Nette\PhpGenerator\Parameter($from->getName());
		$param->setReference($from->isPassedByReference());
		$param->setTypeHint($from->hasType() ? (string) $from->getType() : null);
		$param->setNullable($from->hasType() && $from->getType()->allowsNull());
		if ($from->isDefaultValueAvailable()) {
			$param->setDefaultValue($from->isDefaultValueConstant()
				? new \PHPStanVendor\Nette\PhpGenerator\PhpLiteral($from->getDefaultValueConstantName())
				: $from->getDefaultValue());
			$param->setNullable($param->isNullable() && $param->getDefaultValue() !== null);
		}
		return $param;
	}


	public function fromPropertyReflection(\ReflectionProperty $from): \PHPStanVendor\Nette\PhpGenerator\Property
	{
		$prop = new \PHPStanVendor\Nette\PhpGenerator\Property($from->getName());
		$prop->setValue($from->getDeclaringClass()->getDefaultProperties()[$prop->getName()] ?? null);
		$prop->setStatic($from->isStatic());
		$prop->setVisibility($from->isPrivate() ? 'private' : ($from->isProtected() ? 'protected' : 'public'));
		$prop->setComment(\PHPStanVendor\Nette\PhpGenerator\Helpers::unformatDocComment((string) $from->getDocComment()));
		return $prop;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

declare(strict_types=1);

namespace PHPStanVendor\Nette\PhpGenerator;


/**
 * Global function.
 *
 * @property string $body
 */
final class GlobalFunction
{
	use \PHPStanVendor\Nette\SmartObject;
	use \PHPStanVendor\Nette\PhpGenerator\Traits\FunctionLike;
	use \PHPStanVendor\Nette\PhpGenerator\Traits\NameAware;
	use \PHPStanVendor\Nette\PhpGenerator\Traits\CommentAware;

	/**
	 * @return static
	 */
	public static function from(string $function): self
	{
		return (new \PHPStanVendor\Nette\PhpGenerator\Factory)->fromFunctionReflection(new \ReflectionFunction($function));
	}


	public function __toString(): string
	{
		return \PHPStanVendor\Nette\PhpGenerator\Helpers::formatDocComment($this->comment . "\n")
			. 'function '
			. ($this->returnReference ? '&' : '')
			. $this->name
			. $this->parametersToString()
			. $this->returnTypeToString()
			. "\n{\n" . \PHPStanVendor\Nette\Utils\Strings::indent(ltrim(rtrim($this->body) . "\n"), 1) . '}';
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

declare(strict_types=1);

namespace PHPStanVendor\Nette\PhpGenerator;


/**
 * PHP code generator utils.
 */
final class Helpers
{
	use \PHPStanVendor\Nette\StaticClass;

	const PHP_IDENT = '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*';
	const MAX_DEPTH = 50;
	const WRAP_LENGTH = 70;


	/**
	 * Returns a PHP representation of a variable.
	 */
	public static function dump($var): string
	{
		return self::_dump($var);
	}


	private static function _dump(&$var, int $level = 0)
	{
		if ($var instanceof \PHPStanVendor\Nette\PhpGenerator\PhpLiteral) {
			return (string) $var;

		} elseif (is_float($var)) {
			if (is_finite($var)) {
				$var = var_export($var, true);
				return strpos($var, '.') === false ? $var . '.0' : $var; // workaround for PHP < 7.0.2
			}
			return str_replace('.0', '', var_export($var, true)); // workaround for PHP 7.0.2

		} elseif ($var === null) {
			return 'null';

		} elseif (is_string($var) && (preg_match('#[^\x09\x20-\x7E\xA0-\x{10FFFF}]#u', $var) || preg_last_error())) {
			static $table;
			if ($table === null) {
				foreach (array_merge(range("\x00", "\x1F"), range("\x7F", "\xFF")) as $ch) {
					$table[$ch] = '\x' . str_pad(dechex(ord($ch)), 2, '0', STR_PAD_LEFT);
				}
				$table['\\'] = '\\\\';
				$table["\r"] = '\r';
				$table["\n"] = '\n';
				$table["\t"] = '\t';
				$table['$'] = '\$';
				$table['"'] = '\"';
			}
			return '"' . strtr($var, $table) . '"';

		} elseif (is_string($var)) {
			return "'" . preg_replace('#\'|\\\\(?=[\'\\\\]|\z)#', '\\\\$0', $var) . "'";

		} elseif (is_array($var)) {
			$space = str_repeat("\t", $level);

			static $marker;
			if ($marker === null) {
				$marker = uniqid("\x00", true);
			}
			if (empty($var)) {
				$out = '';

			} elseif ($level > self::MAX_DEPTH || isset($var[$marker])) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException('Nesting level too deep or recursive dependency.');

			} else {
				$out = '';
				$outAlt = "\n$space";
				$var[$marker] = true;
				$counter = 0;
				foreach ($var as $k => &$v) {
					if ($k !== $marker) {
						$item = ($k === $counter ? '' : self::_dump($k, $level + 1) . ' => ') . self::_dump($v, $level + 1);
						$counter = is_int($k) ? max($k + 1, $counter) : $counter;
						$out .= ($out === '' ? '' : ', ') . $item;
						$outAlt .= "\t$item,\n$space";
					}
				}
				unset($var[$marker]);
			}
			return '[' . (strpos($out, "\n") === false && strlen($out) < self::WRAP_LENGTH ? $out : $outAlt) . ']';

		} elseif ($var instanceof \Serializable) {
			$var = serialize($var);
			return 'unserialize(' . self::_dump($var, $level) . ')';

		} elseif ($var instanceof \Closure) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException('Cannot dump closure.');

		} elseif (is_object($var)) {
			$class = get_class($var);
			if ((new \ReflectionObject($var))->isAnonymous()) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException('Cannot dump anonymous class.');

			} elseif (in_array($class, ['DateTime', 'DateTimeImmutable'], true)) {
				return self::formatArgs("new $class(?, new DateTimeZone(?))", [$var->format('Y-m-d H:i:s.u'), $var->getTimeZone()->getName()]);
			}

			$arr = (array) $var;
			$space = str_repeat("\t", $level);

			static $list = [];
			if ($level > self::MAX_DEPTH || in_array($var, $list, true)) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException('Nesting level too deep or recursive dependency.');

			} else {
				$out = "\n";
				$list[] = $var;
				if (method_exists($var, '__sleep')) {
					foreach ($var->__sleep() as $v) {
						$props[$v] = $props["\x00*\x00$v"] = $props["\x00$class\x00$v"] = true;
					}
				}
				foreach ($arr as $k => &$v) {
					if (!isset($props) || isset($props[$k])) {
						$out .= "$space\t" . self::_dump($k, $level + 1) . ' => ' . self::_dump($v, $level + 1) . ",\n";
					}
				}
				array_pop($list);
				$out .= $space;
			}
			return $class === 'stdClass'
				? "(object) [$out]"
				: __CLASS__ . "::createObject('$class', [$out])";

		} elseif (is_resource($var)) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException('Cannot dump resource.');

		} else {
			return var_export($var, true);
		}
	}


	/**
	 * Generates PHP statement.
	 */
	public static function format(string $statement, ...$args): string
	{
		return self::formatArgs($statement, $args);
	}


	/**
	 * Generates PHP statement.
	 */
	public static function formatArgs(string $statement, array $args): string
	{
		$tokens = preg_split('#(\.\.\.\?|\$\?|->\?|::\?|\\\\\?|\?\*|\?)#', $statement, -1, PREG_SPLIT_DELIM_CAPTURE);
		$res = '';
		foreach ($tokens as $n => $token) {
			if ($n % 2 === 0) {
				$res .= $token;
			} elseif ($token === '\\?') {
				$res .= '?';
			} elseif (!$args) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException('Insufficient number of arguments.');
			} elseif ($token === '?') {
				$res .= self::dump(array_shift($args));
			} elseif ($token === '...?' || $token === '?*') {
				$arg = array_shift($args);
				if (!is_array($arg)) {
					throw new \PHPStanVendor\Nette\InvalidArgumentException('Argument must be an array.');
				}
				$sep = '';
				foreach ($arg as $tmp) {
					$res .= $sep . self::dump($tmp);
					$sep = strlen($res) - strrpos($res, "\n") > self::WRAP_LENGTH ? ",\n\t" : ', ';
				}
			} else { // $  ->  ::
				$res .= substr($token, 0, -1) . self::formatMember(array_shift($args));
			}
		}
		if ($args) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException('Insufficient number of placeholders.');
		}
		return $res;
	}


	/**
	 * Returns a PHP representation of a object member.
	 */
	public static function formatMember($name): string
	{
		return $name instanceof \PHPStanVendor\Nette\PhpGenerator\PhpLiteral || !self::isIdentifier($name)
			? '{' . self::_dump($name) . '}'
			: $name;
	}


	public static function formatDocComment(string $content): string
	{
		if (($s = trim($content)) === '') {
			return '';
		} elseif (strpos($content, "\n") === false) {
			return "/** $s */\n";
		} else {
			return str_replace("\n", "\n * ", "/**\n$s") . "\n */\n";
		}
	}


	public static function unformatDocComment(string $comment): string
	{
		return preg_replace('#^\s*\* ?#m', '', trim(trim(trim($comment), '/*')));
	}


	public static function isIdentifier($value): bool
	{
		return is_string($value) && preg_match('#^' . self::PHP_IDENT . '\z#', $value);
	}


	public static function isNamespaceIdentifier($value, bool $allowLeadingSlash = false): bool
	{
		$re = '#^' . ($allowLeadingSlash ? '\\\\?' : '') . self::PHP_IDENT . '(\\\\' . self::PHP_IDENT . ')*\z#';
		return is_string($value) && preg_match($re, $value);
	}


	/**
	 * @return object
	 * @internal
	 */
	public static function createObject(string $class, array $props)
	{
		return unserialize('O' . substr(serialize($class), 1, -1) . substr(serialize($props), 1));
	}


	public static function extractNamespace(string $name): string
	{
		return ($pos = strrpos($name, '\\')) ? substr($name, 0, $pos) : '';
	}


	public static function extractShortName(string $name): string
	{
		return ($pos = strrpos($name, '\\')) === false ? $name : substr($name, $pos + 1);
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

declare(strict_types=1);

namespace PHPStanVendor\Nette\PhpGenerator;


/**
 * Class method.
 *
 * @property string|null $body
 */
final class Method
{
	use \PHPStanVendor\Nette\SmartObject;
	use \PHPStanVendor\Nette\PhpGenerator\Traits\FunctionLike;
	use \PHPStanVendor\Nette\PhpGenerator\Traits\NameAware;
	use \PHPStanVendor\Nette\PhpGenerator\Traits\VisibilityAware;
	use \PHPStanVendor\Nette\PhpGenerator\Traits\CommentAware;

	/** @var string|null */
	private $body = '';

	/** @var bool */
	private $static = false;

	/** @var bool */
	private $final = false;

	/** @var bool */
	private $abstract = false;


	/**
	 * @return static
	 */
	public static function from($method): self
	{
		if ($method instanceof \ReflectionMethod) {
			trigger_error(__METHOD__ . '() accepts only method name.', E_USER_DEPRECATED);
		} else {
			$method = \PHPStanVendor\Nette\Utils\Callback::toReflection($method);
		}
		return (new \PHPStanVendor\Nette\PhpGenerator\Factory)->fromMethodReflection($method);
	}


	public function __construct(string $name)
	{
		if (!\PHPStanVendor\Nette\PhpGenerator\Helpers::isIdentifier($name)) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException("Value '$name' is not valid name.");
		}
		$this->name = $name;
	}


	public function __toString(): string
	{
		return \PHPStanVendor\Nette\PhpGenerator\Helpers::formatDocComment($this->comment . "\n")
			. ($this->abstract ? 'abstract ' : '')
			. ($this->final ? 'final ' : '')
			. ($this->visibility ? $this->visibility . ' ' : '')
			. ($this->static ? 'static ' : '')
			. 'function '
			. ($this->returnReference ? '&' : '')
			. $this->name
			. $this->parametersToString()
			. $this->returnTypeToString()
			. ($this->abstract || $this->body === null
				? ';'
				: "\n{\n" . \PHPStanVendor\Nette\Utils\Strings::indent(ltrim(rtrim($this->body) . "\n"), 1) . '}');
	}


	/**
	 * @param  string|null
	 * @return static
	 */
	public function setBody($code, array $args = null): self
	{
		if ($code === false) {
			$code = null;
			trigger_error(__METHOD__ . '() use null instead of false', E_USER_DEPRECATED);
		}
		$this->body = $args === null ? $code : \PHPStanVendor\Nette\PhpGenerator\Helpers::formatArgs($code, $args);
		return $this;
	}


	/**
	 * @return string|null
	 */
	public function getBody()
	{
		return $this->body;
	}


	/**
	 * @return static
	 */
	public function setStatic(bool $state = true): self
	{
		$this->static = $state;
		return $this;
	}


	public function isStatic(): bool
	{
		return $this->static;
	}


	/**
	 * @return static
	 */
	public function setFinal(bool $state = true): self
	{
		$this->final = $state;
		return $this;
	}


	public function isFinal(): bool
	{
		return $this->final;
	}


	/**
	 * @return static
	 */
	public function setAbstract(bool $state = true): self
	{
		$this->abstract = $state;
		return $this;
	}


	public function isAbstract(): bool
	{
		return $this->abstract;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

declare(strict_types=1);

namespace PHPStanVendor\Nette\PhpGenerator;


/**
 * Method parameter description.
 *
 * @property mixed $defaultValue
 */
final class Parameter
{
	use \PHPStanVendor\Nette\SmartObject;
	use \PHPStanVendor\Nette\PhpGenerator\Traits\NameAware;

	/** @var bool */
	private $reference = false;

	/** @var string|null */
	private $typeHint;

	/** @var bool */
	private $nullable = false;

	/** @var bool */
	private $hasDefaultValue = false;

	/** @var mixed */
	private $defaultValue;


	/**
	 * @return static
	 */
	public function setReference(bool $state = true): self
	{
		$this->reference = $state;
		return $this;
	}


	public function isReference(): bool
	{
		return $this->reference;
	}


	/**
	 * @param  string|null
	 * @return static
	 */
	public function setTypeHint($hint): self
	{
		$this->typeHint = $hint ? (string) $hint : null;
		return $this;
	}


	/**
	 * @return string|null
	 */
	public function getTypeHint()
	{
		return $this->typeHint;
	}


	/**
	 * @deprecated  just use setDefaultValue()
	 * @return static
	 */
	public function setOptional(bool $state = true): self
	{
		$this->hasDefaultValue = $state;
		return $this;
	}


	/**
	 * @deprecated  use hasDefaultValue()
	 */
	public function isOptional(): bool
	{
		trigger_error(__METHOD__ . '() is deprecated, use hasDefaultValue()', E_USER_DEPRECATED);
		return $this->hasDefaultValue;
	}


	/**
	 * @return static
	 */
	public function setNullable(bool $state = true): self
	{
		$this->nullable = $state;
		return $this;
	}


	public function isNullable(): bool
	{
		return $this->nullable;
	}


	/**
	 * @return static
	 */
	public function setDefaultValue($val): self
	{
		$this->defaultValue = $val;
		$this->hasDefaultValue = true;
		return $this;
	}


	public function getDefaultValue()
	{
		return $this->defaultValue;
	}


	public function hasDefaultValue(): bool
	{
		return $this->hasDefaultValue;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

declare(strict_types=1);

namespace PHPStanVendor\Nette\PhpGenerator;


/**
 * Instance of PHP file.
 *
 * Generates:
 * - opening tag (<?php)
 * - doc comments
 * - one or more namespaces
 */
final class PhpFile
{
	use \PHPStanVendor\Nette\SmartObject;
	use \PHPStanVendor\Nette\PhpGenerator\Traits\CommentAware;

	/** @var PhpNamespace[] */
	private $namespaces = [];


	public function addClass(string $name): \PHPStanVendor\Nette\PhpGenerator\ClassType
	{
		return $this
			->addNamespace(\PHPStanVendor\Nette\PhpGenerator\Helpers::extractNamespace($name))
			->addClass(\PHPStanVendor\Nette\PhpGenerator\Helpers::extractShortName($name));
	}


	public function addInterface(string $name): \PHPStanVendor\Nette\PhpGenerator\ClassType
	{
		return $this
			->addNamespace(\PHPStanVendor\Nette\PhpGenerator\Helpers::extractNamespace($name))
			->addInterface(\PHPStanVendor\Nette\PhpGenerator\Helpers::extractShortName($name));
	}


	public function addTrait(string $name): \PHPStanVendor\Nette\PhpGenerator\ClassType
	{
		return $this
			->addNamespace(\PHPStanVendor\Nette\PhpGenerator\Helpers::extractNamespace($name))
			->addTrait(\PHPStanVendor\Nette\PhpGenerator\Helpers::extractShortName($name));
	}


	public function addNamespace(string $name): \PHPStanVendor\Nette\PhpGenerator\PhpNamespace
	{
		if (!isset($this->namespaces[$name])) {
			$this->namespaces[$name] = new \PHPStanVendor\Nette\PhpGenerator\PhpNamespace($name);
		}
		return $this->namespaces[$name];
	}


	public function __toString(): string
	{
		foreach ($this->namespaces as $namespace) {
			$namespace->setBracketedSyntax(count($this->namespaces) > 1 && isset($this->namespaces['']));
		}

		return \PHPStanVendor\Nette\Utils\Strings::normalize(
			"<?php\n"
			. ($this->comment ? "\n" . \PHPStanVendor\Nette\PhpGenerator\Helpers::formatDocComment($this->comment . "\n") . "\n" : '')
			. implode("\n\n", $this->namespaces)
		) . "\n";
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

declare(strict_types=1);

namespace PHPStanVendor\Nette\PhpGenerator;


/**
 * PHP literal value.
 */
final class PhpLiteral
{
	/** @var string */
	private $value;


	public function __construct(string $value)
	{
		$this->value = $value;
	}


	public function __toString(): string
	{
		return $this->value;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

declare(strict_types=1);

namespace PHPStanVendor\Nette\PhpGenerator;


/**
 * Namespaced part of a PHP file.
 *
 * Generates:
 * - namespace statement
 * - variable amount of use statements
 * - one or more class declarations
 */
final class PhpNamespace
{
	use \PHPStanVendor\Nette\SmartObject;

	private static $keywords = [
		'string' => 1, 'int' => 1, 'float' => 1, 'bool' => 1, 'array' => 1,
		'callable' => 1, 'iterable' => 1, 'void' => 1, 'self' => 1, 'parent' => 1,
	];

	/** @var string */
	private $name;

	/** @var bool */
	private $bracketedSyntax = false;

	/** @var string[] */
	private $uses = [];

	/** @var ClassType[] */
	private $classes = [];


	public function __construct(string $name)
	{
		if ($name !== '' && !\PHPStanVendor\Nette\PhpGenerator\Helpers::isNamespaceIdentifier($name)) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException("Value '$name' is not valid name.");
		}
		$this->name = $name;
	}


	/** @deprecated */
	public function setName($name)
	{
		trigger_error(__METHOD__ . '() is deprecated, use constructor.', E_USER_DEPRECATED);
		$this->__construct($name);
		return $this;
	}


	public function getName(): string
	{
		return $this->name;
	}


	/**
	 * @return static
	 * @internal
	 */
	public function setBracketedSyntax(bool $state = true): self
	{
		$this->bracketedSyntax = $state;
		return $this;
	}


	public function getBracketedSyntax(): bool
	{
		return $this->bracketedSyntax;
	}


	/**
	 * @throws InvalidStateException
	 * @return static
	 */
	public function addUse(string $name, string $alias = null, string &$aliasOut = null): self
	{
		$name = ltrim($name, '\\');
		if ($alias === null && $this->name === \PHPStanVendor\Nette\PhpGenerator\Helpers::extractNamespace($name)) {
			$alias = \PHPStanVendor\Nette\PhpGenerator\Helpers::extractShortName($name);
		}
		if ($alias === null) {
			$path = explode('\\', $name);
			$counter = null;
			do {
				if (empty($path)) {
					$counter++;
				} else {
					$alias = array_pop($path) . $alias;
				}
			} while (isset($this->uses[$alias . $counter]) && $this->uses[$alias . $counter] !== $name);
			$alias .= $counter;

		} elseif (isset($this->uses[$alias]) && $this->uses[$alias] !== $name) {
			throw new \PHPStanVendor\Nette\InvalidStateException(
				"Alias '$alias' used already for '{$this->uses[$alias]}', cannot use for '{$name}'."
			);
		}

		$aliasOut = $alias;
		$this->uses[$alias] = $name;
		return $this;
	}


	/**
	 * @return string[]
	 */
	public function getUses(): array
	{
		return $this->uses;
	}


	public function unresolveName(string $name): string
	{
		if (isset(self::$keywords[strtolower($name)]) || $name === '') {
			return $name;
		}
		$name = ltrim($name, '\\');
		$res = null;
		$lower = strtolower($name);
		foreach ($this->uses as $alias => $for) {
			if (\PHPStanVendor\Nette\Utils\Strings::startsWith($lower . '\\', strtolower($for) . '\\')) {
				$short = $alias . substr($name, strlen($for));
				if (!isset($res) || strlen($res) > strlen($short)) {
					$res = $short;
				}
			}
		}

		if (!$res && \PHPStanVendor\Nette\Utils\Strings::startsWith($lower, strtolower($this->name) . '\\')) {
			return substr($name, strlen($this->name) + 1);
		} else {
			return $res ?: ($this->name ? '\\' : '') . $name;
		}
	}


	public function addClass(string $name): \PHPStanVendor\Nette\PhpGenerator\ClassType
	{
		if (isset($this->classes[$name])) {
			trigger_error(__METHOD__ . "() class $name was already added.", E_USER_DEPRECATED);
			return $this->classes[$name];
		}
		$this->addUse($this->name . '\\' . $name);
		return $this->classes[$name] = new \PHPStanVendor\Nette\PhpGenerator\ClassType($name, $this);
	}


	public function addInterface(string $name): \PHPStanVendor\Nette\PhpGenerator\ClassType
	{
		return $this->addClass($name)->setType(\PHPStanVendor\Nette\PhpGenerator\ClassType::TYPE_INTERFACE);
	}


	public function addTrait(string $name): \PHPStanVendor\Nette\PhpGenerator\ClassType
	{
		return $this->addClass($name)->setType(\PHPStanVendor\Nette\PhpGenerator\ClassType::TYPE_TRAIT);
	}


	/**
	 * @return ClassType[]
	 */
	public function getClasses(): array
	{
		return $this->classes;
	}


	public function __toString(): string
	{
		$uses = [];
		asort($this->uses);
		foreach ($this->uses as $alias => $name) {
			$useNamespace = \PHPStanVendor\Nette\PhpGenerator\Helpers::extractNamespace($name);

			if ($this->name !== $useNamespace) {
				if ($alias === $name || substr($name, -(strlen($alias) + 1)) === '\\' . $alias) {
					$uses[] = "use {$name};";
				} else {
					$uses[] = "use {$name} as {$alias};";
				}
			}
		}

		$body = ($uses ? implode("\n", $uses) . "\n\n" : '')
			. implode("\n", $this->classes);

		if ($this->bracketedSyntax) {
			return 'namespace' . ($this->name ? ' ' . $this->name : '') . " {\n\n"
				. \PHPStanVendor\Nette\Utils\Strings::indent($body)
				. "\n}\n";

		} else {
			return ($this->name ? "namespace {$this->name};\n\n" : '')
				. $body;
		}
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

declare(strict_types=1);

namespace PHPStanVendor\Nette\PhpGenerator;


/**
 * Class property description.
 *
 * @property mixed $value
 */
final class Property
{
	use \PHPStanVendor\Nette\SmartObject;
	use \PHPStanVendor\Nette\PhpGenerator\Traits\NameAware;
	use \PHPStanVendor\Nette\PhpGenerator\Traits\VisibilityAware;
	use \PHPStanVendor\Nette\PhpGenerator\Traits\CommentAware;

	/** @var mixed */
	private $value;

	/** @var bool */
	private $static = false;


	/**
	 * @return static
	 */
	public function setValue($val): self
	{
		$this->value = $val;
		return $this;
	}


	public function &getValue()
	{
		return $this->value;
	}


	/**
	 * @return static
	 */
	public function setStatic(bool $state = true): self
	{
		$this->static = $state;
		return $this;
	}


	public function isStatic(): bool
	{
		return $this->static;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

declare(strict_types=1);

namespace PHPStanVendor\Nette\PhpGenerator\Traits;


/**
 * @internal
 */
trait CommentAware
{
	/** @var string|null */
	private $comment;


	/**
	 * @param  string|null
	 * @return static
	 */
	public function setComment($val): self
	{
		$this->comment = $val ? (string) $val : null;
		return $this;
	}


	/**
	 * @return string|null
	 */
	public function getComment()
	{
		return $this->comment;
	}


	/**
	 * @return static
	 */
	public function addComment(string $val): self
	{
		$this->comment .= $this->comment ? "\n$val" : $val;
		return $this;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

declare(strict_types=1);

namespace PHPStanVendor\Nette\PhpGenerator\Traits;


/**
 * @internal
 */
trait FunctionLike
{
	/** @var string */
	private $body = '';

	/** @var array of name => Parameter */
	private $parameters = [];

	/** @var bool */
	private $variadic = false;

	/** @var string|null */
	private $returnType;

	/** @var bool */
	private $returnReference = false;

	/** @var bool */
	private $returnNullable = false;

	/** @var PhpNamespace|null */
	private $namespace;


	/**
	 * @return static
	 */
	public function setBody(string $code, array $args = null): self
	{
		$this->body = $args === null ? $code : \PHPStanVendor\Nette\PhpGenerator\Helpers::formatArgs($code, $args);
		return $this;
	}


	public function getBody(): string
	{
		return $this->body;
	}


	/**
	 * @return static
	 */
	public function addBody(string $code, array $args = null): self
	{
		$this->body .= ($args === null ? $code : \PHPStanVendor\Nette\PhpGenerator\Helpers::formatArgs($code, $args)) . "\n";
		return $this;
	}


	/**
	 * @param  Parameter[]
	 * @return static
	 */
	public function setParameters(array $val): self
	{
		$this->parameters = [];
		foreach ($val as $v) {
			if (!$v instanceof \PHPStanVendor\Nette\PhpGenerator\Parameter) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException('Argument must be \PHPStanVendor\Nette\PhpGenerator\Parameter[].');
			}
			$this->parameters[$v->getName()] = $v;
		}
		return $this;
	}


	/**
	 * @return Parameter[]
	 */
	public function getParameters(): array
	{
		return $this->parameters;
	}


	/**
	 * @param  string  without $
	 */
	public function addParameter(string $name, $defaultValue = null): \PHPStanVendor\Nette\PhpGenerator\Parameter
	{
		$param = new \PHPStanVendor\Nette\PhpGenerator\Parameter($name);
		if (func_num_args() > 1) {
			$param->setDefaultValue($defaultValue);
		}
		return $this->parameters[$name] = $param;
	}


	/**
	 * @return static
	 */
	public function setVariadic(bool $state = true): self
	{
		$this->variadic = $state;
		return $this;
	}


	public function isVariadic(): bool
	{
		return $this->variadic;
	}


	/**
	 * @param  string|null
	 * @return static
	 */
	public function setReturnType($val): self
	{
		$this->returnType = $val ? (string) $val : null;
		return $this;
	}


	/**
	 * @return string|null
	 */
	public function getReturnType()
	{
		return $this->returnType;
	}


	/**
	 * @return static
	 */
	public function setReturnReference(bool $state = true): self
	{
		$this->returnReference = $state;
		return $this;
	}


	public function getReturnReference(): bool
	{
		return $this->returnReference;
	}


	/**
	 * @return static
	 */
	public function setReturnNullable(bool $state = true): self
	{
		$this->returnNullable = $state;
		return $this;
	}


	public function getReturnNullable(): bool
	{
		return $this->returnNullable;
	}


	/**
	 * @return static
	 */
	public function setNamespace(\PHPStanVendor\Nette\PhpGenerator\PhpNamespace $val = null): self
	{
		$this->namespace = $val;
		return $this;
	}


	protected function parametersToString(): string
	{
		$params = [];
		foreach ($this->parameters as $param) {
			$variadic = $this->variadic && $param === end($this->parameters);
			$hint = $param->getTypeHint();
			$params[] = ($hint ? ($param->isNullable() ? '?' : '') . ($this->namespace ? $this->namespace->unresolveName($hint) : $hint) . ' ' : '')
				. ($param->isReference() ? '&' : '')
				. ($variadic ? '...' : '')
				. '$' . $param->getName()
				. ($param->hasDefaultValue() && !$variadic ? ' = ' . \PHPStanVendor\Nette\PhpGenerator\Helpers::dump($param->getDefaultValue()) : '');
		}
		return '(' . implode(', ', $params) . ')';
	}


	protected function returnTypeToString(): string
	{
		return $this->returnType
			? ': ' . ($this->returnNullable ? '?' : '') . ($this->namespace ? $this->namespace->unresolveName($this->returnType) : $this->returnType)
			: '';
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

declare(strict_types=1);

namespace PHPStanVendor\Nette\PhpGenerator\Traits;


/**
 * @internal
 */
trait NameAware
{
	/** @var string */
	private $name;


	public function __construct(string $name)
	{
		if (!\PHPStanVendor\Nette\PhpGenerator\Helpers::isIdentifier($name)) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException("Value '$name' is not valid name.");
		}
		$this->name = $name;
	}


	public function getName(): string
	{
		return $this->name;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

declare(strict_types=1);

namespace PHPStanVendor\Nette\PhpGenerator\Traits;


/**
 * @internal
 */
trait VisibilityAware
{
	/** @var string|null  public|protected|private */
	private $visibility;


	/**
	 * @param  string|null  public|protected|private
	 * @return static
	 */
	public function setVisibility($val): self
	{
		if (!in_array($val, ['public', 'protected', 'private', null], true)) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException('Argument must be public|protected|private.');
		}
		$this->visibility = $val;
		return $this;
	}


	/**
	 * @return string|null
	 */
	public function getVisibility()
	{
		return $this->visibility;
	}
}
{
	"name": "nette/robot-loader",
	"description": "🍀 Nette RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.",
	"keywords": ["nette", "autoload", "class", "trait", "interface"],
	"homepage": "https://nette.org",
	"license": ["BSD-3-Clause", "GPL-2.0", "GPL-3.0"],
	"authors": [
		{
			"name": "David Grudl",
			"homepage": "https://davidgrudl.com"
		},
		{
			"name": "Nette Community",
			"homepage": "https://nette.org/contributors"
		}
	],
	"require": {
		"php": ">=5.6.0",
		"ext-tokenizer": "*",
		"nette/finder": "^2.3 || ^3.0",
		"nette/utils": "^2.4 || ^3.0"
	},
	"require-dev": {
		"nette/tester": "^2.0",
		"tracy/tracy": "^2.3"
	},
	"conflict": {
		"nette/nette": "<2.2"
	},
	"autoload": {
		"classmap": ["src/"]
	},
	"minimum-stability": "dev",
	"extra": {
		"branch-alias": {
			"dev-master": "3.0-dev"
		}
	}
}
Licenses
========

Good news! You may use Nette Framework under the terms of either
the New BSD License or the GNU General Public License (GPL) version 2 or 3.

The BSD License is recommended for most projects. It is easy to understand and it
places almost no restrictions on what you can do with the framework. If the GPL
fits better to your project, you can use the framework under this license.

You don't have to notify anyone which license you are using. You can freely
use Nette Framework in commercial projects as long as the copyright header
remains intact.

Please be advised that the name "Nette Framework" is a protected trademark and its
usage has some limitations. So please do not use word "Nette" in the name of your
project or top-level domain, and choose a name that stands on its own merits.
If your stuff is good, it will not take long to establish a reputation for yourselves.


New BSD License
---------------

Copyright (c) 2004, 2014 David Grudl (https://davidgrudl.com)
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

	* Redistributions of source code must retain the above copyright notice,
	this list of conditions and the following disclaimer.

	* Redistributions in binary form must reproduce the above copyright notice,
	this list of conditions and the following disclaimer in the documentation
	and/or other materials provided with the distribution.

	* Neither the name of "Nette Framework" nor the names of its contributors
	may be used to endorse or promote products derived from this software
	without specific prior written permission.

This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall the copyright owner or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused and on
any theory of liability, whether in contract, strict liability, or tort
(including negligence or otherwise) arising in any way out of the use of this
software, even if advised of the possibility of such damage.


GNU General Public License
--------------------------

GPL licenses are very very long, so instead of including them here we offer
you URLs with full text:

- [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html)
- [GPL version 3](http://www.gnu.org/licenses/gpl-3.0.html)
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Loaders;


/**
 * Nette auto loader is responsible for loading classes and interfaces.
 *
 * <code>
 * $loader = new Nette\Loaders\RobotLoader;
 * $loader->addDirectory('app');
 * $loader->excludeDirectory('app/exclude');
 * $loader->setTempDirectory('temp');
 * $loader->register();
 * </code>
 */
class RobotLoader
{
	use \PHPStanVendor\Nette\SmartObject;

	const RETRY_LIMIT = 3;

	/** @var array  comma separated wildcards */
	public $ignoreDirs = ['.*', '*.old', '*.bak', '*.tmp', 'temp'];

	/** @var array  comma separated wildcards */
	public $acceptFiles = ['*.php'];

	/** @var bool */
	private $autoRebuild = true;

	/** @var array */
	private $scanPaths = [];

	/** @var array */
	private $excludeDirs = [];

	/** @var array of class => [file, time] */
	private $classes = [];

	/** @var bool */
	private $refreshed = false;

	/** @var array of missing classes */
	private $missing = [];

	/** @var string|null */
	private $tempDirectory;


	public function __construct()
	{
		if (!extension_loaded('tokenizer')) {
			throw new \PHPStanVendor\Nette\NotSupportedException('PHP extension Tokenizer is not loaded.');
		}
	}


	/**
	 * Register autoloader.
	 * @param  bool  prepend autoloader?
	 * @return static
	 */
	public function register($prepend = false)
	{
		$this->loadCache();
		spl_autoload_register([$this, 'tryLoad'], true, (bool) $prepend);
		return $this;
	}


	/**
	 * Handles autoloading of classes, interfaces or traits.
	 * @param  string
	 * @return void
	 */
	public function tryLoad($type)
	{
		$type = ltrim($type, '\\'); // PHP namespace bug #49143
		$info = isset($this->classes[$type]) ? $this->classes[$type] : null;

		if ($this->autoRebuild) {
			if (!$info || !is_file($info['file'])) {
				$missing = &$this->missing[$type];
				$missing++;
				if (!$this->refreshed && $missing <= self::RETRY_LIMIT) {
					$this->refresh();
					$this->saveCache();
				} elseif ($info) {
					unset($this->classes[$type]);
					$this->saveCache();
				}

			} elseif (!$this->refreshed && filemtime($info['file']) !== $info['time']) {
				$this->updateFile($info['file']);
				if (empty($this->classes[$type])) {
					$this->missing[$type] = 0;
				}
				$this->saveCache();
			}
			$info = isset($this->classes[$type]) ? $this->classes[$type] : null;
		}

		if ($info) {
			call_user_func(function ($file) { require $file; }, $info['file']);
		}
	}


	/**
	 * Add path or paths to list.
	 * @param  string|string[]  absolute path
	 * @return static
	 */
	public function addDirectory($path)
	{
		$this->scanPaths = array_merge($this->scanPaths, (array) $path);
		return $this;
	}


	/**
	 * Excludes path or paths from list.
	 * @param  string|string[]  absolute path
	 * @return static
	 */
	public function excludeDirectory($path)
	{
		$this->excludeDirs = array_merge($this->excludeDirs, (array) $path);
		return $this;
	}


	/**
	 * @return array of class => filename
	 */
	public function getIndexedClasses()
	{
		$res = [];
		foreach ($this->classes as $class => $info) {
			$res[$class] = $info['file'];
		}
		return $res;
	}


	/**
	 * Rebuilds class list cache.
	 * @return void
	 */
	public function rebuild()
	{
		$this->refresh();
		if ($this->tempDirectory) {
			$this->saveCache();
		}
	}


	/**
	 * Refreshes class list.
	 * @return void
	 */
	private function refresh()
	{
		$this->refreshed = true; // prevents calling refresh() or updateFile() in tryLoad()
		$files = [];
		foreach ($this->classes as $class => $info) {
			$files[$info['file']]['time'] = $info['time'];
			$files[$info['file']]['classes'][] = $class;
		}

		$this->classes = [];
		foreach ($this->scanPaths as $path) {
			foreach (is_file($path) ? [new \SplFileInfo($path)] : $this->createFileIterator($path) as $file) {
				$file = $file->getPathname();
				if (isset($files[$file]) && $files[$file]['time'] == filemtime($file)) {
					$classes = $files[$file]['classes'];
				} else {
					$classes = $this->scanPhp(file_get_contents($file));
				}
				$files[$file] = ['classes' => [], 'time' => filemtime($file)];

				foreach ($classes as $class) {
					$info = &$this->classes[$class];
					if (isset($info['file'])) {
						throw new \PHPStanVendor\Nette\InvalidStateException("Ambiguous class $class resolution; defined in {$info['file']} and in $file.");
					}
					$info = ['file' => $file, 'time' => filemtime($file)];
					unset($this->missing[$class]);
				}
			}
		}
	}


	/**
	 * Creates an iterator scaning directory for PHP files, subdirectories and 'netterobots.txt' files.
	 * @return \Iterator
	 * @throws Nette\IOException if path is not found
	 */
	private function createFileIterator($dir)
	{
		if (!is_dir($dir)) {
			throw new \PHPStanVendor\Nette\IOException("File or directory '$dir' not found.");
		}

		$ignoreDirs = is_array($this->ignoreDirs) ? $this->ignoreDirs : preg_split('#[,\s]+#', $this->ignoreDirs);
		$disallow = [];
		foreach (array_merge($ignoreDirs, $this->excludeDirs) as $item) {
			if ($item = realpath($item)) {
				$disallow[str_replace('\\', '/', $item)] = true;
			}
		}

		$iterator = \PHPStanVendor\Nette\Utils\Finder::findFiles(is_array($this->acceptFiles) ? $this->acceptFiles : preg_split('#[,\s]+#', $this->acceptFiles))
			->filter(function (\SplFileInfo $file) use (&$disallow) {
				return !isset($disallow[str_replace('\\', '/', $file->getPathname())]);
			})
			->from($dir)
			->exclude($ignoreDirs)
			->filter($filter = function (\SplFileInfo $dir) use (&$disallow) {
				$path = str_replace('\\', '/', $dir->getPathname());
				if (is_file("$path/netterobots.txt")) {
					foreach (file("$path/netterobots.txt") as $s) {
						if (preg_match('#^(?:disallow\\s*:)?\\s*(\\S+)#i', $s, $matches)) {
							$disallow[$path . rtrim('/' . ltrim($matches[1], '/'), '/')] = true;
						}
					}
				}
				return !isset($disallow[$path]);
			});

		$filter(new \SplFileInfo($dir));
		return $iterator;
	}


	/**
	 * @return void
	 */
	private function updateFile($file)
	{
		foreach ($this->classes as $class => $info) {
			if (isset($info['file']) && $info['file'] === $file) {
				unset($this->classes[$class]);
			}
		}

		$classes = is_file($file) ? $this->scanPhp(file_get_contents($file)) : [];
		foreach ($classes as $class) {
			$info = &$this->classes[$class];
			if (isset($info['file']) && @filemtime($info['file']) !== $info['time']) { // @ file may not exists
				$this->updateFile($info['file']);
				$info = &$this->classes[$class];
			}
			if (isset($info['file'])) {
				throw new \PHPStanVendor\Nette\InvalidStateException("Ambiguous class $class resolution; defined in {$info['file']} and in $file.");
			}
			$info = ['file' => $file, 'time' => filemtime($file)];
		}
	}


	/**
	 * Searches classes, interfaces and traits in PHP file.
	 * @param  string
	 * @return string[]
	 */
	private function scanPhp($code)
	{
		$expected = false;
		$namespace = '';
		$level = $minLevel = 0;
		$classes = [];

		if (preg_match('#//nette' . 'loader=(\S*)#', $code, $matches)) {
			foreach (explode(',', $matches[1]) as $name) {
				$classes[] = $name;
			}
			return $classes;
		}

		foreach (@token_get_all($code) as $token) { // @ can be corrupted or can use newer syntax
			if (is_array($token)) {
				switch ($token[0]) {
					case T_COMMENT:
					case T_DOC_COMMENT:
					case T_WHITESPACE:
						continue 2;

					case T_NS_SEPARATOR:
					case T_STRING:
						if ($expected) {
							$name .= $token[1];
						}
						continue 2;

					case T_NAMESPACE:
					case T_CLASS:
					case T_INTERFACE:
					case T_TRAIT:
						$expected = $token[0];
						$name = '';
						continue 2;
					case T_CURLY_OPEN:
					case T_DOLLAR_OPEN_CURLY_BRACES:
						$level++;
				}
			}

			if ($expected) {
				switch ($expected) {
					case T_CLASS:
					case T_INTERFACE:
					case T_TRAIT:
						if ($name && $level === $minLevel) {
							$classes[] = $namespace . $name;
						}
						break;

					case T_NAMESPACE:
						$namespace = $name ? $name . '\\' : '';
						$minLevel = $token === '{' ? 1 : 0;
				}

				$expected = null;
			}

			if ($token === '{') {
				$level++;
			} elseif ($token === '}') {
				$level--;
			}
		}
		return $classes;
	}


	/********************* caching ****************d*g**/


	/**
	 * Sets auto-refresh mode.
	 * @return static
	 */
	public function setAutoRefresh($on = true)
	{
		$this->autoRebuild = (bool) $on;
		return $this;
	}


	/**
	 * Sets path to temporary directory.
	 * @return static
	 */
	public function setTempDirectory($dir)
	{
		if (!is_dir($dir)) {
			@mkdir($dir); // @ - directory may already exist
		}
		$this->tempDirectory = $dir;
		return $this;
	}


	/**
	 * Loads class list from cache.
	 * @return void
	 */
	private function loadCache()
	{
		$file = $this->getCacheFile();
		list($this->classes, $this->missing) = @include $file; // @ file may not exist
		if (is_array($this->classes)) {
			return;
		}

		$handle = fopen("$file.lock", 'c+');
		if (!$handle || !flock($handle, LOCK_EX)) {
			throw new \RuntimeException("Unable to create or acquire exclusive lock on file '$file.lock'.");
		}

		list($this->classes, $this->missing) = @include $file; // @ file may not exist
		if (!is_array($this->classes)) {
			$this->classes = [];
			$this->refresh();
			$this->saveCache();
		}

		flock($handle, LOCK_UN);
		fclose($handle);
		@unlink("$file.lock"); // @ file may become locked on Windows
	}


	/**
	 * Writes class list to cache.
	 * @return void
	 */
	private function saveCache()
	{
		$file = $this->getCacheFile();
		$tempFile = $file . uniqid('', true) . '.tmp';
		$code = "<?php\nreturn " . var_export([$this->classes, $this->missing], true) . ";\n";
		if (file_put_contents($tempFile, $code) !== strlen($code) || !rename($tempFile, $file)) {
			@unlink($tempFile); // @ - file may not exist
			throw new \RuntimeException("Unable to create '$file'.");
		}
		if (function_exists('opcache_invalidate')) {
			@opcache_invalidate($file, true); // @ can be restricted
		}
	}


	/**
	 * @return string
	 */
	private function getCacheFile()
	{
		if (!$this->tempDirectory) {
			throw new \LogicException('Set path to temporary directory using setTempDirectory().');
		}
		return $this->tempDirectory . '/' . md5(serialize($this->getCacheKey())) . '.php';
	}


	/**
	 * @return array
	 */
	protected function getCacheKey()
	{
		return [$this->ignoreDirs, $this->acceptFiles, $this->scanPaths, $this->excludeDirs];
	}
}
{
	"name": "nette/utils",
	"description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.",
	"keywords": ["nette", "images", "json", "password", "validation", "utility", "string", "array", "core", "slugify", "utf-8", "unicode", "paginator", "datetime"],
	"homepage": "https://nette.org",
	"license": ["BSD-3-Clause", "GPL-2.0", "GPL-3.0"],
	"authors": [
		{
			"name": "David Grudl",
			"homepage": "https://davidgrudl.com"
		},
		{
			"name": "Nette Community",
			"homepage": "https://nette.org/contributors"
		}
	],
	"require": {
		"php": ">=5.6.0"
	},
	"require-dev": {
		"nette/tester": "~2.0",
		"tracy/tracy": "^2.3"
	},
	"suggest": {
		"ext-iconv": "to use Strings::webalize() and toAscii()",
		"ext-json": "to use Nette\\Utils\\Json",
		"ext-intl": "for script transliteration in Strings::webalize() and toAscii()",
		"ext-mbstring": "to use Strings::lower() etc...",
		"ext-xml": "to use Strings::length() etc. when mbstring is not available",
		"ext-gd": "to use Image"
	},
	"conflict": {
		"nette/nette": "<2.2"
	},
	"autoload": {
		"classmap": ["src/"]
	},
	"minimum-stability": "dev",
	"extra": {
		"branch-alias": {
			"dev-master": "2.4-dev"
		}
	}
}
Licenses
========

Good news! You may use Nette Framework under the terms of either
the New BSD License or the GNU General Public License (GPL) version 2 or 3.

The BSD License is recommended for most projects. It is easy to understand and it
places almost no restrictions on what you can do with the framework. If the GPL
fits better to your project, you can use the framework under this license.

You don't have to notify anyone which license you are using. You can freely
use Nette Framework in commercial projects as long as the copyright header
remains intact.

Please be advised that the name "Nette Framework" is a protected trademark and its
usage has some limitations. So please do not use word "Nette" in the name of your
project or top-level domain, and choose a name that stands on its own merits.
If your stuff is good, it will not take long to establish a reputation for yourselves.


New BSD License
---------------

Copyright (c) 2004, 2014 David Grudl (https://davidgrudl.com)
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

	* Redistributions of source code must retain the above copyright notice,
	this list of conditions and the following disclaimer.

	* Redistributions in binary form must reproduce the above copyright notice,
	this list of conditions and the following disclaimer in the documentation
	and/or other materials provided with the distribution.

	* Neither the name of "Nette Framework" nor the names of its contributors
	may be used to endorse or promote products derived from this software
	without specific prior written permission.

This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall the copyright owner or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused and on
any theory of liability, whether in contract, strict liability, or tort
(including negligence or otherwise) arising in any way out of the use of this
software, even if advised of the possibility of such damage.


GNU General Public License
--------------------------

GPL licenses are very very long, so instead of including them here we offer
you URLs with full text:

- [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html)
- [GPL version 3](http://www.gnu.org/licenses/gpl-3.0.html)
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Iterators;


/**
 * Smarter caching iterator.
 *
 * @property-read bool $first
 * @property-read bool $last
 * @property-read bool $empty
 * @property-read bool $odd
 * @property-read bool $even
 * @property-read int $counter
 * @property-read mixed $nextKey
 * @property-read mixed $nextValue
 */
class CachingIterator extends \CachingIterator implements \Countable
{
	use \PHPStanVendor\Nette\SmartObject;

	/** @var int */
	private $counter = 0;


	public function __construct($iterator)
	{
		if (is_array($iterator) || $iterator instanceof \stdClass) {
			$iterator = new \ArrayIterator($iterator);

		} elseif ($iterator instanceof \IteratorAggregate) {
			do {
				$iterator = $iterator->getIterator();
			} while ($iterator instanceof \IteratorAggregate);

		} elseif ($iterator instanceof \Traversable) {
			if (!$iterator instanceof \Iterator) {
				$iterator = new \IteratorIterator($iterator);
			}
		} else {
			throw new \PHPStanVendor\Nette\InvalidArgumentException(sprintf('Invalid argument passed to %s; array or Traversable expected, %s given.', __CLASS__, is_object($iterator) ? get_class($iterator) : gettype($iterator)));
		}

		parent::__construct($iterator, 0);
	}


	/**
	 * Is the current element the first one?
	 * @param  int  grid width
	 * @return bool
	 */
	public function isFirst($width = null)
	{
		return $this->counter === 1 || ($width && $this->counter !== 0 && (($this->counter - 1) % $width) === 0);
	}


	/**
	 * Is the current element the last one?
	 * @param  int  grid width
	 * @return bool
	 */
	public function isLast($width = null)
	{
		return !$this->hasNext() || ($width && ($this->counter % $width) === 0);
	}


	/**
	 * Is the iterator empty?
	 * @return bool
	 */
	public function isEmpty()
	{
		return $this->counter === 0;
	}


	/**
	 * Is the counter odd?
	 * @return bool
	 */
	public function isOdd()
	{
		return $this->counter % 2 === 1;
	}


	/**
	 * Is the counter even?
	 * @return bool
	 */
	public function isEven()
	{
		return $this->counter % 2 === 0;
	}


	/**
	 * Returns the counter.
	 * @return int
	 */
	public function getCounter()
	{
		return $this->counter;
	}


	/**
	 * Returns the count of elements.
	 * @return int
	 */
	public function count()
	{
		$inner = $this->getInnerIterator();
		if ($inner instanceof \Countable) {
			return $inner->count();

		} else {
			throw new \PHPStanVendor\Nette\NotSupportedException('Iterator is not countable.');
		}
	}


	/**
	 * Forwards to the next element.
	 * @return void
	 */
	public function next()
	{
		parent::next();
		if (parent::valid()) {
			$this->counter++;
		}
	}


	/**
	 * Rewinds the Iterator.
	 * @return void
	 */
	public function rewind()
	{
		parent::rewind();
		$this->counter = parent::valid() ? 1 : 0;
	}


	/**
	 * Returns the next key.
	 * @return mixed
	 */
	public function getNextKey()
	{
		return $this->getInnerIterator()->key();
	}


	/**
	 * Returns the next element.
	 * @return mixed
	 */
	public function getNextValue()
	{
		return $this->getInnerIterator()->current();
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Iterators;


/**
 * CallbackFilterIterator for PHP < 5.4.
 * @deprecated use CallbackFilterIterator
 */
class Filter extends \FilterIterator
{
	/** @var callable */
	protected $callback;


	public function __construct(\Iterator $iterator, $callback)
	{
		trigger_error(__CLASS__ . ' is deprecated, use CallbackFilterIterator.', E_USER_WARNING);
		parent::__construct($iterator);
		$this->callback = \PHPStanVendor\Nette\Utils\Callback::check($callback);
	}


	public function accept()
	{
		return call_user_func($this->callback, $this->current(), $this->key(), $this);
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Iterators;


/**
 * Applies the callback to the elements of the inner iterator.
 */
class Mapper extends \IteratorIterator
{
	/** @var callable */
	private $callback;


	public function __construct(\Traversable $iterator, callable $callback)
	{
		parent::__construct($iterator);
		$this->callback = $callback;
	}


	public function current()
	{
		return call_user_func($this->callback, parent::current(), parent::key());
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Iterators;


/**
 * RecursiveCallbackFilterIterator for PHP < 5.4.
 * @deprecated use RecursiveCallbackFilterIterator
 */
class RecursiveFilter extends \PHPStanVendor\Nette\Iterators\Filter implements \RecursiveIterator
{
	public function __construct(\RecursiveIterator $iterator, $callback)
	{
		trigger_error(__CLASS__ . ' is deprecated, use RecursiveCallbackFilterIterator.', E_USER_WARNING);
		parent::__construct($iterator, $callback);
	}


	public function hasChildren()
	{
		return $this->getInnerIterator()->hasChildren();
	}


	public function getChildren()
	{
		return new static($this->getInnerIterator()->getChildren(), $this->callback);
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Utils;


/**
 * Provides objects to work as array.
 */
class ArrayHash extends \stdClass implements \ArrayAccess, \Countable, \IteratorAggregate
{

	/**
	 * @param  array to wrap
	 * @param  bool
	 * @return static
	 */
	public static function from($arr, $recursive = true)
	{
		$obj = new static;
		foreach ($arr as $key => $value) {
			if ($recursive && is_array($value)) {
				$obj->$key = static::from($value, true);
			} else {
				$obj->$key = $value;
			}
		}
		return $obj;
	}


	/**
	 * Returns an iterator over all items.
	 * @return \RecursiveArrayIterator
	 */
	public function getIterator()
	{
		return new \RecursiveArrayIterator((array) $this);
	}


	/**
	 * Returns items count.
	 * @return int
	 */
	public function count()
	{
		return count((array) $this);
	}


	/**
	 * Replaces or appends a item.
	 * @return void
	 */
	public function offsetSet($key, $value)
	{
		if (!is_scalar($key)) { // prevents null
			throw new \PHPStanVendor\Nette\InvalidArgumentException(sprintf('Key must be either a string or an integer, %s given.', gettype($key)));
		}
		$this->$key = $value;
	}


	/**
	 * Returns a item.
	 * @return mixed
	 */
	public function offsetGet($key)
	{
		return $this->$key;
	}


	/**
	 * Determines whether a item exists.
	 * @return bool
	 */
	public function offsetExists($key)
	{
		return isset($this->$key);
	}


	/**
	 * Removes the element from this list.
	 * @return void
	 */
	public function offsetUnset($key)
	{
		unset($this->$key);
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Utils;


/**
 * Provides the base class for a generic list (items can be accessed by index).
 */
class ArrayList implements \ArrayAccess, \Countable, \IteratorAggregate
{
	use \PHPStanVendor\Nette\SmartObject;

	private $list = [];


	/**
	 * Returns an iterator over all items.
	 * @return \ArrayIterator
	 */
	public function getIterator()
	{
		return new \ArrayIterator($this->list);
	}


	/**
	 * Returns items count.
	 * @return int
	 */
	public function count()
	{
		return count($this->list);
	}


	/**
	 * Replaces or appends a item.
	 * @param  int|null
	 * @param  mixed
	 * @return void
	 * @throws Nette\OutOfRangeException
	 */
	public function offsetSet($index, $value)
	{
		if ($index !== null && !is_int($index)) {
			trigger_error('Index is not integer.', E_USER_NOTICE);
		}
		if ($index === null) {
			$this->list[] = $value;

		} elseif ($index < 0 || $index >= count($this->list)) {
			throw new \PHPStanVendor\Nette\OutOfRangeException('Offset invalid or out of range');

		} else {
			$this->list[(int) $index] = $value;
		}
	}


	/**
	 * Returns a item.
	 * @param  int
	 * @return mixed
	 * @throws Nette\OutOfRangeException
	 */
	public function offsetGet($index)
	{
		if (!is_int($index)) {
			trigger_error('Index is not integer.', E_USER_NOTICE);
		}
		if ($index < 0 || $index >= count($this->list)) {
			throw new \PHPStanVendor\Nette\OutOfRangeException('Offset invalid or out of range');
		}
		return $this->list[(int) $index];
	}


	/**
	 * Determines whether a item exists.
	 * @param  int
	 * @return bool
	 */
	public function offsetExists($index)
	{
		return $index >= 0 && $index < count($this->list);
	}


	/**
	 * Removes the element at the specified position in this list.
	 * @param  int
	 * @return void
	 * @throws Nette\OutOfRangeException
	 */
	public function offsetUnset($index)
	{
		if (!is_int($index)) {
			trigger_error('Index is not integer.', E_USER_NOTICE);
		}
		if ($index < 0 || $index >= count($this->list)) {
			throw new \PHPStanVendor\Nette\OutOfRangeException('Offset invalid or out of range');
		}
		array_splice($this->list, (int) $index, 1);
	}


	/**
	 * Prepends a item.
	 * @param  mixed
	 * @return void
	 */
	public function prepend($value)
	{
		$first = array_slice($this->list, 0, 1);
		$this->offsetSet(0, $value);
		array_splice($this->list, 1, 0, $first);
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Utils;


/**
 * Array tools library.
 */
class Arrays
{
	use \PHPStanVendor\Nette\StaticClass;

	/**
	 * Returns item from array or $default if item is not set.
	 * @param  array
	 * @param  string|int|array one or more keys
	 * @param  mixed
	 * @return mixed
	 * @throws Nette\InvalidArgumentException if item does not exist and default value is not provided
	 */
	public static function get(array $arr, $key, $default = null)
	{
		foreach (is_array($key) ? $key : [$key] as $k) {
			if (is_array($arr) && array_key_exists($k, $arr)) {
				$arr = $arr[$k];
			} else {
				if (func_num_args() < 3) {
					throw new \PHPStanVendor\Nette\InvalidArgumentException("Missing item '$k'.");
				}
				return $default;
			}
		}
		return $arr;
	}


	/**
	 * Returns reference to array item.
	 * @param  array
	 * @param  string|int|array one or more keys
	 * @return mixed
	 * @throws Nette\InvalidArgumentException if traversed item is not an array
	 */
	public static function &getRef(array &$arr, $key)
	{
		foreach (is_array($key) ? $key : [$key] as $k) {
			if (is_array($arr) || $arr === null) {
				$arr = &$arr[$k];
			} else {
				throw new \PHPStanVendor\Nette\InvalidArgumentException('Traversed item is not an array.');
			}
		}
		return $arr;
	}


	/**
	 * Recursively appends elements of remaining keys from the second array to the first.
	 * @return array
	 */
	public static function mergeTree(array $arr1, array $arr2)
	{
		$res = $arr1 + $arr2;
		foreach (array_intersect_key($arr1, $arr2) as $k => $v) {
			if (is_array($v) && is_array($arr2[$k])) {
				$res[$k] = self::mergeTree($v, $arr2[$k]);
			}
		}
		return $res;
	}


	/**
	 * Searches the array for a given key and returns the offset if successful.
	 * @return int|false offset if it is found, false otherwise
	 */
	public static function searchKey(array $arr, $key)
	{
		$foo = [$key => null];
		return array_search(key($foo), array_keys($arr), true);
	}


	/**
	 * Inserts new array before item specified by key.
	 * @return void
	 */
	public static function insertBefore(array &$arr, $key, array $inserted)
	{
		$offset = (int) self::searchKey($arr, $key);
		$arr = array_slice($arr, 0, $offset, true) + $inserted + array_slice($arr, $offset, count($arr), true);
	}


	/**
	 * Inserts new array after item specified by key.
	 * @return void
	 */
	public static function insertAfter(array &$arr, $key, array $inserted)
	{
		$offset = self::searchKey($arr, $key);
		$offset = $offset === false ? count($arr) : $offset + 1;
		$arr = array_slice($arr, 0, $offset, true) + $inserted + array_slice($arr, $offset, count($arr), true);
	}


	/**
	 * Renames key in array.
	 * @return void
	 */
	public static function renameKey(array &$arr, $oldKey, $newKey)
	{
		$offset = self::searchKey($arr, $oldKey);
		if ($offset !== false) {
			$keys = array_keys($arr);
			$keys[$offset] = $newKey;
			$arr = array_combine($keys, $arr);
		}
	}


	/**
	 * Returns array entries that match the pattern.
	 * @return array
	 */
	public static function grep(array $arr, $pattern, $flags = 0)
	{
		return \PHPStanVendor\Nette\Utils\Strings::pcre('preg_grep', [$pattern, $arr, $flags]);
	}


	/**
	 * Returns flattened array.
	 * @return array
	 */
	public static function flatten(array $arr, $preserveKeys = false)
	{
		$res = [];
		$cb = $preserveKeys
			? function ($v, $k) use (&$res) { $res[$k] = $v; }
		: function ($v) use (&$res) { $res[] = $v; };
		array_walk_recursive($arr, $cb);
		return $res;
	}


	/**
	 * Finds whether a variable is a zero-based integer indexed array.
	 * @return bool
	 */
	public static function isList($value)
	{
		return is_array($value) && (!$value || array_keys($value) === range(0, count($value) - 1));
	}


	/**
	 * Reformats table to associative tree. Path looks like 'field|field[]field->field=field'.
	 * @return array|\stdClass
	 */
	public static function associate(array $arr, $path)
	{
		$parts = is_array($path)
			? $path
			: preg_split('#(\[\]|->|=|\|)#', $path, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);

		if (!$parts || $parts[0] === '=' || $parts[0] === '|' || $parts === ['->']) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException("Invalid path '$path'.");
		}

		$res = $parts[0] === '->' ? new \stdClass : [];

		foreach ($arr as $rowOrig) {
			$row = (array) $rowOrig;
			$x = &$res;

			for ($i = 0; $i < count($parts); $i++) {
				$part = $parts[$i];
				if ($part === '[]') {
					$x = &$x[];

				} elseif ($part === '=') {
					if (isset($parts[++$i])) {
						$x = $row[$parts[$i]];
						$row = null;
					}

				} elseif ($part === '->') {
					if (isset($parts[++$i])) {
						$x = &$x->{$row[$parts[$i]]};
					} else {
						$row = is_object($rowOrig) ? $rowOrig : (object) $row;
					}

				} elseif ($part !== '|') {
					$x = &$x[(string) $row[$part]];
				}
			}

			if ($x === null) {
				$x = $row;
			}
		}

		return $res;
	}


	/**
	 * Normalizes to associative array.
	 * @return array
	 */
	public static function normalize(array $arr, $filling = null)
	{
		$res = [];
		foreach ($arr as $k => $v) {
			$res[is_int($k) ? $v : $k] = is_int($k) ? $filling : $v;
		}
		return $res;
	}


	/**
	 * Picks element from the array by key and return its value.
	 * @param  array
	 * @param  string|int array key
	 * @param  mixed
	 * @return mixed
	 * @throws Nette\InvalidArgumentException if item does not exist and default value is not provided
	 */
	public static function pick(array &$arr, $key, $default = null)
	{
		if (array_key_exists($key, $arr)) {
			$value = $arr[$key];
			unset($arr[$key]);
			return $value;

		} elseif (func_num_args() < 3) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException("Missing item '$key'.");

		} else {
			return $default;
		}
	}


	/**
	 * Tests whether some element in the array passes the callback test.
	 * @return bool
	 */
	public static function some(array $arr, callable $callback)
	{
		foreach ($arr as $k => $v) {
			if ($callback($v, $k, $arr)) {
				return true;
			}
		}
		return false;
	}


	/**
	 * Tests whether all elements in the array pass the callback test.
	 * @return bool
	 */
	public static function every(array $arr, callable $callback)
	{
		foreach ($arr as $k => $v) {
			if (!$callback($v, $k, $arr)) {
				return false;
			}
		}
		return true;
	}


	/**
	 * Applies the callback to the elements of the array.
	 * @return array
	 */
	public static function map(array $arr, callable $callback)
	{
		$res = [];
		foreach ($arr as $k => $v) {
			$res[$k] = $callback($v, $k, $arr);
		}
		return $res;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Utils;


/**
 * PHP callable tools.
 */
class Callback
{
	use \PHPStanVendor\Nette\StaticClass;

	/**
	 * @param  mixed   class, object, callable
	 * @param  string  method
	 * @return \Closure
	 */
	public static function closure($callable, $m = null)
	{
		if ($m !== null) {
			$callable = [$callable, $m];

		} elseif (is_string($callable) && count($tmp = explode('::', $callable)) === 2) {
			$callable = $tmp;

		} elseif ($callable instanceof \Closure) {
			return $callable;

		} elseif (is_object($callable)) {
			$callable = [$callable, '__invoke'];
		}

		if (is_string($callable) && function_exists($callable)) {
			return (new \ReflectionFunction($callable))->getClosure();

		} elseif (is_array($callable) && method_exists($callable[0], $callable[1])) {
			return (new \ReflectionMethod($callable[0], $callable[1]))->getClosure($callable[0]);
		}

		self::check($callable);
		$_callable_ = $callable;
		return function (...$args) use ($_callable_) {
			return $_callable_(...$args);
		};
	}


	/**
	 * Invokes callback.
	 * @return mixed
	 */
	public static function invoke($callable, ...$args)
	{
		self::check($callable);
		return call_user_func_array($callable, $args);
	}


	/**
	 * Invokes callback with an array of parameters.
	 * @return mixed
	 */
	public static function invokeArgs($callable, array $args = [])
	{
		self::check($callable);
		return call_user_func_array($callable, $args);
	}


	/**
	 * Invokes internal PHP function with own error handler.
	 * @param  string
	 * @return mixed
	 */
	public static function invokeSafe($function, array $args, $onError)
	{
		$prev = set_error_handler(function ($severity, $message, $file) use ($onError, &$prev, $function) {
			if ($file === '' && defined('HHVM_VERSION')) { // https://github.com/facebook/hhvm/issues/4625
				$file = func_get_arg(5)[1]['file'];
			}
			if ($file === __FILE__) {
				$msg = preg_replace("#^$function\(.*?\): #", '', $message);
				if ($onError($msg, $severity) !== false) {
					return;
				}
			}
			return $prev ? $prev(...func_get_args()) : false;
		});

		try {
			return call_user_func_array($function, $args);
		} finally {
			restore_error_handler();
		}
	}


	/**
	 * @return callable
	 */
	public static function check($callable, $syntax = false)
	{
		if (!is_callable($callable, $syntax)) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException($syntax
				? 'Given value is not a callable type.'
				: sprintf("Callback '%s' is not callable.", self::toString($callable))
			);
		}
		return $callable;
	}


	/**
	 * @return string
	 */
	public static function toString($callable)
	{
		if ($callable instanceof \Closure) {
			$inner = self::unwrap($callable);
			return '{closure' . ($inner instanceof \Closure ? '}' : ' ' . self::toString($inner) . '}');
		} elseif (is_string($callable) && $callable[0] === "\0") {
			return '{lambda}';
		} else {
			is_callable($callable, true, $textual);
			return $textual;
		}
	}


	/**
	 * @return \ReflectionMethod|\ReflectionFunction
	 */
	public static function toReflection($callable)
	{
		if ($callable instanceof \Closure) {
			$callable = self::unwrap($callable);
		} elseif ($callable instanceof \PHPStanVendor\Nette\Callback) {
			trigger_error('\PHPStanVendor\Nette\Callback is deprecated.', E_USER_DEPRECATED);
			$callable = $callable->getNative();
		}

		$class = class_exists(\PHPStanVendor\Nette\Reflection\Method::class) ? \PHPStanVendor\Nette\Reflection\Method::class : 'ReflectionMethod';
		if (is_string($callable) && strpos($callable, '::')) {
			return new $class($callable);
		} elseif (is_array($callable)) {
			return new $class($callable[0], $callable[1]);
		} elseif (is_object($callable) && !$callable instanceof \Closure) {
			return new $class($callable, '__invoke');
		} else {
			$class = class_exists(\PHPStanVendor\Nette\Reflection\GlobalFunction::class) ? \PHPStanVendor\Nette\Reflection\GlobalFunction::class : 'ReflectionFunction';
			return new $class($callable);
		}
	}


	/**
	 * @return bool
	 */
	public static function isStatic($callable)
	{
		return is_array($callable) ? is_string($callable[0]) : is_string($callable);
	}


	/**
	 * Unwraps closure created by self::closure()
	 * @internal
	 * @return callable
	 */
	public static function unwrap(\Closure $closure)
	{
		$r = new \ReflectionFunction($closure);
		if (substr($r->getName(), -1) === '}') {
			$vars = $r->getStaticVariables();
			return isset($vars['_callable_']) ? $vars['_callable_'] : $closure;

		} elseif ($obj = $r->getClosureThis()) {
			return [$obj, $r->getName()];

		} elseif ($class = $r->getClosureScopeClass()) {
			return [$class->getName(), $r->getName()];

		} else {
			return $r->getName();
		}
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Utils;


/**
 * DateTime.
 */
class DateTime extends \DateTime implements \JsonSerializable
{
	use \PHPStanVendor\Nette\SmartObject;

	/** minute in seconds */
	const MINUTE = 60;

	/** hour in seconds */
	const HOUR = 60 * self::MINUTE;

	/** day in seconds */
	const DAY = 24 * self::HOUR;

	/** week in seconds */
	const WEEK = 7 * self::DAY;

	/** average month in seconds */
	const MONTH = 2629800;

	/** average year in seconds */
	const YEAR = 31557600;


	/**
	 * DateTime object factory.
	 * @param  string|int|\DateTimeInterface
	 * @return static
	 */
	public static function from($time)
	{
		if ($time instanceof \DateTimeInterface) {
			return new static($time->format('Y-m-d H:i:s.u'), $time->getTimezone());

		} elseif (is_numeric($time)) {
			if ($time <= self::YEAR) {
				$time += time();
			}
			return (new static('@' . $time))->setTimeZone(new \DateTimeZone(date_default_timezone_get()));

		} else { // textual or null
			return new static($time);
		}
	}


	/**
	 * Creates DateTime object.
	 * @return static
	 */
	public static function fromParts($year, $month, $day, $hour = 0, $minute = 0, $second = 0)
	{
		$s = sprintf('%04d-%02d-%02d %02d:%02d:%02.5f', $year, $month, $day, $hour, $minute, $second);
		if (!checkdate($month, $day, $year) || $hour < 0 || $hour > 23 || $minute < 0 || $minute > 59 || $second < 0 || $second >= 60) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException("Invalid date '$s'");
		}
		return new static($s);
	}


	/**
	 * @return string
	 */
	public function __toString()
	{
		return $this->format('Y-m-d H:i:s');
	}


	/**
	 * @param  string
	 * @return static
	 */
	public function modifyClone($modify = '')
	{
		$dolly = clone $this;
		return $modify ? $dolly->modify($modify) : $dolly;
	}


	/**
	 * @param  int
	 * @return static
	 */
	public function setTimestamp($timestamp)
	{
		$zone = $this->getTimezone();
		$this->__construct('@' . $timestamp);
		return $this->setTimeZone($zone);
	}


	/**
	 * @return int|string
	 */
	public function getTimestamp()
	{
		$ts = $this->format('U');
		return is_float($tmp = $ts * 1) ? $ts : $tmp;
	}


	/**
	 * Returns new DateTime object formatted according to the specified format.
	 * @param string The format the $time parameter should be in
	 * @param string String representing the time
	 * @param string|\DateTimeZone desired timezone (default timezone is used if null is passed)
	 * @return static|false
	 */
	public static function createFromFormat($format, $time, $timezone = null)
	{
		if ($timezone === null) {
			$timezone = new \DateTimeZone(date_default_timezone_get());

		} elseif (is_string($timezone)) {
			$timezone = new \DateTimeZone($timezone);

		} elseif (!$timezone instanceof \DateTimeZone) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException('Invalid timezone given');
		}

		$date = parent::createFromFormat($format, $time, $timezone);
		return $date ? static::from($date) : false;
	}


	/**
	 * Returns JSON representation in ISO 8601 (used by JavaScript).
	 * @return string
	 */
	public function jsonSerialize()
	{
		return $this->format('c');
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Utils;


/**
 * File system tool.
 */
class FileSystem
{
	use \PHPStanVendor\Nette\StaticClass;

	/**
	 * Creates a directory.
	 * @return void
	 * @throws Nette\IOException
	 */
	public static function createDir($dir, $mode = 0777)
	{
		if (!is_dir($dir) && !@mkdir($dir, $mode, true) && !is_dir($dir)) { // @ - dir may already exist
			throw new \PHPStanVendor\Nette\IOException("Unable to create directory '$dir'. " . error_get_last()['message']);
		}
	}


	/**
	 * Copies a file or directory.
	 * @return void
	 * @throws Nette\IOException
	 */
	public static function copy($source, $dest, $overwrite = true)
	{
		if (stream_is_local($source) && !file_exists($source)) {
			throw new \PHPStanVendor\Nette\IOException("File or directory '$source' not found.");

		} elseif (!$overwrite && file_exists($dest)) {
			throw new \PHPStanVendor\Nette\InvalidStateException("File or directory '$dest' already exists.");

		} elseif (is_dir($source)) {
			static::createDir($dest);
			foreach (new \FilesystemIterator($dest) as $item) {
				static::delete($item->getPathname());
			}
			foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST) as $item) {
				if ($item->isDir()) {
					static::createDir($dest . '/' . $iterator->getSubPathName());
				} else {
					static::copy($item->getPathname(), $dest . '/' . $iterator->getSubPathName());
				}
			}

		} else {
			static::createDir(dirname($dest));
			if (@stream_copy_to_stream(fopen($source, 'r'), fopen($dest, 'w')) === false) { // @ is escalated to exception
				throw new \PHPStanVendor\Nette\IOException("Unable to copy file '$source' to '$dest'.");
			}
		}
	}


	/**
	 * Deletes a file or directory.
	 * @return void
	 * @throws Nette\IOException
	 */
	public static function delete($path)
	{
		if (is_file($path) || is_link($path)) {
			$func = DIRECTORY_SEPARATOR === '\\' && is_dir($path) ? 'rmdir' : 'unlink';
			if (!@$func($path)) { // @ is escalated to exception
				throw new \PHPStanVendor\Nette\IOException("Unable to delete '$path'.");
			}

		} elseif (is_dir($path)) {
			foreach (new \FilesystemIterator($path) as $item) {
				static::delete($item->getPathname());
			}
			if (!@rmdir($path)) { // @ is escalated to exception
				throw new \PHPStanVendor\Nette\IOException("Unable to delete directory '$path'.");
			}
		}
	}


	/**
	 * Renames a file or directory.
	 * @return void
	 * @throws Nette\IOException
	 * @throws Nette\InvalidStateException if the target file or directory already exist
	 */
	public static function rename($name, $newName, $overwrite = true)
	{
		if (!$overwrite && file_exists($newName)) {
			throw new \PHPStanVendor\Nette\InvalidStateException("File or directory '$newName' already exists.");

		} elseif (!file_exists($name)) {
			throw new \PHPStanVendor\Nette\IOException("File or directory '$name' not found.");

		} else {
			static::createDir(dirname($newName));
			static::delete($newName);
			if (!@rename($name, $newName)) { // @ is escalated to exception
				throw new \PHPStanVendor\Nette\IOException("Unable to rename file or directory '$name' to '$newName'.");
			}
		}
	}


	/**
	 * Reads file content.
	 * @return string
	 * @throws Nette\IOException
	 */
	public static function read($file)
	{
		$content = @file_get_contents($file); // @ is escalated to exception
		if ($content === false) {
			throw new \PHPStanVendor\Nette\IOException("Unable to read file '$file'.");
		}
		return $content;
	}


	/**
	 * Writes a string to a file.
	 * @return void
	 * @throws Nette\IOException
	 */
	public static function write($file, $content, $mode = 0666)
	{
		static::createDir(dirname($file));
		if (@file_put_contents($file, $content) === false) { // @ is escalated to exception
			throw new \PHPStanVendor\Nette\IOException("Unable to write file '$file'.");
		}
		if ($mode !== null && !@chmod($file, $mode)) { // @ is escalated to exception
			throw new \PHPStanVendor\Nette\IOException("Unable to chmod file '$file'.");
		}
	}


	/**
	 * Is path absolute?
	 * @return bool
	 */
	public static function isAbsolute($path)
	{
		return (bool) preg_match('#([a-z]:)?[/\\\\]|[a-z][a-z0-9+.-]*://#Ai', $path);
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Utils;


/**
 * HTML helper.
 *
 * <code>
 * $el = Html::el('a')->href($link)->setText('Nette');
 * $el->class = 'myclass';
 * echo $el;
 *
 * echo $el->startTag(), $el->endTag();
 * </code>
 */
class Html implements \ArrayAccess, \Countable, \IteratorAggregate, \PHPStanVendor\Nette\Utils\IHtmlString
{
	use \PHPStanVendor\Nette\SmartObject;

	/** @var array  element's attributes */
	public $attrs = [];

	/** @var bool  use XHTML syntax? */
	public static $xhtml = false;

	/** @var array  empty (void) elements */
	public static $emptyElements = [
		'img' => 1, 'hr' => 1, 'br' => 1, 'input' => 1, 'meta' => 1, 'area' => 1, 'embed' => 1, 'keygen' => 1,
		'source' => 1, 'base' => 1, 'col' => 1, 'link' => 1, 'param' => 1, 'basefont' => 1, 'frame' => 1,
		'isindex' => 1, 'wbr' => 1, 'command' => 1, 'track' => 1,
	];

	/** @var array  of Html | string nodes */
	protected $children = [];

	/** @var string  element's name */
	private $name;

	/** @var bool  is element empty? */
	private $isEmpty;


	/**
	 * Static factory.
	 * @param  string element name (or null)
	 * @param  array|string element's attributes or plain text content
	 * @return static
	 */
	public static function el($name = null, $attrs = null)
	{
		$el = new static;
		$parts = explode(' ', (string) $name, 2);
		$el->setName($parts[0]);

		if (is_array($attrs)) {
			$el->attrs = $attrs;

		} elseif ($attrs !== null) {
			$el->setText($attrs);
		}

		if (isset($parts[1])) {
			foreach (\PHPStanVendor\Nette\Utils\Strings::matchAll($parts[1] . ' ', '#([a-z0-9:-]+)(?:=(["\'])?(.*?)(?(2)\\2|\s))?#i') as $m) {
				$el->attrs[$m[1]] = isset($m[3]) ? $m[3] : true;
			}
		}

		return $el;
	}


	/**
	 * Changes element's name.
	 * @param  string
	 * @param  bool  Is element empty?
	 * @return static
	 * @throws Nette\InvalidArgumentException
	 */
	public function setName($name, $isEmpty = null)
	{
		if ($name !== null && !is_string($name)) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException(sprintf('Name must be string or null, %s given.', gettype($name)));
		}

		$this->name = $name;
		$this->isEmpty = $isEmpty === null ? isset(static::$emptyElements[$name]) : (bool) $isEmpty;
		return $this;
	}


	/**
	 * Returns element's name.
	 * @return string
	 */
	public function getName()
	{
		return $this->name;
	}


	/**
	 * Is element empty?
	 * @return bool
	 */
	public function isEmpty()
	{
		return $this->isEmpty;
	}


	/**
	 * Sets multiple attributes.
	 * @param  array
	 * @return static
	 */
	public function addAttributes(array $attrs)
	{
		$this->attrs = array_merge($this->attrs, $attrs);
		return $this;
	}


	/**
	 * Appends value to element's attribute.
	 * @param  string
	 * @param  string|array value to append
	 * @param  string|bool  value option
	 * @return static
	 */
	public function appendAttribute($name, $value, $option = true)
	{
		if (is_array($value)) {
			$prev = isset($this->attrs[$name]) ? (array) $this->attrs[$name] : [];
			$this->attrs[$name] = $value + $prev;

		} elseif ((string) $value === '') {
			$tmp = &$this->attrs[$name]; // appending empty value? -> ignore, but ensure it exists

		} elseif (!isset($this->attrs[$name]) || is_array($this->attrs[$name])) { // needs array
			$this->attrs[$name][$value] = $option;

		} else {
			$this->attrs[$name] = [$this->attrs[$name] => true, $value => $option];
		}
		return $this;
	}


	/**
	 * Sets element's attribute.
	 * @param  string
	 * @param  mixed
	 * @return static
	 */
	public function setAttribute($name, $value)
	{
		$this->attrs[$name] = $value;
		return $this;
	}


	/**
	 * Returns element's attribute.
	 * @param  string
	 * @return mixed
	 */
	public function getAttribute($name)
	{
		return isset($this->attrs[$name]) ? $this->attrs[$name] : null;
	}


	/**
	 * Unsets element's attribute.
	 * @param  string
	 * @return static
	 */
	public function removeAttribute($name)
	{
		unset($this->attrs[$name]);
		return $this;
	}


	/**
	 * Overloaded setter for element's attribute.
	 * @param  string    HTML attribute name
	 * @param  mixed     HTML attribute value
	 * @return void
	 */
	public function __set($name, $value)
	{
		$this->attrs[$name] = $value;
	}


	/**
	 * Overloaded getter for element's attribute.
	 * @param  string    HTML attribute name
	 * @return mixed     HTML attribute value
	 */
	public function &__get($name)
	{
		return $this->attrs[$name];
	}


	/**
	 * Overloaded tester for element's attribute.
	 * @param  string    HTML attribute name
	 * @return bool
	 */
	public function __isset($name)
	{
		return isset($this->attrs[$name]);
	}


	/**
	 * Overloaded unsetter for element's attribute.
	 * @param  string    HTML attribute name
	 * @return void
	 */
	public function __unset($name)
	{
		unset($this->attrs[$name]);
	}


	/**
	 * Overloaded setter for element's attribute.
	 * @param  string  HTML attribute name
	 * @param  array   (string) HTML attribute value or pair?
	 * @return mixed
	 */
	public function __call($m, $args)
	{
		$p = substr($m, 0, 3);
		if ($p === 'get' || $p === 'set' || $p === 'add') {
			$m = substr($m, 3);
			$m[0] = $m[0] | "\x20";
			if ($p === 'get') {
				return isset($this->attrs[$m]) ? $this->attrs[$m] : null;

			} elseif ($p === 'add') {
				$args[] = true;
			}
		}

		if (count($args) === 0) { // invalid

		} elseif (count($args) === 1) { // set
			$this->attrs[$m] = $args[0];

		} else { // add
			$this->appendAttribute($m, $args[0], $args[1]);
		}

		return $this;
	}


	/**
	 * Special setter for element's attribute.
	 * @param  string path
	 * @param  array query
	 * @return static
	 */
	public function href($path, $query = null)
	{
		if ($query) {
			$query = http_build_query($query, '', '&');
			if ($query !== '') {
				$path .= '?' . $query;
			}
		}
		$this->attrs['href'] = $path;
		return $this;
	}


	/**
	 * Setter for data-* attributes. Booleans are converted to 'true' resp. 'false'.
	 * @return static
	 */
	public function data($name, $value = null)
	{
		if (func_num_args() === 1) {
			$this->attrs['data'] = $name;
		} else {
			$this->attrs["data-$name"] = is_bool($value) ? json_encode($value) : $value;
		}
		return $this;
	}


	/**
	 * Sets element's HTML content.
	 * @param  IHtmlString|string
	 * @return static
	 * @throws Nette\InvalidArgumentException
	 */
	public function setHtml($html)
	{
		if (is_array($html)) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException(sprintf('Textual content must be a scalar, %s given.', gettype($html)));
		}
		$this->removeChildren();
		$this->children[] = (string) $html;
		return $this;
	}


	/**
	 * Returns element's HTML content.
	 * @return string
	 */
	public function getHtml()
	{
		return implode('', $this->children);
	}


	/**
	 * Sets element's textual content.
	 * @param  IHtmlString|string
	 * @return static
	 * @throws Nette\InvalidArgumentException
	 */
	public function setText($text)
	{
		if (!$text instanceof \PHPStanVendor\Nette\Utils\IHtmlString) {
			$text = htmlspecialchars((string) $text, ENT_NOQUOTES, 'UTF-8');
		}
		return $this->setHtml($text);
	}


	/**
	 * Returns element's textual content.
	 * @return string
	 */
	public function getText()
	{
		return html_entity_decode(strip_tags($this->getHtml()), ENT_QUOTES, 'UTF-8');
	}


	/**
	 * @deprecated
	 */
	public function add($child)
	{
		trigger_error(__METHOD__ . '() is deprecated, use addHtml() or addText() instead.', E_USER_DEPRECATED);
		return $this->addHtml($child);
	}


	/**
	 * Adds new element's child.
	 * @param  IHtmlString|string  Html node or raw HTML string
	 * @return static
	 */
	public function addHtml($child)
	{
		return $this->insert(null, $child);
	}


	/**
	 * Appends plain-text string to element content.
	 * @param  IHtmlString|string
	 * @return static
	 */
	public function addText($text)
	{
		if (!$text instanceof \PHPStanVendor\Nette\Utils\IHtmlString) {
			$text = htmlspecialchars((string) $text, ENT_NOQUOTES, 'UTF-8');
		}
		return $this->insert(null, $text);
	}


	/**
	 * Creates and adds a new Html child.
	 * @param  string  elements's name
	 * @param  array|string element's attributes or raw HTML string
	 * @return static  created element
	 */
	public function create($name, $attrs = null)
	{
		$this->insert(null, $child = static::el($name, $attrs));
		return $child;
	}


	/**
	 * Inserts child node.
	 * @param  int|null position or null for appending
	 * @param  IHtmlString|string Html node or raw HTML string
	 * @param  bool
	 * @return static
	 * @throws Nette\InvalidArgumentException
	 */
	public function insert($index, $child, $replace = false)
	{
		if ($child instanceof \PHPStanVendor\Nette\Utils\IHtmlString || is_scalar($child)) {
			$child = $child instanceof self ? $child : (string) $child;
			if ($index === null) { // append
				$this->children[] = $child;

			} else { // insert or replace
				array_splice($this->children, (int) $index, $replace ? 1 : 0, [$child]);
			}

		} else {
			throw new \PHPStanVendor\Nette\InvalidArgumentException(sprintf('Child node must be scalar or Html object, %s given.', is_object($child) ? get_class($child) : gettype($child)));
		}

		return $this;
	}


	/**
	 * Inserts (replaces) child node (\ArrayAccess implementation).
	 * @param  int|null position or null for appending
	 * @param  Html|string Html node or raw HTML string
	 * @return void
	 */
	public function offsetSet($index, $child)
	{
		$this->insert($index, $child, true);
	}


	/**
	 * Returns child node (\ArrayAccess implementation).
	 * @param  int
	 * @return static|string
	 */
	public function offsetGet($index)
	{
		return $this->children[$index];
	}


	/**
	 * Exists child node? (\ArrayAccess implementation).
	 * @param  int
	 * @return bool
	 */
	public function offsetExists($index)
	{
		return isset($this->children[$index]);
	}


	/**
	 * Removes child node (\ArrayAccess implementation).
	 * @param  int
	 * @return void
	 */
	public function offsetUnset($index)
	{
		if (isset($this->children[$index])) {
			array_splice($this->children, (int) $index, 1);
		}
	}


	/**
	 * Returns children count.
	 * @return int
	 */
	public function count()
	{
		return count($this->children);
	}


	/**
	 * Removes all children.
	 * @return void
	 */
	public function removeChildren()
	{
		$this->children = [];
	}


	/**
	 * Iterates over elements.
	 * @return \ArrayIterator
	 */
	public function getIterator()
	{
		return new \ArrayIterator($this->children);
	}


	/**
	 * Returns all children.
	 * @return array
	 */
	public function getChildren()
	{
		return $this->children;
	}


	/**
	 * Renders element's start tag, content and end tag.
	 * @param  int
	 * @return string
	 */
	public function render($indent = null)
	{
		$s = $this->startTag();

		if (!$this->isEmpty) {
			// add content
			if ($indent !== null) {
				$indent++;
			}
			foreach ($this->children as $child) {
				if (is_object($child)) {
					$s .= $child->render($indent);
				} else {
					$s .= $child;
				}
			}

			// add end tag
			$s .= $this->endTag();
		}

		if ($indent !== null) {
			return "\n" . str_repeat("\t", $indent - 1) . $s . "\n" . str_repeat("\t", max(0, $indent - 2));
		}
		return $s;
	}


	public function __toString()
	{
		try {
			return $this->render();
		} catch (\Exception $e) {
		} catch (\Throwable $e) {
		}
		trigger_error('Exception in ' . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR);
	}


	/**
	 * Returns element's start tag.
	 * @return string
	 */
	public function startTag()
	{
		if ($this->name) {
			return '<' . $this->name . $this->attributes() . (static::$xhtml && $this->isEmpty ? ' />' : '>');

		} else {
			return '';
		}
	}


	/**
	 * Returns element's end tag.
	 * @return string
	 */
	public function endTag()
	{
		return $this->name && !$this->isEmpty ? '</' . $this->name . '>' : '';
	}


	/**
	 * Returns element's attributes.
	 * @return string
	 * @internal
	 */
	public function attributes()
	{
		if (!is_array($this->attrs)) {
			return '';
		}

		$s = '';
		$attrs = $this->attrs;
		if (isset($attrs['data']) && is_array($attrs['data'])) { // deprecated
			trigger_error('Expanded attribute "data" is deprecated.', E_USER_DEPRECATED);
			foreach ($attrs['data'] as $key => $value) {
				$attrs['data-' . $key] = $value;
			}
			unset($attrs['data']);
		}

		foreach ($attrs as $key => $value) {
			if ($value === null || $value === false) {
				continue;

			} elseif ($value === true) {
				if (static::$xhtml) {
					$s .= ' ' . $key . '="' . $key . '"';
				} else {
					$s .= ' ' . $key;
				}
				continue;

			} elseif (is_array($value)) {
				if (strncmp($key, 'data-', 5) === 0) {
					$value = \PHPStanVendor\Nette\Utils\Json::encode($value);

				} else {
					$tmp = null;
					foreach ($value as $k => $v) {
						if ($v != null) { // intentionally ==, skip nulls & empty string
							//  composite 'style' vs. 'others'
							$tmp[] = $v === true ? $k : (is_string($k) ? $k . ':' . $v : $v);
						}
					}
					if ($tmp === null) {
						continue;
					}

					$value = implode($key === 'style' || !strncmp($key, 'on', 2) ? ';' : ' ', $tmp);
				}

			} elseif (is_float($value)) {
				$value = rtrim(rtrim(number_format($value, 10, '.', ''), '0'), '.');

			} else {
				$value = (string) $value;
			}

			$q = strpos($value, '"') === false ? '"' : "'";
			$s .= ' ' . $key . '=' . $q
				. str_replace(
					['&', $q, '<'],
					['&amp;', $q === '"' ? '&quot;' : '&#39;', self::$xhtml ? '&lt;' : '<'],
					$value
				)
				. (strpos($value, '`') !== false && strpbrk($value, ' <>"\'') === false ? ' ' : '')
				. $q;
		}

		$s = str_replace('@', '&#64;', $s);
		return $s;
	}


	/**
	 * Clones all children too.
	 */
	public function __clone()
	{
		foreach ($this->children as $key => $value) {
			if (is_object($value)) {
				$this->children[$key] = clone $value;
			}
		}
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Utils;


interface IHtmlString
{

	/**
	 * @return string in HTML format
	 */
	function __toString();
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Localization;


/**
 * Translator adapter.
 */
interface ITranslator
{

	/**
	 * Translates the given string.
	 * @param  string   message
	 * @param  int      plural count
	 * @return string
	 */
	function translate($message, $count = null);
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Utils;


/**
 * Basic manipulation with images.
 *
 * <code>
 * $image = Image::fromFile('nette.jpg');
 * $image->resize(150, 100);
 * $image->sharpen();
 * $image->send();
 * </code>
 *
 * @method void alphaBlending(bool $on)
 * @method void antialias(bool $on)
 * @method void arc($x, $y, $w, $h, $start, $end, $color)
 * @method void char(int $font, $x, $y, string $char, $color)
 * @method void charUp(int $font, $x, $y, string $char, $color)
 * @method int colorAllocate($red, $green, $blue)
 * @method int colorAllocateAlpha($red, $green, $blue, $alpha)
 * @method int colorAt($x, $y)
 * @method int colorClosest($red, $green, $blue)
 * @method int colorClosestAlpha($red, $green, $blue, $alpha)
 * @method int colorClosestHWB($red, $green, $blue)
 * @method void colorDeallocate($color)
 * @method int colorExact($red, $green, $blue)
 * @method int colorExactAlpha($red, $green, $blue, $alpha)
 * @method void colorMatch(Image $image2)
 * @method int colorResolve($red, $green, $blue)
 * @method int colorResolveAlpha($red, $green, $blue, $alpha)
 * @method void colorSet($index, $red, $green, $blue)
 * @method array colorsForIndex($index)
 * @method int colorsTotal()
 * @method int colorTransparent($color = null)
 * @method void convolution(array $matrix, float $div, float $offset)
 * @method void copy(Image $src, $dstX, $dstY, $srcX, $srcY, $srcW, $srcH)
 * @method void copyMerge(Image $src, $dstX, $dstY, $srcX, $srcY, $srcW, $srcH, $opacity)
 * @method void copyMergeGray(Image $src, $dstX, $dstY, $srcX, $srcY, $srcW, $srcH, $opacity)
 * @method void copyResampled(Image $src, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH)
 * @method void copyResized(Image $src, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH)
 * @method Image cropAuto(int $mode = -1, float $threshold = .5, int $color = -1)
 * @method void dashedLine($x1, $y1, $x2, $y2, $color)
 * @method void ellipse($cx, $cy, $w, $h, $color)
 * @method void fill($x, $y, $color)
 * @method void filledArc($cx, $cy, $w, $h, $s, $e, $color, $style)
 * @method void filledEllipse($cx, $cy, $w, $h, $color)
 * @method void filledPolygon(array $points, $numPoints, $color)
 * @method void filledRectangle($x1, $y1, $x2, $y2, $color)
 * @method void fillToBorder($x, $y, $border, $color)
 * @method void filter($filtertype)
 * @method void flip(int $mode)
 * @method array ftText($size, $angle, $x, $y, $col, string $fontFile, string $text, array $extrainfo = null)
 * @method void gammaCorrect(float $inputgamma, float $outputgamma)
 * @method int interlace($interlace = null)
 * @method bool isTrueColor()
 * @method void layerEffect($effect)
 * @method void line($x1, $y1, $x2, $y2, $color)
 * @method void paletteCopy(Image $source)
 * @method void paletteToTrueColor()
 * @method void polygon(array $points, $numPoints, $color)
 * @method array psText(string $text, $font, $size, $color, $backgroundColor, $x, $y, $space = null, $tightness = null, float $angle = null, $antialiasSteps = null)
 * @method void rectangle($x1, $y1, $x2, $y2, $col)
 * @method Image rotate(float $angle, $backgroundColor)
 * @method void saveAlpha(bool $saveflag)
 * @method Image scale(int $newWidth, int $newHeight = -1, int $mode = IMG_BILINEAR_FIXED)
 * @method void setBrush(Image $brush)
 * @method void setPixel($x, $y, $color)
 * @method void setStyle(array $style)
 * @method void setThickness($thickness)
 * @method void setTile(Image $tile)
 * @method void string($font, $x, $y, string $s, $col)
 * @method void stringUp($font, $x, $y, string $s, $col)
 * @method void trueColorToPalette(bool $dither, $ncolors)
 * @method array ttfText($size, $angle, $x, $y, $color, string $fontfile, string $text)
 * @property-read int $width
 * @property-read int $height
 * @property-read resource $imageResource
 */
class Image
{
	use \PHPStanVendor\Nette\SmartObject;

	/** {@link resize()} only shrinks images */
	const SHRINK_ONLY = 0b0001;

	/** {@link resize()} will ignore aspect ratio */
	const STRETCH = 0b0010;

	/** {@link resize()} fits in given area so its dimensions are less than or equal to the required dimensions */
	const FIT = 0b0000;

	/** {@link resize()} fills given area so its dimensions are greater than or equal to the required dimensions */
	const FILL = 0b0100;

	/** {@link resize()} fills given area exactly */
	const EXACT = 0b1000;

	/** image types */
	const
		JPEG = IMAGETYPE_JPEG,
		PNG = IMAGETYPE_PNG,
		GIF = IMAGETYPE_GIF,
		WEBP = 18; // IMAGETYPE_WEBP is available as of PHP 7.1

	const EMPTY_GIF = "GIF89a\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\x00\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;";

	/** @deprecated */
	const ENLARGE = 0;

	private static $formats = [self::JPEG => 'jpeg', self::PNG => 'png', self::GIF => 'gif', self::WEBP => 'webp'];

	/** @var resource */
	private $image;


	/**
	 * Returns RGB color.
	 * @param  int  red 0..255
	 * @param  int  green 0..255
	 * @param  int  blue 0..255
	 * @param  int  transparency 0..127
	 * @return array
	 */
	public static function rgb($red, $green, $blue, $transparency = 0)
	{
		return [
			'red' => max(0, min(255, (int) $red)),
			'green' => max(0, min(255, (int) $green)),
			'blue' => max(0, min(255, (int) $blue)),
			'alpha' => max(0, min(127, (int) $transparency)),
		];
	}


	/**
	 * Opens image from file.
	 * @param  string
	 * @param  mixed  detected image format
	 * @throws Nette\NotSupportedException if gd extension is not loaded
	 * @throws UnknownImageFileException if file not found or file type is not known
	 * @return static
	 */
	public static function fromFile($file, &$format = null)
	{
		if (!extension_loaded('gd')) {
			throw new \PHPStanVendor\Nette\NotSupportedException('PHP extension GD is not loaded.');
		}

		$format = @getimagesize($file)[2]; // @ - files smaller than 12 bytes causes read error
		if (!$format && PHP_VERSION_ID < 70100 && @file_get_contents($file, false, null, 8, 4) === 'WEBP') { // @ - may not exists
			$format = self::WEBP;
		}
		if (!isset(self::$formats[$format])) {
			$format = null;
			throw new \PHPStanVendor\Nette\Utils\UnknownImageFileException(is_file($file) ? "Unknown type of file '$file'." : "File '$file' not found.");
		}
		return new static(\PHPStanVendor\Nette\Utils\Callback::invokeSafe('imagecreatefrom' . self::$formats[$format], [$file], function ($message) {
			throw new \PHPStanVendor\Nette\Utils\ImageException($message);
		}));
	}


	/**
	 * Create a new image from the image stream in the string.
	 * @param  string
	 * @param  mixed  detected image format
	 * @return static
	 * @throws ImageException
	 */
	public static function fromString($s, &$format = null)
	{
		if (!extension_loaded('gd')) {
			throw new \PHPStanVendor\Nette\NotSupportedException('PHP extension GD is not loaded.');
		}

		if (func_num_args() > 1) {
			$tmp = @getimagesizefromstring($s)[2]; // @ - strings smaller than 12 bytes causes read error
			$format = isset(self::$formats[$tmp]) ? $tmp : null;
		}

		return new static(\PHPStanVendor\Nette\Utils\Callback::invokeSafe('imagecreatefromstring', [$s], function ($message) {
			throw new \PHPStanVendor\Nette\Utils\ImageException($message);
		}));
	}


	/**
	 * Creates blank image.
	 * @param  int
	 * @param  int
	 * @param  array
	 * @return static
	 */
	public static function fromBlank($width, $height, $color = null)
	{
		if (!extension_loaded('gd')) {
			throw new \PHPStanVendor\Nette\NotSupportedException('PHP extension GD is not loaded.');
		}

		$width = (int) $width;
		$height = (int) $height;
		if ($width < 1 || $height < 1) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException('Image width and height must be greater than zero.');
		}

		$image = imagecreatetruecolor($width, $height);
		if (is_array($color)) {
			$color += ['alpha' => 0];
			$color = imagecolorresolvealpha($image, $color['red'], $color['green'], $color['blue'], $color['alpha']);
			imagealphablending($image, false);
			imagefilledrectangle($image, 0, 0, $width - 1, $height - 1, $color);
			imagealphablending($image, true);
		}
		return new static($image);
	}


	/**
	 * Wraps GD image.
	 * @param  resource
	 */
	public function __construct($image)
	{
		$this->setImageResource($image);
		imagesavealpha($image, true);
	}


	/**
	 * Returns image width.
	 * @return int
	 */
	public function getWidth()
	{
		return imagesx($this->image);
	}


	/**
	 * Returns image height.
	 * @return int
	 */
	public function getHeight()
	{
		return imagesy($this->image);
	}


	/**
	 * Sets image resource.
	 * @param  resource
	 * @return static
	 */
	protected function setImageResource($image)
	{
		if (!is_resource($image) || get_resource_type($image) !== 'gd') {
			throw new \PHPStanVendor\Nette\InvalidArgumentException('Image is not valid.');
		}
		$this->image = $image;
		return $this;
	}


	/**
	 * Returns image GD resource.
	 * @return resource
	 */
	public function getImageResource()
	{
		return $this->image;
	}


	/**
	 * Resizes image.
	 * @param  mixed  width in pixels or percent
	 * @param  mixed  height in pixels or percent
	 * @param  int    flags
	 * @return static
	 */
	public function resize($width, $height, $flags = self::FIT)
	{
		if ($flags & self::EXACT) {
			return $this->resize($width, $height, self::FILL)->crop('50%', '50%', $width, $height);
		}

		list($newWidth, $newHeight) = static::calculateSize($this->getWidth(), $this->getHeight(), $width, $height, $flags);

		if ($newWidth !== $this->getWidth() || $newHeight !== $this->getHeight()) { // resize
			$newImage = static::fromBlank($newWidth, $newHeight, self::RGB(0, 0, 0, 127))->getImageResource();
			imagecopyresampled(
				$newImage, $this->image,
				0, 0, 0, 0,
				$newWidth, $newHeight, $this->getWidth(), $this->getHeight()
			);
			$this->image = $newImage;
		}

		if ($width < 0 || $height < 0) {
			imageflip($this->image, $width < 0 ? ($height < 0 ? IMG_FLIP_BOTH : IMG_FLIP_HORIZONTAL) : IMG_FLIP_VERTICAL);
		}
		return $this;
	}


	/**
	 * Calculates dimensions of resized image.
	 * @param  mixed  source width
	 * @param  mixed  source height
	 * @param  mixed  width in pixels or percent
	 * @param  mixed  height in pixels or percent
	 * @param  int    flags
	 * @return array
	 */
	public static function calculateSize($srcWidth, $srcHeight, $newWidth, $newHeight, $flags = self::FIT)
	{
		if (is_string($newWidth) && substr($newWidth, -1) === '%') {
			$newWidth = (int) round($srcWidth / 100 * abs(substr($newWidth, 0, -1)));
			$percents = true;
		} else {
			$newWidth = (int) abs($newWidth);
		}

		if (is_string($newHeight) && substr($newHeight, -1) === '%') {
			$newHeight = (int) round($srcHeight / 100 * abs(substr($newHeight, 0, -1)));
			$flags |= empty($percents) ? 0 : self::STRETCH;
		} else {
			$newHeight = (int) abs($newHeight);
		}

		if ($flags & self::STRETCH) { // non-proportional
			if (empty($newWidth) || empty($newHeight)) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException('For stretching must be both width and height specified.');
			}

			if ($flags & self::SHRINK_ONLY) {
				$newWidth = (int) round($srcWidth * min(1, $newWidth / $srcWidth));
				$newHeight = (int) round($srcHeight * min(1, $newHeight / $srcHeight));
			}

		} else {  // proportional
			if (empty($newWidth) && empty($newHeight)) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException('At least width or height must be specified.');
			}

			$scale = [];
			if ($newWidth > 0) { // fit width
				$scale[] = $newWidth / $srcWidth;
			}

			if ($newHeight > 0) { // fit height
				$scale[] = $newHeight / $srcHeight;
			}

			if ($flags & self::FILL) {
				$scale = [max($scale)];
			}

			if ($flags & self::SHRINK_ONLY) {
				$scale[] = 1;
			}

			$scale = min($scale);
			$newWidth = (int) round($srcWidth * $scale);
			$newHeight = (int) round($srcHeight * $scale);
		}

		return [max($newWidth, 1), max($newHeight, 1)];
	}


	/**
	 * Crops image.
	 * @param  mixed  x-offset in pixels or percent
	 * @param  mixed  y-offset in pixels or percent
	 * @param  mixed  width in pixels or percent
	 * @param  mixed  height in pixels or percent
	 * @return static
	 */
	public function crop($left, $top, $width, $height)
	{
		list($r['x'], $r['y'], $r['width'], $r['height'])
			= static::calculateCutout($this->getWidth(), $this->getHeight(), $left, $top, $width, $height);
		if (PHP_VERSION_ID > 50611) { // PHP bug #67447
			$this->image = imagecrop($this->image, $r);
		} else {
			$newImage = static::fromBlank($r['width'], $r['height'], self::RGB(0, 0, 0, 127))->getImageResource();
			imagecopy($newImage, $this->image, 0, 0, $r['x'], $r['y'], $r['width'], $r['height']);
			$this->image = $newImage;
		}
		return $this;
	}


	/**
	 * Calculates dimensions of cutout in image.
	 * @param  mixed  source width
	 * @param  mixed  source height
	 * @param  mixed  x-offset in pixels or percent
	 * @param  mixed  y-offset in pixels or percent
	 * @param  mixed  width in pixels or percent
	 * @param  mixed  height in pixels or percent
	 * @return array
	 */
	public static function calculateCutout($srcWidth, $srcHeight, $left, $top, $newWidth, $newHeight)
	{
		if (is_string($newWidth) && substr($newWidth, -1) === '%') {
			$newWidth = (int) round($srcWidth / 100 * substr($newWidth, 0, -1));
		}
		if (is_string($newHeight) && substr($newHeight, -1) === '%') {
			$newHeight = (int) round($srcHeight / 100 * substr($newHeight, 0, -1));
		}
		if (is_string($left) && substr($left, -1) === '%') {
			$left = (int) round(($srcWidth - $newWidth) / 100 * substr($left, 0, -1));
		}
		if (is_string($top) && substr($top, -1) === '%') {
			$top = (int) round(($srcHeight - $newHeight) / 100 * substr($top, 0, -1));
		}
		if ($left < 0) {
			$newWidth += $left;
			$left = 0;
		}
		if ($top < 0) {
			$newHeight += $top;
			$top = 0;
		}
		$newWidth = min($newWidth, $srcWidth - $left);
		$newHeight = min($newHeight, $srcHeight - $top);
		return [$left, $top, $newWidth, $newHeight];
	}


	/**
	 * Sharpen image.
	 * @return static
	 */
	public function sharpen()
	{
		imageconvolution($this->image, [ // my magic numbers ;)
			[-1, -1, -1],
			[-1, 24, -1],
			[-1, -1, -1],
		], 16, 0);
		return $this;
	}


	/**
	 * Puts another image into this image.
	 * @param  Image
	 * @param  mixed  x-coordinate in pixels or percent
	 * @param  mixed  y-coordinate in pixels or percent
	 * @param  int  opacity 0..100
	 * @return static
	 */
	public function place(\PHPStanVendor\Nette\Utils\Image $image, $left = 0, $top = 0, $opacity = 100)
	{
		$opacity = max(0, min(100, (int) $opacity));
		if ($opacity === 0) {
			return $this;
		}

		$width = $image->getWidth();
		$height = $image->getHeight();

		if (is_string($left) && substr($left, -1) === '%') {
			$left = (int) round(($this->getWidth() - $width) / 100 * substr($left, 0, -1));
		}

		if (is_string($top) && substr($top, -1) === '%') {
			$top = (int) round(($this->getHeight() - $height) / 100 * substr($top, 0, -1));
		}

		$output = $input = $image->image;
		if ($opacity < 100) {
			for ($i = 0; $i < 128; $i++) {
				$tbl[$i] = round(127 - (127 - $i) * $opacity / 100);
			}

			$output = imagecreatetruecolor($width, $height);
			imagealphablending($output, false);
			if (!$image->isTrueColor()) {
				$input = $output;
				imagefilledrectangle($output, 0, 0, $width, $height, imagecolorallocatealpha($output, 0, 0, 0, 127));
				imagecopy($output, $image->image, 0, 0, 0, 0, $width, $height);
			}
			for ($x = 0; $x < $width; $x++) {
				for ($y = 0; $y < $height; $y++) {
					$c = \imagecolorat($input, $x, $y);
					$c = ($c & 0xFFFFFF) + ($tbl[$c >> 24] << 24);
					\imagesetpixel($output, $x, $y, $c);
				}
			}
			imagealphablending($output, true);
		}

		imagecopy(
			$this->image, $output,
			$left, $top, 0, 0, $width, $height
		);
		return $this;
	}


	/**
	 * Saves image to the file.
	 * @param  string  filename
	 * @param  int  quality (0..100 for JPEG and WEBP, 0..9 for PNG)
	 * @param  int  optional image type
	 * @return bool true on success or false on failure.
	 */
	public function save($file = null, $quality = null, $type = null)
	{
		if ($type === null) {
			$extensions = array_flip(self::$formats) + ['jpg' => self::JPEG];
			$ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
			if (!isset($extensions[$ext])) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException("Unsupported file extension '$ext'.");
			}
			$type = $extensions[$ext];
		}

		switch ($type) {
			case self::JPEG:
				$quality = $quality === null ? 85 : max(0, min(100, (int) $quality));
				return imagejpeg($this->image, $file, $quality);

			case self::PNG:
				$quality = $quality === null ? 9 : max(0, min(9, (int) $quality));
				return imagepng($this->image, $file, $quality);

			case self::GIF:
				return imagegif($this->image, $file);

			case self::WEBP:
				$quality = $quality === null ? 80 : max(0, min(100, (int) $quality));
				return imagewebp($this->image, $file, $quality);

			default:
				throw new \PHPStanVendor\Nette\InvalidArgumentException("Unsupported image type '$type'.");
		}
	}


	/**
	 * Outputs image to string.
	 * @param  int  image type
	 * @param  int  quality (0..100 for JPEG and WEBP, 0..9 for PNG)
	 * @return string
	 */
	public function toString($type = self::JPEG, $quality = null)
	{
		ob_start(function () {});
		$this->save(null, $quality, $type);
		return ob_get_clean();
	}


	/**
	 * Outputs image to string.
	 * @return string
	 */
	public function __toString()
	{
		try {
			return $this->toString();
		} catch (\Exception $e) {
		} catch (\Throwable $e) {
		}
		if (isset($e)) {
			if (func_num_args()) {
				throw $e;
			}
			trigger_error('Exception in ' . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR);
		}
	}


	/**
	 * Outputs image to browser.
	 * @param  int  image type
	 * @param  int  quality (0..100 for JPEG and WEBP, 0..9 for PNG)
	 * @return bool true on success or false on failure.
	 */
	public function send($type = self::JPEG, $quality = null)
	{
		if (!isset(self::$formats[$type])) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException("Unsupported image type '$type'.");
		}
		header('Content-Type: image/' . self::$formats[$type]);
		return $this->save(null, $quality, $type);
	}


	/**
	 * Call to undefined method.
	 *
	 * @param  string  method name
	 * @param  array   arguments
	 * @return mixed
	 * @throws Nette\MemberAccessException
	 */
	public function __call($name, $args)
	{
		$function = 'image' . $name;
		if (!function_exists($function)) {
			\PHPStanVendor\Nette\Utils\ObjectMixin::strictCall(get_class($this), $name);
		}

		foreach ($args as $key => $value) {
			if ($value instanceof self) {
				$args[$key] = $value->getImageResource();

			} elseif (is_array($value) && isset($value['red'])) { // rgb
				$args[$key] = imagecolorallocatealpha(
					$this->image,
					$value['red'], $value['green'], $value['blue'], $value['alpha']
				) ?: imagecolorresolvealpha(
					$this->image,
					$value['red'], $value['green'], $value['blue'], $value['alpha']
				);
			}
		}
		$res = $function($this->image, ...$args);
		return is_resource($res) && get_resource_type($res) === 'gd' ? $this->setImageResource($res) : $res;
	}


	public function __clone()
	{
		ob_start(function () {});
		imagegd2($this->image);
		$this->setImageResource(imagecreatefromstring(ob_get_clean()));
	}


	/**
	 * Prevents serialization.
	 */
	public function __sleep()
	{
		throw new \PHPStanVendor\Nette\NotSupportedException('You cannot serialize or unserialize ' . self::class . ' instances.');
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Utils;


/**
 * JSON encoder and decoder.
 */
class Json
{
	use \PHPStanVendor\Nette\StaticClass;

	const FORCE_ARRAY = 0b0001;
	const PRETTY = 0b0010;


	/**
	 * Returns the JSON representation of a value.
	 * @param  mixed
	 * @param  int  accepts Json::PRETTY
	 * @return string
	 */
	public static function encode($value, $options = 0)
	{
		$flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
			| ($options & self::PRETTY ? JSON_PRETTY_PRINT : 0)
			| (defined('JSON_PRESERVE_ZERO_FRACTION') ? JSON_PRESERVE_ZERO_FRACTION : 0); // since PHP 5.6.6 & PECL JSON-C 1.3.7

		$json = json_encode($value, $flags);
		if ($error = json_last_error()) {
			throw new \PHPStanVendor\Nette\Utils\JsonException(json_last_error_msg(), $error);
		}

		if (PHP_VERSION_ID < 70100) {
			$json = str_replace(["\xe2\x80\xa8", "\xe2\x80\xa9"], ['\u2028', '\u2029'], $json);
		}

		return $json;
	}


	/**
	 * Decodes a JSON string.
	 * @param  string
	 * @param  int  accepts Json::FORCE_ARRAY
	 * @return mixed
	 */
	public static function decode($json, $options = 0)
	{
		$forceArray = (bool) ($options & self::FORCE_ARRAY);
		$flags = JSON_BIGINT_AS_STRING;

		if (PHP_VERSION_ID < 70000) {
			$json = (string) $json;
			if ($json === '') {
				throw new \PHPStanVendor\Nette\Utils\JsonException('Syntax error');
			} elseif (!$forceArray && preg_match('#(?<=[^\\\\]")\\\\u0000(?:[^"\\\\]|\\\\.)*+"\s*+:#', $json)) {
				throw new \PHPStanVendor\Nette\Utils\JsonException('The decoded property name is invalid'); // fatal error when object key starts with \u0000
			} elseif (defined('JSON_C_VERSION') && !preg_match('##u', $json)) {
				throw new \PHPStanVendor\Nette\Utils\JsonException('Invalid UTF-8 sequence', 5);
			} elseif (defined('JSON_C_VERSION') && PHP_INT_SIZE === 8) {
				$flags &= ~JSON_BIGINT_AS_STRING; // not implemented in PECL JSON-C 1.3.2 for 64bit systems
			}
		}

		$value = json_decode($json, $forceArray, 512, $flags);
		if ($error = json_last_error()) {
			throw new \PHPStanVendor\Nette\Utils\JsonException(json_last_error_msg(), $error);
		}

		return $value;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette;


/**
 * Nette\Object is the ultimate ancestor of all instantiable classes.
 *
 * It defines some handful methods and enhances object core of PHP:
 *   - access to undeclared members throws exceptions
 *   - support for conventional properties with getters and setters
 *   - support for event raising functionality
 *   - ability to add new methods to class (extension methods)
 *
 * Properties is a syntactic sugar which allows access public getter and setter
 * methods as normal object variables. A property is defined by a getter method
 * or setter method (no setter method means read-only property).
 * <code>
 * $val = $obj->label;     // equivalent to $val = $obj->getLabel();
 * $obj->label = 'Nette';  // equivalent to $obj->setLabel('Nette');
 * </code>
 * Property names are case-sensitive, and they are written in the camelCaps
 * or PascalCaps.
 *
 * Event functionality is provided by declaration of property named 'on{Something}'
 * Multiple handlers are allowed.
 * <code>
 * public $onClick;                // declaration in class
 * $this->onClick[] = 'callback';  // attaching event handler
 * if (!empty($this->onClick)) ... // are there any handlers?
 * $this->onClick($sender, $arg);  // raises the event with arguments
 * </code>
 *
 * Adding method to class (i.e. to all instances) works similar to JavaScript
 * prototype property. The syntax for adding a new method is:
 * <code>
 * MyClass::extensionMethod('newMethod', function (MyClass $obj, $arg, ...) { ... });
 * $obj = new MyClass;
 * $obj->newMethod($x);
 * </code>
 *
 * @property-read Nette\Reflection\ClassType|\ReflectionClass $reflection
 */
abstract class Object
{

	/**
	 * Access to reflection.
	 * @return Nette\Reflection\ClassType|\ReflectionClass
	 */
	public static function getReflection()
	{
		$class = class_exists(\PHPStanVendor\Nette\Reflection\ClassType::class) ? \PHPStanVendor\Nette\Reflection\ClassType::class : 'ReflectionClass';
		return new $class(get_called_class());
	}


	/**
	 * Call to undefined method.
	 * @param  string  method name
	 * @param  array   arguments
	 * @return mixed
	 * @throws MemberAccessException
	 */
	public function __call($name, $args)
	{
		return \PHPStanVendor\Nette\Utils\ObjectMixin::call($this, $name, $args);
	}


	/**
	 * Call to undefined static method.
	 * @param  string  method name (in lower case!)
	 * @param  array   arguments
	 * @return mixed
	 * @throws MemberAccessException
	 */
	public static function __callStatic($name, $args)
	{
		return \PHPStanVendor\Nette\Utils\ObjectMixin::callStatic(get_called_class(), $name, $args);
	}


	/**
	 * Adding method to class.
	 * @param  string  method name
	 * @param  callable
	 * @return mixed
	 */
	public static function extensionMethod($name, $callback = null)
	{
		if (strpos($name, '::') === false) {
			$class = get_called_class();
		} else {
			list($class, $name) = explode('::', $name);
			$class = (new \ReflectionClass($class))->getName();
		}
		if ($callback === null) {
			return \PHPStanVendor\Nette\Utils\ObjectMixin::getExtensionMethod($class, $name);
		} else {
			\PHPStanVendor\Nette\Utils\ObjectMixin::setExtensionMethod($class, $name, $callback);
		}
	}


	/**
	 * Returns property value. Do not call directly.
	 * @param  string  property name
	 * @return mixed   property value
	 * @throws MemberAccessException if the property is not defined.
	 */
	public function &__get($name)
	{
		return \PHPStanVendor\Nette\Utils\ObjectMixin::get($this, $name);
	}


	/**
	 * Sets value of a property. Do not call directly.
	 * @param  string  property name
	 * @param  mixed   property value
	 * @return void
	 * @throws MemberAccessException if the property is not defined or is read-only
	 */
	public function __set($name, $value)
	{
		\PHPStanVendor\Nette\Utils\ObjectMixin::set($this, $name, $value);
	}


	/**
	 * Is property defined?
	 * @param  string  property name
	 * @return bool
	 */
	public function __isset($name)
	{
		return \PHPStanVendor\Nette\Utils\ObjectMixin::has($this, $name);
	}


	/**
	 * Access to undeclared property.
	 * @param  string  property name
	 * @return void
	 * @throws MemberAccessException
	 */
	public function __unset($name)
	{
		\PHPStanVendor\Nette\Utils\ObjectMixin::remove($this, $name);
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Utils;


/**
 * Nette\Object behaviour mixin.
 */
class ObjectMixin
{
	use \PHPStanVendor\Nette\StaticClass;

	/** @var array [name => [type => callback]] used by extension methods */
	private static $extMethods = [];


	/********************* strictness ****************d*g**/


	/**
	 * @throws MemberAccessException
	 */
	public static function strictGet($class, $name)
	{
		$rc = new \ReflectionClass($class);
		$hint = self::getSuggestion(array_merge(
			array_filter($rc->getProperties(\ReflectionProperty::IS_PUBLIC), function ($p) { return !$p->isStatic(); }),
			self::parseFullDoc($rc, '~^[ \t*]*@property(?:-read)?[ \t]+(?:\S+[ \t]+)??\$(\w+)~m')
		), $name);
		throw new \PHPStanVendor\Nette\MemberAccessException("Cannot read an undeclared property $class::\$$name" . ($hint ? ", did you mean \$$hint?" : '.'));
	}


	/**
	 * @throws MemberAccessException
	 */
	public static function strictSet($class, $name)
	{
		$rc = new \ReflectionClass($class);
		$hint = self::getSuggestion(array_merge(
			array_filter($rc->getProperties(\ReflectionProperty::IS_PUBLIC), function ($p) { return !$p->isStatic(); }),
			self::parseFullDoc($rc, '~^[ \t*]*@property(?:-write)?[ \t]+(?:\S+[ \t]+)??\$(\w+)~m')
		), $name);
		throw new \PHPStanVendor\Nette\MemberAccessException("Cannot write to an undeclared property $class::\$$name" . ($hint ? ", did you mean \$$hint?" : '.'));
	}


	/**
	 * @throws MemberAccessException
	 */
	public static function strictCall($class, $method, $additionalMethods = [])
	{
		$hint = self::getSuggestion(array_merge(
			get_class_methods($class),
			self::parseFullDoc(new \ReflectionClass($class), '~^[ \t*]*@method[ \t]+(?:\S+[ \t]+)??(\w+)\(~m'),
			$additionalMethods
		), $method);

		if (method_exists($class, $method)) { // called parent::$method()
			$class = 'parent';
		}
		throw new \PHPStanVendor\Nette\MemberAccessException("Call to undefined method $class::$method()" . ($hint ? ", did you mean $hint()?" : '.'));
	}


	/**
	 * @throws MemberAccessException
	 */
	public static function strictStaticCall($class, $method)
	{
		$hint = self::getSuggestion(
			array_filter((new \ReflectionClass($class))->getMethods(\ReflectionMethod::IS_PUBLIC), function ($m) { return $m->isStatic(); }),
			$method
		);
		throw new \PHPStanVendor\Nette\MemberAccessException("Call to undefined static method $class::$method()" . ($hint ? ", did you mean $hint()?" : '.'));
	}


	/********************* Nette\Object ****************d*g**/


	/**
	 * __call() implementation.
	 * @param  object
	 * @param  string
	 * @param  array
	 * @return mixed
	 * @throws MemberAccessException
	 */
	public static function call($_this, $name, $args)
	{
		$class = get_class($_this);
		$isProp = self::hasProperty($class, $name);

		if ($name === '') {
			throw new \PHPStanVendor\Nette\MemberAccessException("Call to class '$class' method without name.");

		} elseif ($isProp === 'event') { // calling event handlers
			if (is_array($_this->$name) || $_this->$name instanceof \Traversable) {
				foreach ($_this->$name as $handler) {
					\PHPStanVendor\Nette\Utils\Callback::invokeArgs($handler, $args);
				}
			} elseif ($_this->$name !== null) {
				throw new \PHPStanVendor\Nette\UnexpectedValueException("Property $class::$$name must be array or null, " . gettype($_this->$name) . ' given.');
			}

		} elseif ($isProp && $_this->$name instanceof \Closure) { // closure in property
			return call_user_func_array($_this->$name, $args);

		} elseif (($methods = &self::getMethods($class)) && isset($methods[$name]) && is_array($methods[$name])) { // magic @methods
			list($op, $rp, $type) = $methods[$name];
			if (count($args) !== ($op === 'get' ? 0 : 1)) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException("$class::$name() expects " . ($op === 'get' ? 'no' : '1') . ' argument, ' . count($args) . ' given.');

			} elseif ($type && $args && !self::checkType($args[0], $type)) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException("Argument passed to $class::$name() must be $type, " . gettype($args[0]) . ' given.');
			}

			if ($op === 'get') {
				return $rp->getValue($_this);
			} elseif ($op === 'set') {
				$rp->setValue($_this, $args[0]);
			} elseif ($op === 'add') {
				$val = $rp->getValue($_this);
				$val[] = $args[0];
				$rp->setValue($_this, $val);
			}
			return $_this;

		} elseif ($cb = self::getExtensionMethod($class, $name)) { // extension methods
			return \PHPStanVendor\Nette\Utils\Callback::invoke($cb, $_this, ...$args);

		} else {
			self::strictCall($class, $name, array_keys(self::getExtensionMethods($class)));
		}
	}


	/**
	 * __callStatic() implementation.
	 * @param  string
	 * @param  string
	 * @param  array
	 * @return void
	 * @throws MemberAccessException
	 */
	public static function callStatic($class, $method, $args)
	{
		self::strictStaticCall($class, $method);
	}


	/**
	 * __get() implementation.
	 * @param  object
	 * @param  string  property name
	 * @return mixed   property value
	 * @throws MemberAccessException if the property is not defined.
	 */
	public static function &get($_this, $name)
	{
		$class = get_class($_this);
		$uname = ucfirst($name);
		$methods = &self::getMethods($class);

		if ($name === '') {
			throw new \PHPStanVendor\Nette\MemberAccessException("Cannot read a class '$class' property without name.");

		} elseif (isset($methods[$m = 'get' . $uname]) || isset($methods[$m = 'is' . $uname])) { // property getter
			if ($methods[$m] === 0) {
				$methods[$m] = (new \ReflectionMethod($class, $m))->returnsReference();
			}
			if ($methods[$m] === true) {
				return $_this->$m();
			} else {
				$val = $_this->$m();
				return $val;
			}

		} elseif (isset($methods[$name])) { // public method as closure getter
			if (preg_match('#^(is|get|has)([A-Z]|$)#', $name) && !(new \ReflectionMethod($class, $name))->getNumberOfRequiredParameters()) {
				trigger_error("Did you forget parentheses after $name" . self::getSource() . '?', E_USER_WARNING);
			}
			$val = \PHPStanVendor\Nette\Utils\Callback::closure($_this, $name);
			return $val;

		} elseif (isset($methods['set' . $uname])) { // property getter
			throw new \PHPStanVendor\Nette\MemberAccessException("Cannot read a write-only property $class::\$$name.");

		} else {
			self::strictGet($class, $name);
		}
	}


	/**
	 * __set() implementation.
	 * @param  object
	 * @param  string  property name
	 * @param  mixed   property value
	 * @return void
	 * @throws MemberAccessException if the property is not defined or is read-only
	 */
	public static function set($_this, $name, $value)
	{
		$class = get_class($_this);
		$uname = ucfirst($name);
		$methods = &self::getMethods($class);

		if ($name === '') {
			throw new \PHPStanVendor\Nette\MemberAccessException("Cannot write to a class '$class' property without name.");

		} elseif (self::hasProperty($class, $name)) { // unsetted property
			$_this->$name = $value;

		} elseif (isset($methods[$m = 'set' . $uname])) { // property setter
			$_this->$m($value);

		} elseif (isset($methods['get' . $uname]) || isset($methods['is' . $uname])) { // property setter
			throw new \PHPStanVendor\Nette\MemberAccessException("Cannot write to a read-only property $class::\$$name.");

		} else {
			self::strictSet($class, $name);
		}
	}


	/**
	 * __unset() implementation.
	 * @param  object
	 * @param  string  property name
	 * @return void
	 * @throws MemberAccessException
	 */
	public static function remove($_this, $name)
	{
		$class = get_class($_this);
		if (!self::hasProperty($class, $name)) {
			throw new \PHPStanVendor\Nette\MemberAccessException("Cannot unset the property $class::\$$name.");
		}
	}


	/**
	 * __isset() implementation.
	 * @param  object
	 * @param  string  property name
	 * @return bool
	 */
	public static function has($_this, $name)
	{
		$name = ucfirst($name);
		$methods = &self::getMethods(get_class($_this));
		return $name !== '' && (isset($methods['get' . $name]) || isset($methods['is' . $name]));
	}


	/********************* magic @properties ****************d*g**/


	/**
	 * Returns array of magic properties defined by annotation @property.
	 * @return array of [name => bit mask]
	 */
	public static function getMagicProperties($class)
	{
		static $cache;
		$props = &$cache[$class];
		if ($props !== null) {
			return $props;
		}

		$rc = new \ReflectionClass($class);
		preg_match_all(
			'~^  [ \t*]*  @property(|-read|-write)  [ \t]+  [^\s$]+  [ \t]+  \$  (\w+)  ()~mx',
			(string) $rc->getDocComment(), $matches, PREG_SET_ORDER
		);

		$props = [];
		foreach ($matches as list(, $type, $name)) {
			$uname = ucfirst($name);
			$write = $type !== '-read'
				&& $rc->hasMethod($nm = 'set' . $uname)
				&& ($rm = $rc->getMethod($nm)) && $rm->getName() === $nm && !$rm->isPrivate() && !$rm->isStatic();
			$read = $type !== '-write'
				&& ($rc->hasMethod($nm = 'get' . $uname) || $rc->hasMethod($nm = 'is' . $uname))
				&& ($rm = $rc->getMethod($nm)) && $rm->getName() === $nm && !$rm->isPrivate() && !$rm->isStatic();

			if ($read || $write) {
				$props[$name] = $read << 0 | ($nm[0] === 'g') << 1 | $rm->returnsReference() << 2 | $write << 3;
			}
		}

		foreach ($rc->getTraits() as $trait) {
			$props += self::getMagicProperties($trait->getName());
		}

		if ($parent = get_parent_class($class)) {
			$props += self::getMagicProperties($parent);
		}
		return $props;
	}


	/** @internal */
	public static function getMagicProperty($class, $name)
	{
		$props = self::getMagicProperties($class);
		return isset($props[$name]) ? $props[$name] : null;
	}


	/********************* magic @methods ****************d*g**/


	/**
	 * Returns array of magic methods defined by annotation @method.
	 * @return array
	 */
	public static function getMagicMethods($class)
	{
		$rc = new \ReflectionClass($class);
		preg_match_all('~^
			[ \t*]*  @method  [ \t]+
			(?: [^\s(]+  [ \t]+ )?
			(set|get|is|add)  ([A-Z]\w*)
			(?: ([ \t]* \()  [ \t]* ([^)$\s]*)  )?
		()~mx', (string) $rc->getDocComment(), $matches, PREG_SET_ORDER);

		$methods = [];
		foreach ($matches as list(, $op, $prop, $bracket, $type)) {
			if ($bracket !== '(') {
				trigger_error("Bracket must be immediately after @method $op$prop() in class $class.", E_USER_WARNING);
			}
			$name = $op . $prop;
			$prop = strtolower($prop[0]) . substr($prop, 1) . ($op === 'add' ? 's' : '');
			if ($rc->hasProperty($prop) && ($rp = $rc->getProperty($prop)) && !$rp->isStatic()) {
				$rp->setAccessible(true);
				if ($op === 'get' || $op === 'is') {
					$type = null;
					$op = 'get';
				} elseif (!$type && preg_match('#@var[ \t]+(\S+)' . ($op === 'add' ? '\[\]#' : '#'), (string) $rp->getDocComment(), $m)) {
					$type = $m[1];
				}
				if ($rc->inNamespace() && preg_match('#^[A-Z]\w+(\[|\||\z)#', (string) $type)) {
					$type = $rc->getNamespaceName() . '\\' . $type;
				}
				$methods[$name] = [$op, $rp, $type];
			}
		}
		return $methods;
	}


	/**
	 * Finds whether a variable is of expected type and do non-data-loss conversion.
	 * @return bool
	 * @internal
	 */
	public static function checkType(&$val, $type)
	{
		if (strpos($type, '|') !== false) {
			$found = null;
			foreach (explode('|', $type) as $type) {
				$tmp = $val;
				if (self::checkType($tmp, $type)) {
					if ($val === $tmp) {
						return true;
					}
					$found[] = $tmp;
				}
			}
			if ($found) {
				$val = $found[0];
				return true;
			}
			return false;

		} elseif (substr($type, -2) === '[]') {
			if (!is_array($val)) {
				return false;
			}
			$type = substr($type, 0, -2);
			$res = [];
			foreach ($val as $k => $v) {
				if (!self::checkType($v, $type)) {
					return false;
				}
				$res[$k] = $v;
			}
			$val = $res;
			return true;
		}

		switch (strtolower($type)) {
			case null:
			case 'mixed':
				return true;
			case 'bool':
			case 'boolean':
				return ($val === null || is_scalar($val)) && settype($val, 'bool');
			case 'string':
				return ($val === null || is_scalar($val) || (is_object($val) && method_exists($val, '__toString'))) && settype($val, 'string');
			case 'int':
			case 'integer':
				return ($val === null || is_bool($val) || is_numeric($val)) && ((float) (int) $val === (float) $val) && settype($val, 'int');
			case 'float':
				return ($val === null || is_bool($val) || is_numeric($val)) && settype($val, 'float');
			case 'scalar':
			case 'array':
			case 'object':
			case 'callable':
			case 'resource':
			case 'null':
				return call_user_func("is_$type", $val);
			default:
				return $val instanceof $type;
		}
	}


	/********************* extension methods ****************d*g**/


	/**
	 * Adds a method to class.
	 * @param  string
	 * @param  string
	 * @param  mixed   callable
	 * @return void
	 */
	public static function setExtensionMethod($class, $name, $callback)
	{
		$name = strtolower($name);
		self::$extMethods[$name][$class] = \PHPStanVendor\Nette\Utils\Callback::check($callback);
		self::$extMethods[$name][''] = null;
	}


	/**
	 * Returns extension method.
	 * @param  string
	 * @param  string
	 * @return mixed
	 */
	public static function getExtensionMethod($class, $name)
	{
		$list = &self::$extMethods[strtolower($name)];
		$cache = &$list[''][$class];
		if (isset($cache)) {
			return $cache;
		}

		foreach ([$class] + class_parents($class) + class_implements($class) as $cl) {
			if (isset($list[$cl])) {
				return $cache = $list[$cl];
			}
		}
		return $cache = false;
	}


	/**
	 * Returns extension methods.
	 * @param  string
	 * @return array
	 */
	public static function getExtensionMethods($class)
	{
		$res = [];
		foreach (array_keys(self::$extMethods) as $name) {
			if ($cb = self::getExtensionMethod($class, $name)) {
				$res[$name] = $cb;
			}
		}
		return $res;
	}


	/********************* utilities ****************d*g**/


	/**
	 * Finds the best suggestion (for 8-bit encoding).
	 * @return string|null
	 * @internal
	 */
	public static function getSuggestion(array $possibilities, $value)
	{
		$norm = preg_replace($re = '#^(get|set|has|is|add)(?=[A-Z])#', '', $value);
		$best = null;
		$min = (strlen($value) / 4 + 1) * 10 + .1;
		foreach (array_unique($possibilities, SORT_REGULAR) as $item) {
			$item = $item instanceof \Reflector ? $item->getName() : $item;
			if ($item !== $value && (
				($len = levenshtein($item, $value, 10, 11, 10)) < $min
				|| ($len = levenshtein(preg_replace($re, '', $item), $norm, 10, 11, 10) + 20) < $min
			)) {
				$min = $len;
				$best = $item;
			}
		}
		return $best;
	}


	private static function parseFullDoc(\ReflectionClass $rc, $pattern)
	{
		do {
			$doc[] = $rc->getDocComment();
			$traits = $rc->getTraits();
			while ($trait = array_pop($traits)) {
				$doc[] = $trait->getDocComment();
				$traits += $trait->getTraits();
			}
		} while ($rc = $rc->getParentClass());
		return preg_match_all($pattern, implode($doc), $m) ? $m[1] : [];
	}


	/**
	 * Checks if the public non-static property exists.
	 * @return bool|'event'
	 * @internal
	 */
	public static function hasProperty($class, $name)
	{
		static $cache;
		$prop = &$cache[$class][$name];
		if ($prop === null) {
			$prop = false;
			try {
				$rp = new \ReflectionProperty($class, $name);
				if ($rp->isPublic() && !$rp->isStatic()) {
					$prop = $name >= 'onA' && $name < 'on_' ? 'event' : true;
				}
			} catch (\ReflectionException $e) {
			}
		}
		return $prop;
	}


	/**
	 * Returns array of public (static, non-static and magic) methods.
	 * @return array
	 * @internal
	 */
	public static function &getMethods($class)
	{
		static $cache;
		if (!isset($cache[$class])) {
			$cache[$class] = array_fill_keys(get_class_methods($class), 0) + self::getMagicMethods($class);
			if ($parent = get_parent_class($class)) {
				$cache[$class] += self::getMethods($parent);
			}
		}
		return $cache[$class];
	}


	/** @internal */
	public static function getSource()
	{
		foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $item) {
			if (isset($item['file']) && dirname($item['file']) !== __DIR__) {
				return " in $item[file]:$item[line]";
			}
		}
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Utils;


/**
 * Paginating math.
 *
 * @property   int $page
 * @property-read int $firstPage
 * @property-read int|null $lastPage
 * @property   int $base
 * @property-read bool $first
 * @property-read bool $last
 * @property-read int|null $pageCount
 * @property   int $itemsPerPage
 * @property   int|null $itemCount
 * @property-read int $offset
 * @property-read int|null $countdownOffset
 * @property-read int|null $length
 */
class Paginator
{
	use \PHPStanVendor\Nette\SmartObject;

	/** @var int */
	private $base = 1;

	/** @var int */
	private $itemsPerPage = 1;

	/** @var int */
	private $page;

	/** @var int|null */
	private $itemCount;


	/**
	 * Sets current page number.
	 * @param  int
	 * @return static
	 */
	public function setPage($page)
	{
		$this->page = (int) $page;
		return $this;
	}


	/**
	 * Returns current page number.
	 * @return int
	 */
	public function getPage()
	{
		return $this->base + $this->getPageIndex();
	}


	/**
	 * Returns first page number.
	 * @return int
	 */
	public function getFirstPage()
	{
		return $this->base;
	}


	/**
	 * Returns last page number.
	 * @return int|null
	 */
	public function getLastPage()
	{
		return $this->itemCount === null ? null : $this->base + max(0, $this->getPageCount() - 1);
	}


	/**
	 * Sets first page (base) number.
	 * @param  int
	 * @return static
	 */
	public function setBase($base)
	{
		$this->base = (int) $base;
		return $this;
	}


	/**
	 * Returns first page (base) number.
	 * @return int
	 */
	public function getBase()
	{
		return $this->base;
	}


	/**
	 * Returns zero-based page number.
	 * @return int
	 */
	protected function getPageIndex()
	{
		$index = max(0, $this->page - $this->base);
		return $this->itemCount === null ? $index : min($index, max(0, $this->getPageCount() - 1));
	}


	/**
	 * Is the current page the first one?
	 * @return bool
	 */
	public function isFirst()
	{
		return $this->getPageIndex() === 0;
	}


	/**
	 * Is the current page the last one?
	 * @return bool
	 */
	public function isLast()
	{
		return $this->itemCount === null ? false : $this->getPageIndex() >= $this->getPageCount() - 1;
	}


	/**
	 * Returns the total number of pages.
	 * @return int|null
	 */
	public function getPageCount()
	{
		return $this->itemCount === null ? null : (int) ceil($this->itemCount / $this->itemsPerPage);
	}


	/**
	 * Sets the number of items to display on a single page.
	 * @param  int
	 * @return static
	 */
	public function setItemsPerPage($itemsPerPage)
	{
		$this->itemsPerPage = max(1, (int) $itemsPerPage);
		return $this;
	}


	/**
	 * Returns the number of items to display on a single page.
	 * @return int
	 */
	public function getItemsPerPage()
	{
		return $this->itemsPerPage;
	}


	/**
	 * Sets the total number of items.
	 * @param  int (or null as infinity)
	 * @return static
	 */
	public function setItemCount($itemCount)
	{
		$this->itemCount = ($itemCount === false || $itemCount === null) ? null : max(0, (int) $itemCount);
		return $this;
	}


	/**
	 * Returns the total number of items.
	 * @return int|null
	 */
	public function getItemCount()
	{
		return $this->itemCount;
	}


	/**
	 * Returns the absolute index of the first item on current page.
	 * @return int
	 */
	public function getOffset()
	{
		return $this->getPageIndex() * $this->itemsPerPage;
	}


	/**
	 * Returns the absolute index of the first item on current page in countdown paging.
	 * @return int|null
	 */
	public function getCountdownOffset()
	{
		return $this->itemCount === null
			? null
			: max(0, $this->itemCount - ($this->getPageIndex() + 1) * $this->itemsPerPage);
	}


	/**
	 * Returns the number of items on current page.
	 * @return int|null
	 */
	public function getLength()
	{
		return $this->itemCount === null
			? $this->itemsPerPage
			: min($this->itemsPerPage, $this->itemCount - $this->getPageIndex() * $this->itemsPerPage);
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Utils;


/**
 * Secure random string generator.
 */
class Random
{
	use \PHPStanVendor\Nette\StaticClass;

	/**
	 * Generate random string.
	 * @param  int
	 * @param  string
	 * @return string
	 */
	public static function generate($length = 10, $charlist = '0-9a-z')
	{
		$charlist = count_chars(preg_replace_callback('#.-.#', function (array $m) {
			return implode('', range($m[0][0], $m[0][2]));
		}, $charlist), 3);
		$chLen = strlen($charlist);

		if ($length < 1) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException('Length must be greater than zero.');
		} elseif ($chLen < 2) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException('Character list must contain as least two chars.');
		}

		$res = '';
		if (PHP_VERSION_ID >= 70000) {
			for ($i = 0; $i < $length; $i++) {
				$res .= $charlist[random_int(0, $chLen - 1)];
			}
			return $res;
		}

		$bytes = '';
		if (function_exists('openssl_random_pseudo_bytes')) {
			$bytes = (string) openssl_random_pseudo_bytes($length, $secure);
			if (!$secure) {
				$bytes = '';
			}
		}
		if (strlen($bytes) < $length && function_exists('mcrypt_create_iv')) {
			$bytes = (string) mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
		}
		if (strlen($bytes) < $length && !defined('PHP_WINDOWS_VERSION_BUILD') && is_readable('/dev/urandom')) {
			$bytes = (string) file_get_contents('/dev/urandom', false, null, -1, $length);
		}
		if (strlen($bytes) < $length) {
			$rand3 = md5(serialize($_SERVER), true);
			$charlist = str_shuffle($charlist);
			for ($i = 0; $i < $length; $i++) {
				if ($i % 5 === 0) {
					list($rand1, $rand2) = explode(' ', microtime());
					$rand1 += lcg_value();
				}
				$rand1 *= $chLen;
				$res .= $charlist[($rand1 + $rand2 + ord($rand3[$i % strlen($rand3)])) % $chLen];
				$rand1 -= (int) $rand1;
			}
			return $res;
		}

		for ($i = 0; $i < $length; $i++) {
			$res .= $charlist[($i + ord($bytes[$i])) % $chLen];
		}
		return $res;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Utils;


/**
 * PHP reflection helpers.
 */
class Reflection
{
	use \PHPStanVendor\Nette\StaticClass;

	private static $builtinTypes = [
		'string' => 1, 'int' => 1, 'float' => 1, 'bool' => 1, 'array' => 1, 'object' => 1,
		'callable' => 1, 'iterable' => 1, 'void' => 1,
	];


	/**
	 * @param  string
	 * @return bool
	 */
	public static function isBuiltinType($type)
	{
		return isset(self::$builtinTypes[strtolower($type)]);
	}


	/**
	 * @return string|null
	 */
	public static function getReturnType(\ReflectionFunctionAbstract $func)
	{
		return PHP_VERSION_ID >= 70000 && $func->hasReturnType()
			? self::normalizeType((string) $func->getReturnType(), $func)
			: null;
	}


	/**
	 * @return string|null
	 */
	public static function getParameterType(\ReflectionParameter $param)
	{
		if (PHP_VERSION_ID >= 70000) {
			return $param->hasType()
				? self::normalizeType((string) $param->getType(), $param)
				: null;
		} elseif ($param->isArray() || $param->isCallable()) {
			return $param->isArray() ? 'array' : 'callable';
		} else {
			try {
				return ($ref = $param->getClass()) ? $ref->getName() : null;
			} catch (\ReflectionException $e) {
				if (preg_match('#Class (.+) does not exist#', $e->getMessage(), $m)) {
					return $m[1];
				}
				throw $e;
			}
		}
	}


	private static function normalizeType($type, $reflection)
	{
		$lower = strtolower($type);
		if ($lower === 'self') {
			return $reflection->getDeclaringClass()->getName();
		} elseif ($lower === 'parent' && $reflection->getDeclaringClass()->getParentClass()) {
			return $reflection->getDeclaringClass()->getParentClass()->getName();
		} else {
			return $type;
		}
	}


	/**
	 * @return mixed
	 * @throws \ReflectionException when default value is not available or resolvable
	 */
	public static function getParameterDefaultValue(\ReflectionParameter $param)
	{
		if ($param->isDefaultValueConstant()) {
			$const = $orig = $param->getDefaultValueConstantName();
			$pair = explode('::', $const);
			if (isset($pair[1]) && strtolower($pair[0]) === 'self') {
				$const = $param->getDeclaringClass()->getName() . '::' . $pair[1];
			}
			if (!defined($const)) {
				$const = substr((string) strrchr($const, '\\'), 1);
				if (isset($pair[1]) || !defined($const)) {
					$name = self::toString($param);
					throw new \ReflectionException("Unable to resolve constant $orig used as default value of $name.");
				}
			}
			return constant($const);
		}
		return $param->getDefaultValue();
	}


	/**
	 * Returns declaring class or trait.
	 * @return \ReflectionClass
	 */
	public static function getPropertyDeclaringClass(\ReflectionProperty $prop)
	{
		foreach ($prop->getDeclaringClass()->getTraits() as $trait) {
			if ($trait->hasProperty($prop->getName())) {
				return self::getPropertyDeclaringClass($trait->getProperty($prop->getName()));
			}
		}
		return $prop->getDeclaringClass();
	}


	/**
	 * Are documentation comments available?
	 * @return bool
	 */
	public static function areCommentsAvailable()
	{
		static $res;
		return $res === null
			? $res = (bool) (new \ReflectionMethod(__METHOD__))->getDocComment()
			: $res;
	}


	/**
	 * @return string
	 */
	public static function toString(\Reflector $ref)
	{
		if ($ref instanceof \ReflectionClass) {
			return $ref->getName();
		} elseif ($ref instanceof \ReflectionMethod) {
			return $ref->getDeclaringClass()->getName() . '::' . $ref->getName();
		} elseif ($ref instanceof \ReflectionFunction) {
			return $ref->getName();
		} elseif ($ref instanceof \ReflectionProperty) {
			return self::getPropertyDeclaringClass($ref)->getName() . '::$' . $ref->getName();
		} elseif ($ref instanceof \ReflectionParameter) {
			return '$' . $ref->getName() . ' in ' . self::toString($ref->getDeclaringFunction()) . '()';
		} else {
			throw new \PHPStanVendor\Nette\InvalidArgumentException;
		}
	}


	/**
	 * Expands class name into full name.
	 * @param  string
	 * @return string  full name
	 * @throws Nette\InvalidArgumentException
	 */
	public static function expandClassName($name, \ReflectionClass $rc)
	{
		$lower = strtolower($name);
		if (empty($name)) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException('Class name must not be empty.');

		} elseif (isset(self::$builtinTypes[$lower])) {
			return $lower;

		} elseif ($lower === 'self') {
			return $rc->getName();

		} elseif ($name[0] === '\\') { // fully qualified name
			return ltrim($name, '\\');
		}

		$uses = self::getUseStatements($rc);
		$parts = explode('\\', $name, 2);
		if (isset($uses[$parts[0]])) {
			$parts[0] = $uses[$parts[0]];
			return implode('\\', $parts);

		} elseif ($rc->inNamespace()) {
			return $rc->getNamespaceName() . '\\' . $name;

		} else {
			return $name;
		}
	}


	/**
	 * @return array of [alias => class]
	 */
	public static function getUseStatements(\ReflectionClass $class)
	{
		static $cache = [];
		if (!isset($cache[$name = $class->getName()])) {
			if ($class->isInternal()) {
				$cache[$name] = [];
			} else {
				$code = file_get_contents($class->getFileName());
				$cache = self::parseUseStatements($code, $name) + $cache;
			}
		}
		return $cache[$name];
	}


	/**
	 * Parses PHP code.
	 * @param  string
	 * @return array of [class => [alias => class, ...]]
	 */
	private static function parseUseStatements($code, $forClass = null)
	{
		$tokens = token_get_all($code);
		$namespace = $class = $classLevel = $level = null;
		$res = $uses = [];

		while ($token = current($tokens)) {
			next($tokens);
			switch (is_array($token) ? $token[0] : $token) {
				case T_NAMESPACE:
					$namespace = ltrim(self::fetch($tokens, [T_STRING, T_NS_SEPARATOR]) . '\\', '\\');
					$uses = [];
					break;

				case T_CLASS:
				case T_INTERFACE:
				case T_TRAIT:
					if ($name = self::fetch($tokens, T_STRING)) {
						$class = $namespace . $name;
						$classLevel = $level + 1;
						$res[$class] = $uses;
						if ($class === $forClass) {
							return $res;
						}
					}
					break;

				case T_USE:
					while (!$class && ($name = self::fetch($tokens, [T_STRING, T_NS_SEPARATOR]))) {
						$name = ltrim($name, '\\');
						if (self::fetch($tokens, '{')) {
							while ($suffix = self::fetch($tokens, [T_STRING, T_NS_SEPARATOR])) {
								if (self::fetch($tokens, T_AS)) {
									$uses[self::fetch($tokens, T_STRING)] = $name . $suffix;
								} else {
									$tmp = explode('\\', $suffix);
									$uses[end($tmp)] = $name . $suffix;
								}
								if (!self::fetch($tokens, ',')) {
									break;
								}
							}

						} elseif (self::fetch($tokens, T_AS)) {
							$uses[self::fetch($tokens, T_STRING)] = $name;

						} else {
							$tmp = explode('\\', $name);
							$uses[end($tmp)] = $name;
						}
						if (!self::fetch($tokens, ',')) {
							break;
						}
					}
					break;

				case T_CURLY_OPEN:
				case T_DOLLAR_OPEN_CURLY_BRACES:
				case '{':
					$level++;
					break;

				case '}':
					if ($level === $classLevel) {
						$class = $classLevel = null;
					}
					$level--;
			}
		}

		return $res;
	}


	private static function fetch(&$tokens, $take)
	{
		$res = null;
		while ($token = current($tokens)) {
			list($token, $s) = is_array($token) ? $token : [$token, $token];
			if (in_array($token, (array) $take, true)) {
				$res .= $s;
			} elseif (!in_array($token, [T_DOC_COMMENT, T_WHITESPACE, T_COMMENT], true)) {
				break;
			}
			next($tokens);
		}
		return $res;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette;


/**
 * Strict class for better experience.
 * - 'did you mean' hints
 * - access to undeclared members throws exceptions
 * - support for @property annotations
 * - support for calling event handlers stored in $onEvent via onEvent()
 * - compatible with Nette\Object
 */
trait SmartObject
{

	/**
	 * @return mixed
	 * @throws MemberAccessException
	 */
	public function __call($name, $args)
	{
		$class = get_class($this);
		$isProp = \PHPStanVendor\Nette\Utils\ObjectMixin::hasProperty($class, $name);

		if ($name === '') {
			throw new \PHPStanVendor\Nette\MemberAccessException("Call to class '$class' method without name.");

		} elseif ($isProp === 'event') { // calling event handlers
			if (is_array($this->$name) || $this->$name instanceof \Traversable) {
				foreach ($this->$name as $handler) {
					\PHPStanVendor\Nette\Utils\Callback::invokeArgs($handler, $args);
				}
			} elseif ($this->$name !== null) {
				throw new \PHPStanVendor\Nette\UnexpectedValueException("Property $class::$$name must be array or null, " . gettype($this->$name) . ' given.');
			}

		} elseif ($isProp && $this->$name instanceof \Closure) { // closure in property
			trigger_error("Invoking closure in property via \$obj->$name() is deprecated" . \PHPStanVendor\Nette\Utils\ObjectMixin::getSource(), E_USER_DEPRECATED);
			return call_user_func_array($this->$name, $args);

		} elseif (($methods = &\PHPStanVendor\Nette\Utils\ObjectMixin::getMethods($class)) && isset($methods[$name]) && is_array($methods[$name])) { // magic @methods
			trigger_error("Magic methods such as $class::$name() are deprecated" . \PHPStanVendor\Nette\Utils\ObjectMixin::getSource(), E_USER_DEPRECATED);
			list($op, $rp, $type) = $methods[$name];
			if (count($args) !== ($op === 'get' ? 0 : 1)) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException("$class::$name() expects " . ($op === 'get' ? 'no' : '1') . ' argument, ' . count($args) . ' given.');

			} elseif ($type && $args && !\PHPStanVendor\Nette\Utils\ObjectMixin::checkType($args[0], $type)) {
				throw new \PHPStanVendor\Nette\InvalidArgumentException("Argument passed to $class::$name() must be $type, " . gettype($args[0]) . ' given.');
			}

			if ($op === 'get') {
				return $rp->getValue($this);
			} elseif ($op === 'set') {
				$rp->setValue($this, $args[0]);
			} elseif ($op === 'add') {
				$val = $rp->getValue($this);
				$val[] = $args[0];
				$rp->setValue($this, $val);
			}
			return $this;

		} elseif ($cb = \PHPStanVendor\Nette\Utils\ObjectMixin::getExtensionMethod($class, $name)) { // extension methods
			trigger_error("Extension methods such as $class::$name() are deprecated" . \PHPStanVendor\Nette\Utils\ObjectMixin::getSource(), E_USER_DEPRECATED);
			return \PHPStanVendor\Nette\Utils\Callback::invoke($cb, $this, ...$args);

		} else {
			\PHPStanVendor\Nette\Utils\ObjectMixin::strictCall($class, $name);
		}
	}


	/**
	 * @return void
	 * @throws MemberAccessException
	 */
	public static function __callStatic($name, $args)
	{
		\PHPStanVendor\Nette\Utils\ObjectMixin::strictStaticCall(get_called_class(), $name);
	}


	/**
	 * @return mixed   property value
	 * @throws MemberAccessException if the property is not defined.
	 */
	public function &__get($name)
	{
		$class = get_class($this);
		$uname = ucfirst($name);

		if ($prop = \PHPStanVendor\Nette\Utils\ObjectMixin::getMagicProperty($class, $name)) { // property getter
			if (!($prop & 0b0001)) {
				throw new \PHPStanVendor\Nette\MemberAccessException("Cannot read a write-only property $class::\$$name.");
			}
			$m = ($prop & 0b0010 ? 'get' : 'is') . $uname;
			if ($prop & 0b0100) { // return by reference
				return $this->$m();
			} else {
				$val = $this->$m();
				return $val;
			}

		} elseif ($name === '') {
			throw new \PHPStanVendor\Nette\MemberAccessException("Cannot read a class '$class' property without name.");

		} elseif (($methods = &\PHPStanVendor\Nette\Utils\ObjectMixin::getMethods($class)) && isset($methods[$m = 'get' . $uname]) || isset($methods[$m = 'is' . $uname])) { // old property getter
			trigger_error("Use $m() or add annotation @property for $class::\$$name" . \PHPStanVendor\Nette\Utils\ObjectMixin::getSource(), E_USER_DEPRECATED);
			if ($methods[$m] === 0) {
				$methods[$m] = (new \ReflectionMethod($class, $m))->returnsReference();
			}
			if ($methods[$m] === true) {
				return $this->$m();
			} else {
				$val = $this->$m();
				return $val;
			}

		} elseif (isset($methods[$name])) { // public method as closure getter
			trigger_error("Accessing methods as properties via \$obj->$name is deprecated" . \PHPStanVendor\Nette\Utils\ObjectMixin::getSource(), E_USER_DEPRECATED);
			$val = \PHPStanVendor\Nette\Utils\Callback::closure($this, $name);
			return $val;

		} elseif (isset($methods['set' . $uname])) { // property getter
			throw new \PHPStanVendor\Nette\MemberAccessException("Cannot read a write-only property $class::\$$name.");

		} else {
			\PHPStanVendor\Nette\Utils\ObjectMixin::strictGet($class, $name);
		}
	}


	/**
	 * @return void
	 * @throws MemberAccessException if the property is not defined or is read-only
	 */
	public function __set($name, $value)
	{
		$class = get_class($this);
		$uname = ucfirst($name);

		if (\PHPStanVendor\Nette\Utils\ObjectMixin::hasProperty($class, $name)) { // unsetted property
			$this->$name = $value;

		} elseif ($prop = \PHPStanVendor\Nette\Utils\ObjectMixin::getMagicProperty($class, $name)) { // property setter
			if (!($prop & 0b1000)) {
				throw new \PHPStanVendor\Nette\MemberAccessException("Cannot write to a read-only property $class::\$$name.");
			}
			$this->{'set' . $name}($value);

		} elseif ($name === '') {
			throw new \PHPStanVendor\Nette\MemberAccessException("Cannot write to a class '$class' property without name.");

		} elseif (($methods = &\PHPStanVendor\Nette\Utils\ObjectMixin::getMethods($class)) && isset($methods[$m = 'set' . $uname])) { // old property setter
			trigger_error("Use $m() or add annotation @property for $class::\$$name" . \PHPStanVendor\Nette\Utils\ObjectMixin::getSource(), E_USER_DEPRECATED);
			$this->$m($value);

		} elseif (isset($methods['get' . $uname]) || isset($methods['is' . $uname])) { // property setter
			throw new \PHPStanVendor\Nette\MemberAccessException("Cannot write to a read-only property $class::\$$name.");

		} else {
			\PHPStanVendor\Nette\Utils\ObjectMixin::strictSet($class, $name);
		}
	}


	/**
	 * @return void
	 * @throws MemberAccessException
	 */
	public function __unset($name)
	{
		$class = get_class($this);
		if (!\PHPStanVendor\Nette\Utils\ObjectMixin::hasProperty($class, $name)) {
			throw new \PHPStanVendor\Nette\MemberAccessException("Cannot unset the property $class::\$$name.");
		}
	}


	/**
	 * @return bool
	 */
	public function __isset($name)
	{
		$uname = ucfirst($name);
		return \PHPStanVendor\Nette\Utils\ObjectMixin::getMagicProperty(get_class($this), $name)
			|| ($name !== '' && ($methods = \PHPStanVendor\Nette\Utils\ObjectMixin::getMethods(get_class($this))) && (isset($methods['get' . $uname]) || isset($methods['is' . $uname])));
	}


	/**
	 * @return Reflection\ClassType|\ReflectionClass
	 * @deprecated
	 */
	public static function getReflection()
	{
		trigger_error(get_called_class() . '::getReflection() is deprecated' . \PHPStanVendor\Nette\Utils\ObjectMixin::getSource(), E_USER_DEPRECATED);
		$class = class_exists(\PHPStanVendor\Nette\Reflection\ClassType::class) ? \PHPStanVendor\Nette\Reflection\ClassType::class : \ReflectionClass::class;
		return new $class(get_called_class());
	}


	/**
	 * @return mixed
	 * @deprecated use Nette\Utils\ObjectMixin::setExtensionMethod()
	 */
	public static function extensionMethod($name, $callback = null)
	{
		if (strpos($name, '::') === false) {
			$class = get_called_class();
		} else {
			list($class, $name) = explode('::', $name);
			$class = (new \ReflectionClass($class))->getName();
		}
		trigger_error("Extension methods such as $class::$name() are deprecated" . \PHPStanVendor\Nette\Utils\ObjectMixin::getSource(), E_USER_DEPRECATED);
		if ($callback === null) {
			return \PHPStanVendor\Nette\Utils\ObjectMixin::getExtensionMethod($class, $name);
		} else {
			\PHPStanVendor\Nette\Utils\ObjectMixin::setExtensionMethod($class, $name, $callback);
		}
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette;


/**
 * Static class.
 */
trait StaticClass
{

	/**
	 * @throws \LogicException
	 */
	final public function __construct()
	{
		throw new \LogicException('Class ' . get_class($this) . ' is static and cannot be instantiated.');
	}


	/**
	 * Call to undefined static method.
	 * @throws MemberAccessException
	 */
	public static function __callStatic($name, $args)
	{
		\PHPStanVendor\Nette\Utils\ObjectMixin::strictStaticCall(get_called_class(), $name);
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Utils;


/**
 * String tools library.
 */
class Strings
{
	use \PHPStanVendor\Nette\StaticClass;

	const TRIM_CHARACTERS = " \t\n\r\0\x0B\xC2\xA0";


	/**
	 * Checks if the string is valid for UTF-8 encoding.
	 * @param  string  byte stream to check
	 * @return bool
	 */
	public static function checkEncoding($s)
	{
		return $s === self::fixEncoding($s);
	}


	/**
	 * Removes invalid code unit sequences from UTF-8 string.
	 * @param  string  byte stream to fix
	 * @return string
	 */
	public static function fixEncoding($s)
	{
		// removes xD800-xDFFF, x110000 and higher
		return htmlspecialchars_decode(htmlspecialchars($s, ENT_NOQUOTES | ENT_IGNORE, 'UTF-8'), ENT_NOQUOTES);
	}


	/**
	 * Returns a specific character in UTF-8.
	 * @param  int     code point (0x0 to 0xD7FF or 0xE000 to 0x10FFFF)
	 * @return string
	 * @throws Nette\InvalidArgumentException if code point is not in valid range
	 */
	public static function chr($code)
	{
		if ($code < 0 || ($code >= 0xD800 && $code <= 0xDFFF) || $code > 0x10FFFF) {
			throw new \PHPStanVendor\Nette\InvalidArgumentException('Code point must be in range 0x0 to 0xD7FF or 0xE000 to 0x10FFFF.');
		}
		return iconv('UTF-32BE', 'UTF-8//IGNORE', pack('N', $code));
	}


	/**
	 * Starts the $haystack string with the prefix $needle?
	 * @param  string
	 * @param  string
	 * @return bool
	 */
	public static function startsWith($haystack, $needle)
	{
		return strncmp($haystack, $needle, strlen($needle)) === 0;
	}


	/**
	 * Ends the $haystack string with the suffix $needle?
	 * @param  string
	 * @param  string
	 * @return bool
	 */
	public static function endsWith($haystack, $needle)
	{
		return strlen($needle) === 0 || substr($haystack, -strlen($needle)) === $needle;
	}


	/**
	 * Does $haystack contain $needle?
	 * @param  string
	 * @param  string
	 * @return bool
	 */
	public static function contains($haystack, $needle)
	{
		return strpos($haystack, $needle) !== false;
	}


	/**
	 * Returns a part of UTF-8 string.
	 * @param  string
	 * @param  int in characters (code points)
	 * @param  int in characters (code points)
	 * @return string
	 */
	public static function substring($s, $start, $length = null)
	{
		if (function_exists('mb_substr')) {
			return mb_substr($s, $start, $length, 'UTF-8'); // MB is much faster
		} elseif ($length === null) {
			$length = self::length($s);
		} elseif ($start < 0 && $length < 0) {
			$start += self::length($s); // unifies iconv_substr behavior with mb_substr
		}
		return iconv_substr($s, $start, $length, 'UTF-8');
	}


	/**
	 * Removes special controls characters and normalizes line endings and spaces.
	 * @param  string  UTF-8 encoding
	 * @return string
	 */
	public static function normalize($s)
	{
		$s = self::normalizeNewLines($s);

		// remove control characters; leave \t + \n
		$s = preg_replace('#[\x00-\x08\x0B-\x1F\x7F-\x9F]+#u', '', $s);

		// right trim
		$s = preg_replace('#[\t ]+$#m', '', $s);

		// leading and trailing blank lines
		$s = trim($s, "\n");

		return $s;
	}


	/**
	 * Standardize line endings to unix-like.
	 * @param  string  UTF-8 encoding or 8-bit
	 * @return string
	 */
	public static function normalizeNewLines($s)
	{
		return str_replace(["\r\n", "\r"], "\n", $s);
	}


	/**
	 * Converts to ASCII.
	 * @param  string  UTF-8 encoding
	 * @return string  ASCII
	 */
	public static function toAscii($s)
	{
		static $transliterator = null;
		if ($transliterator === null && class_exists('Transliterator', false)) {
			$transliterator = \Transliterator::create('Any-Latin; Latin-ASCII');
		}

		$s = preg_replace('#[^\x09\x0A\x0D\x20-\x7E\xA0-\x{2FF}\x{370}-\x{10FFFF}]#u', '', $s);
		$s = strtr($s, '`\'"^~?', "\x01\x02\x03\x04\x05\x06");
		$s = str_replace(
			["\xE2\x80\x9E", "\xE2\x80\x9C", "\xE2\x80\x9D", "\xE2\x80\x9A", "\xE2\x80\x98", "\xE2\x80\x99", "\xC2\xB0"],
			["\x03", "\x03", "\x03", "\x02", "\x02", "\x02", "\x04"], $s
		);
		if ($transliterator !== null) {
			$s = $transliterator->transliterate($s);
		}
		if (ICONV_IMPL === 'glibc') {
			$s = str_replace(
				["\xC2\xBB", "\xC2\xAB", "\xE2\x80\xA6", "\xE2\x84\xA2", "\xC2\xA9", "\xC2\xAE"],
				['>>', '<<', '...', 'TM', '(c)', '(R)'], $s
			);
			$s = iconv('UTF-8', 'WINDOWS-1250//TRANSLIT//IGNORE', $s);
			$s = strtr($s, "\xa5\xa3\xbc\x8c\xa7\x8a\xaa\x8d\x8f\x8e\xaf\xb9\xb3\xbe\x9c\x9a\xba\x9d\x9f\x9e"
				. "\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3"
				. "\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8"
				. "\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf8\xf9\xfa\xfb\xfc\xfd\xfe"
				. "\x96\xa0\x8b\x97\x9b\xa6\xad\xb7",
				'ALLSSSSTZZZallssstzzzRAAAALCCCEEEEIIDDNNOOOOxRUUUUYTsraaaalccceeeeiiddnnooooruuuuyt- <->|-.');
			$s = preg_replace('#[^\x00-\x7F]++#', '', $s);
		} else {
			$s = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $s);
		}
		$s = str_replace(['`', "'", '"', '^', '~', '?'], '', $s);
		return strtr($s, "\x01\x02\x03\x04\x05\x06", '`\'"^~?');
	}


	/**
	 * Converts to web safe characters [a-z0-9-] text.
	 * @param  string  UTF-8 encoding
	 * @param  string  allowed characters
	 * @param  bool
	 * @return string
	 */
	public static function webalize($s, $charlist = null, $lower = true)
	{
		$s = self::toAscii($s);
		if ($lower) {
			$s = strtolower($s);
		}
		$s = preg_replace('#[^a-z0-9' . ($charlist !== null ? preg_quote($charlist, '#') : '') . ']+#i', '-', $s);
		$s = trim($s, '-');
		return $s;
	}


	/**
	 * Truncates string to maximal length.
	 * @param  string  UTF-8 encoding
	 * @param  int
	 * @param  string  UTF-8 encoding
	 * @return string
	 */
	public static function truncate($s, $maxLen, $append = "\xE2\x80\xA6")
	{
		if (self::length($s) > $maxLen) {
			$maxLen = $maxLen - self::length($append);
			if ($maxLen < 1) {
				return $append;

			} elseif ($matches = self::match($s, '#^.{1,' . $maxLen . '}(?=[\s\x00-/:-@\[-`{-~])#us')) {
				return $matches[0] . $append;

			} else {
				return self::substring($s, 0, $maxLen) . $append;
			}
		}
		return $s;
	}


	/**
	 * Indents the content from the left.
	 * @param  string  UTF-8 encoding or 8-bit
	 * @param  int
	 * @param  string
	 * @return string
	 */
	public static function indent($s, $level = 1, $chars = "\t")
	{
		if ($level > 0) {
			$s = self::replace($s, '#(?:^|[\r\n]+)(?=[^\r\n])#', '$0' . str_repeat($chars, $level));
		}
		return $s;
	}


	/**
	 * Convert to lower case.
	 * @param  string  UTF-8 encoding
	 * @return string
	 */
	public static function lower($s)
	{
		return mb_strtolower($s, 'UTF-8');
	}


	/**
	 * Convert first character to lower case.
	 * @param  string  UTF-8 encoding
	 * @return string
	 */
	public static function firstLower($s)
	{
		return self::lower(self::substring($s, 0, 1)) . self::substring($s, 1);
	}


	/**
	 * Convert to upper case.
	 * @param  string  UTF-8 encoding
	 * @return string
	 */
	public static function upper($s)
	{
		return mb_strtoupper($s, 'UTF-8');
	}


	/**
	 * Convert first character to upper case.
	 * @param  string  UTF-8 encoding
	 * @return string
	 */
	public static function firstUpper($s)
	{
		return self::upper(self::substring($s, 0, 1)) . self::substring($s, 1);
	}


	/**
	 * Capitalize string.
	 * @param  string  UTF-8 encoding
	 * @return string
	 */
	public static function capitalize($s)
	{
		return mb_convert_case($s, MB_CASE_TITLE, 'UTF-8');
	}


	/**
	 * Case-insensitive compares UTF-8 strings.
	 * @param  string
	 * @param  string
	 * @param  int
	 * @return bool
	 */
	public static function compare($left, $right, $len = null)
	{
		if ($len < 0) {
			$left = self::substring($left, $len, -$len);
			$right = self::substring($right, $len, -$len);
		} elseif ($len !== null) {
			$left = self::substring($left, 0, $len);
			$right = self::substring($right, 0, $len);
		}
		return self::lower($left) === self::lower($right);
	}


	/**
	 * Finds the length of common prefix of strings.
	 * @param  string|array
	 * @return string
	 */
	public static function findPrefix(...$strings)
	{
		if (is_array($strings[0])) {
			$strings = $strings[0];
		}
		$first = array_shift($strings);
		for ($i = 0; $i < strlen($first); $i++) {
			foreach ($strings as $s) {
				if (!isset($s[$i]) || $first[$i] !== $s[$i]) {
					while ($i && $first[$i - 1] >= "\x80" && $first[$i] >= "\x80" && $first[$i] < "\xC0") {
						$i--;
					}
					return substr($first, 0, $i);
				}
			}
		}
		return $first;
	}


	/**
	 * Returns number of characters (not bytes) in UTF-8 string.
	 * That is the number of Unicode code points which may differ from the number of graphemes.
	 * @param  string
	 * @return int
	 */
	public static function length($s)
	{
		return function_exists('mb_strlen') ? mb_strlen($s, 'UTF-8') : strlen(utf8_decode($s));
	}


	/**
	 * Strips whitespace.
	 * @param  string  UTF-8 encoding
	 * @param  string
	 * @return string
	 */
	public static function trim($s, $charlist = self::TRIM_CHARACTERS)
	{
		$charlist = preg_quote($charlist, '#');
		return self::replace($s, '#^[' . $charlist . ']+|[' . $charlist . ']+\z#u', '');
	}


	/**
	 * Pad a string to a certain length with another string.
	 * @param  string  UTF-8 encoding
	 * @param  int
	 * @param  string
	 * @return string
	 */
	public static function padLeft($s, $length, $pad = ' ')
	{
		$length = max(0, $length - self::length($s));
		$padLen = self::length($pad);
		return str_repeat($pad, (int) ($length / $padLen)) . self::substring($pad, 0, $length % $padLen) . $s;
	}


	/**
	 * Pad a string to a certain length with another string.
	 * @param  string  UTF-8 encoding
	 * @param  int
	 * @param  string
	 * @return string
	 */
	public static function padRight($s, $length, $pad = ' ')
	{
		$length = max(0, $length - self::length($s));
		$padLen = self::length($pad);
		return $s . str_repeat($pad, (int) ($length / $padLen)) . self::substring($pad, 0, $length % $padLen);
	}


	/**
	 * Reverse string.
	 * @param  string  UTF-8 encoding
	 * @return string
	 */
	public static function reverse($s)
	{
		return iconv('UTF-32LE', 'UTF-8', strrev(iconv('UTF-8', 'UTF-32BE', $s)));
	}


	/**
	 * Use Nette\Utils\Random::generate
	 * @deprecated
	 */
	public static function random($length = 10, $charlist = '0-9a-z')
	{
		trigger_error(__METHOD__ . '() is deprecated, use \PHPStanVendor\Nette\Utils\Random::generate()', E_USER_DEPRECATED);
		return \PHPStanVendor\Nette\Utils\Random::generate($length, $charlist);
	}


	/**
	 * Returns part of $haystack before $nth occurence of $needle.
	 * @param  string
	 * @param  string
	 * @param  int  negative value means searching from the end
	 * @return string|false  returns false if the needle was not found
	 */
	public static function before($haystack, $needle, $nth = 1)
	{
		$pos = self::pos($haystack, $needle, $nth);
		return $pos === false
			? false
			: substr($haystack, 0, $pos);
	}


	/**
	 * Returns part of $haystack after $nth occurence of $needle.
	 * @param  string
	 * @param  string
	 * @param  int  negative value means searching from the end
	 * @return string|false  returns false if the needle was not found
	 */
	public static function after($haystack, $needle, $nth = 1)
	{
		$pos = self::pos($haystack, $needle, $nth);
		return $pos === false
			? false
			: (string) substr($haystack, $pos + strlen($needle));
	}


	/**
	 * Returns position of $nth occurence of $needle in $haystack.
	 * @param  string
	 * @param  string
	 * @param  int  negative value means searching from the end
	 * @return int|false  offset in characters or false if the needle was not found
	 */
	public static function indexOf($haystack, $needle, $nth = 1)
	{
		$pos = self::pos($haystack, $needle, $nth);
		return $pos === false
			? false
			: self::length(substr($haystack, 0, $pos));
	}


	/**
	 * Returns position of $nth occurence of $needle in $haystack.
	 * @return int|false  offset in bytes or false if the needle was not found
	 */
	private static function pos($haystack, $needle, $nth = 1)
	{
		if (!$nth) {
			return false;
		} elseif ($nth > 0) {
			if (strlen($needle) === 0) {
				return 0;
			}
			$pos = 0;
			while (($pos = strpos($haystack, $needle, $pos)) !== false && --$nth) {
				$pos++;
			}
		} else {
			$len = strlen($haystack);
			if (strlen($needle) === 0) {
				return $len;
			}
			$pos = $len - 1;
			while (($pos = strrpos($haystack, $needle, $pos - $len)) !== false && ++$nth) {
				$pos--;
			}
		}
		return $pos;
	}


	/**
	 * Splits string by a regular expression.
	 * @param  string
	 * @param  string
	 * @param  int
	 * @return array
	 */
	public static function split($subject, $pattern, $flags = 0)
	{
		return self::pcre('preg_split', [$pattern, $subject, -1, $flags | PREG_SPLIT_DELIM_CAPTURE]);
	}


	/**
	 * Performs a regular expression match.
	 * @param  string
	 * @param  string
	 * @param  int  can be PREG_OFFSET_CAPTURE (returned in bytes)
	 * @param  int  offset in bytes
	 * @return mixed
	 */
	public static function match($subject, $pattern, $flags = 0, $offset = 0)
	{
		if ($offset > strlen($subject)) {
			return null;
		}
		return self::pcre('preg_match', [$pattern, $subject, &$m, $flags, $offset])
			? $m
			: null;
	}


	/**
	 * Performs a global regular expression match.
	 * @param  string
	 * @param  string
	 * @param  int  can be PREG_OFFSET_CAPTURE (returned in bytes); PREG_SET_ORDER is default
	 * @param  int  offset in bytes
	 * @return array
	 */
	public static function matchAll($subject, $pattern, $flags = 0, $offset = 0)
	{
		if ($offset > strlen($subject)) {
			return [];
		}
		self::pcre('preg_match_all', [
			$pattern, $subject, &$m,
			($flags & PREG_PATTERN_ORDER) ? $flags : ($flags | PREG_SET_ORDER),
			$offset,
		]);
		return $m;
	}


	/**
	 * Perform a regular expression search and replace.
	 * @param  string
	 * @param  string|array
	 * @param  string|callable
	 * @param  int
	 * @return string
	 */
	public static function replace($subject, $pattern, $replacement = null, $limit = -1)
	{
		if (is_object($replacement) || is_array($replacement)) {
			if ($replacement instanceof \PHPStanVendor\Nette\Callback) {
				trigger_error('\PHPStanVendor\Nette\Callback is deprecated, use PHP callback.', E_USER_DEPRECATED);
				$replacement = $replacement->getNative();
			}
			if (!is_callable($replacement, false, $textual)) {
				throw new \PHPStanVendor\Nette\InvalidStateException("Callback '$textual' is not callable.");
			}

			return self::pcre('preg_replace_callback', [$pattern, $replacement, $subject, $limit]);

		} elseif ($replacement === null && is_array($pattern)) {
			$replacement = array_values($pattern);
			$pattern = array_keys($pattern);
		}

		return self::pcre('preg_replace', [$pattern, $replacement, $subject, $limit]);
	}


	/** @internal */
	public static function pcre($func, $args)
	{
		static $messages = [
			PREG_INTERNAL_ERROR => 'Internal error',
			PREG_BACKTRACK_LIMIT_ERROR => 'Backtrack limit was exhausted',
			PREG_RECURSION_LIMIT_ERROR => 'Recursion limit was exhausted',
			PREG_BAD_UTF8_ERROR => 'Malformed UTF-8 data',
			PREG_BAD_UTF8_OFFSET_ERROR => 'Offset didn\'t correspond to the begin of a valid UTF-8 code point',
			6 => 'Failed due to limited JIT stack space', // PREG_JIT_STACKLIMIT_ERROR
		];
		$res = \PHPStanVendor\Nette\Utils\Callback::invokeSafe($func, $args, function ($message) use ($args) {
			// compile-time error, not detectable by preg_last_error
			throw new \PHPStanVendor\Nette\Utils\RegexpException($message . ' in pattern: ' . implode(' or ', (array) $args[0]));
		});

		if (($code = preg_last_error()) // run-time error, but preg_last_error & return code are liars
			&& ($res === null || !in_array($func, ['preg_filter', 'preg_replace_callback', 'preg_replace'], true))
		) {
			throw new \PHPStanVendor\Nette\Utils\RegexpException((isset($messages[$code]) ? $messages[$code] : 'Unknown error')
				. ' (pattern: ' . implode(' or ', (array) $args[0]) . ')', $code);
		}
		return $res;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette\Utils;


/**
 * Validation utilities.
 */
class Validators
{
	use \PHPStanVendor\Nette\StaticClass;

	protected static $validators = [
		'bool' => 'is_bool',
		'boolean' => 'is_bool',
		'int' => 'is_int',
		'integer' => 'is_int',
		'float' => 'is_float',
		'number' => [__CLASS__, 'isNumber'],
		'numeric' => [__CLASS__, 'isNumeric'],
		'numericint' => [__CLASS__, 'isNumericInt'],
		'string' => 'is_string',
		'unicode' => [__CLASS__, 'isUnicode'],
		'array' => 'is_array',
		'list' => [\PHPStanVendor\Nette\Utils\Arrays::class, 'isList'],
		'object' => 'is_object',
		'resource' => 'is_resource',
		'scalar' => 'is_scalar',
		'callable' => [__CLASS__, 'isCallable'],
		'null' => 'is_null',
		'email' => [__CLASS__, 'isEmail'],
		'url' => [__CLASS__, 'isUrl'],
		'uri' => [__CLASS__, 'isUri'],
		'none' => [__CLASS__, 'isNone'],
		'type' => [__CLASS__, 'isType'],
		'identifier' => [__CLASS__, 'isPhpIdentifier'],
		'pattern' => null,
		'alnum' => 'ctype_alnum',
		'alpha' => 'ctype_alpha',
		'digit' => 'ctype_digit',
		'lower' => 'ctype_lower',
		'upper' => 'ctype_upper',
		'space' => 'ctype_space',
		'xdigit' => 'ctype_xdigit',
		'iterable' => [__CLASS__, 'isIterable'],
	];

	protected static $counters = [
		'string' => 'strlen',
		'unicode' => [\PHPStanVendor\Nette\Utils\Strings::class, 'length'],
		'array' => 'count',
		'list' => 'count',
		'alnum' => 'strlen',
		'alpha' => 'strlen',
		'digit' => 'strlen',
		'lower' => 'strlen',
		'space' => 'strlen',
		'upper' => 'strlen',
		'xdigit' => 'strlen',
	];


	/**
	 * Throws exception if a variable is of unexpected type.
	 * @param  mixed
	 * @param  string  expected types separated by pipe
	 * @param  string  label
	 * @return void
	 */
	public static function assert($value, $expected, $label = 'variable')
	{
		if (!static::is($value, $expected)) {
			$expected = str_replace(['|', ':'], [' or ', ' in range '], $expected);
			if (is_array($value)) {
				$type = 'array(' . count($value) . ')';
			} elseif (is_object($value)) {
				$type = 'object ' . get_class($value);
			} elseif (is_string($value) && strlen($value) < 40) {
				$type = "string '$value'";
			} else {
				$type = gettype($value);
			}
			throw new \PHPStanVendor\Nette\Utils\AssertionException("The $label expects to be $expected, $type given.");
		}
	}


	/**
	 * Throws exception if an array field is missing or of unexpected type.
	 * @param  array
	 * @param  string  item
	 * @param  string  expected types separated by pipe
	 * @param  string
	 * @return void
	 */
	public static function assertField($arr, $field, $expected = null, $label = "item '%' in array")
	{
		self::assert($arr, 'array', 'first argument');
		if (!array_key_exists($field, $arr)) {
			throw new \PHPStanVendor\Nette\Utils\AssertionException('Missing ' . str_replace('%', $field, $label) . '.');

		} elseif ($expected) {
			static::assert($arr[$field], $expected, str_replace('%', $field, $label));
		}
	}


	/**
	 * Finds whether a variable is of expected type.
	 * @param  mixed
	 * @param  string  expected types separated by pipe with optional ranges
	 * @return bool
	 */
	public static function is($value, $expected)
	{
		foreach (explode('|', $expected) as $item) {
			if (substr($item, -2) === '[]') {
				if (self::everyIs($value, substr($item, 0, -2))) {
					return true;
				}
				continue;
			}

			list($type) = $item = explode(':', $item, 2);
			if (isset(static::$validators[$type])) {
				if (!call_user_func(static::$validators[$type], $value)) {
					continue;
				}
			} elseif ($type === 'pattern') {
				if (preg_match('|^' . (isset($item[1]) ? $item[1] : '') . '\z|', $value)) {
					return true;
				}
				continue;
			} elseif (!$value instanceof $type) {
				continue;
			}

			if (isset($item[1])) {
				$length = $value;
				if (isset(static::$counters[$type])) {
					$length = call_user_func(static::$counters[$type], $value);
				}
				$range = explode('..', $item[1]);
				if (!isset($range[1])) {
					$range[1] = $range[0];
				}
				if (($range[0] !== '' && $length < $range[0]) || ($range[1] !== '' && $length > $range[1])) {
					continue;
				}
			}
			return true;
		}
		return false;
	}


	/**
	 * Finds whether all values are of expected type.
	 * @param  array|\Traversable
	 * @param  string  expected types separated by pipe with optional ranges
	 * @return bool
	 */
	public static function everyIs($values, $expected)
	{
		if (!self::isIterable($values)) {
			return false;
		}
		foreach ($values as $value) {
			if (!static::is($value, $expected)) {
				return false;
			}
		}
		return true;
	}


	/**
	 * Finds whether a value is an integer or a float.
	 * @return bool
	 */
	public static function isNumber($value)
	{
		return is_int($value) || is_float($value);
	}


	/**
	 * Finds whether a value is an integer.
	 * @return bool
	 */
	public static function isNumericInt($value)
	{
		return is_int($value) || is_string($value) && preg_match('#^-?[0-9]+\z#', $value);
	}


	/**
	 * Finds whether a string is a floating point number in decimal base.
	 * @return bool
	 */
	public static function isNumeric($value)
	{
		return is_float($value) || is_int($value) || is_string($value) && preg_match('#^-?[0-9]*[.]?[0-9]+\z#', $value);
	}


	/**
	 * Finds whether a value is a syntactically correct callback.
	 * @return bool
	 */
	public static function isCallable($value)
	{
		return $value && is_callable($value, true);
	}


	/**
	 * Finds whether a value is an UTF-8 encoded string.
	 * @param  string
	 * @return bool
	 */
	public static function isUnicode($value)
	{
		return is_string($value) && preg_match('##u', $value);
	}


	/**
	 * Finds whether a value is "falsy".
	 * @return bool
	 */
	public static function isNone($value)
	{
		return $value == null; // intentionally ==
	}


	/**
	 * Finds whether a variable is a zero-based integer indexed array.
	 * @param  array
	 * @return bool
	 */
	public static function isList($value)
	{
		return \PHPStanVendor\Nette\Utils\Arrays::isList($value);
	}


	/**
	 * Is a value in specified range?
	 * @param  mixed
	 * @param  array  min and max value pair
	 * @return bool
	 */
	public static function isInRange($value, $range)
	{
		if ($value === null || !(isset($range[0]) || isset($range[1]))) {
			return false;
		}
		$limit = isset($range[0]) ? $range[0] : $range[1];
		if (is_string($limit)) {
			$value = (string) $value;
		} elseif ($limit instanceof \DateTimeInterface) {
			if (!$value instanceof \DateTimeInterface) {
				return false;
			}
		} elseif (is_numeric($value)) {
			$value *= 1;
		} else {
			return false;
		}
		return (!isset($range[0]) || ($value >= $range[0])) && (!isset($range[1]) || ($value <= $range[1]));
	}


	/**
	 * Finds whether a string is a valid email address.
	 * @param  string
	 * @return bool
	 */
	public static function isEmail($value)
	{
		$atom = "[-a-z0-9!#$%&'*+/=?^_`{|}~]"; // RFC 5322 unquoted characters in local-part
		$alpha = "a-z\x80-\xFF"; // superset of IDN
		return (bool) preg_match("(^
			(\"([ !#-[\\]-~]*|\\\\[ -~])+\"|$atom+(\\.$atom+)*)  # quoted or unquoted
			@
			([0-9$alpha]([-0-9$alpha]{0,61}[0-9$alpha])?\\.)+    # domain - RFC 1034
			[$alpha]([-0-9$alpha]{0,17}[$alpha])?                # top domain
		\\z)ix", $value);
	}


	/**
	 * Finds whether a string is a valid http(s) URL.
	 * @param  string
	 * @return bool
	 */
	public static function isUrl($value)
	{
		$alpha = "a-z\x80-\xFF";
		return (bool) preg_match("(^
			https?://(
				(([-_0-9$alpha]+\\.)*                       # subdomain
					[0-9$alpha]([-0-9$alpha]{0,61}[0-9$alpha])?\\.)?  # domain
					[$alpha]([-0-9$alpha]{0,17}[$alpha])?   # top domain
				|\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}  # IPv4
				|\[[0-9a-f:]{3,39}\]                        # IPv6
			)(:\\d{1,5})?                                   # port
			(/\\S*)?                                        # path
		\\z)ix", $value);
	}


	/**
	 * Finds whether a string is a valid URI according to RFC 1738.
	 * @param  string
	 * @return bool
	 */
	public static function isUri($value)
	{
		return (bool) preg_match('#^[a-z\d+\.-]+:\S+\z#i', $value);
	}


	/**
	 * Checks whether the input is a class, interface or trait.
	 * @param  string
	 * @return bool
	 */
	public static function isType($type)
	{
		return class_exists($type) || interface_exists($type) || trait_exists($type);
	}


	/**
	 * Checks whether the input is a valid PHP identifier.
	 * @return bool
	 */
	public static function isPhpIdentifier($value)
	{
		return is_string($value) && preg_match('#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\z#', $value);
	}


	/**
	 * Returns true if value is iterable (array or instance of Traversable).
	 * @return bool
	 */
	private static function isIterable($value)
	{
		return is_array($value) || $value instanceof \Traversable;
	}
}
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */

namespace PHPStanVendor\Nette;


/**
 * The exception that is thrown when the value of an argument is
 * outside the allowable range of values as defined by the invoked method.
 */
class ArgumentOutOfRangeException extends \InvalidArgumentException
{
}


/**
 * The exception that is thrown when a method call is invalid for the object's
 * current state, method has been invoked at an illegal or inappropriate time.
 */
class InvalidStateException extends \RuntimeException
{
}


/**
 * The exception that is thrown when a requested method or operation is not implemented.
 */
class NotImplementedException extends \LogicException
{
}


/**
 * The exception that is thrown when an invoked method is not supported. For scenarios where
 * it is sometimes possible to perform the requested operation, see InvalidStateException.
 */
class NotSupportedException extends \LogicException
{
}


/**
 * The exception that is thrown when a requested method or operation is deprecated.
 */
class DeprecatedException extends \PHPStanVendor\Nette\NotSupportedException
{
}


/**
 * The exception that is thrown when accessing a class member (property or method) fails.
 */
class MemberAccessException extends \LogicException
{
}


/**
 * The exception that is thrown when an I/O error occurs.
 */
class IOException extends \RuntimeException
{
}


/**
 * The exception that is thrown when accessing a file that does not exist on disk.
 */
class FileNotFoundException extends \PHPStanVendor\Nette\IOException
{
}


/**
 * The exception that is thrown when part of a file or directory cannot be found.
 */
class DirectoryNotFoundException extends \PHPStanVendor\Nette\IOException
{
}


/**
 * The exception that is thrown when an argument does not match with the expected value.
 */
class InvalidArgumentException extends \InvalidArgumentException
{
}


/**
 * The exception that is thrown when an illegal index was requested.
 */
class OutOfRangeException extends \OutOfRangeException
{
}


/**
 * The exception that is thrown when a value (typically returned by function) does not match with the expected value.
 */
class UnexpectedValueException extends \UnexpectedValueException
{
}


/**
 * The exception that is thrown when static class is instantiated.
 */
class StaticClassException extends \LogicException
{
}

namespace PHPStanVendor\Nette\Utils;


/**
 * The exception that is thrown when an image error occurs.
 */
class ImageException extends \Exception
{
}


/**
 * The exception that indicates invalid image file.
 */
class UnknownImageFileException extends \PHPStanVendor\Nette\Utils\ImageException
{
}


/**
 * The exception that indicates error of JSON encoding/decoding.
 */
class JsonException extends \Exception
{
}


/**
 * The exception that indicates error of the last Regexp execution.
 */
class RegexpException extends \Exception
{
}


/**
 * The exception that indicates assertion error.
 */
class AssertionException extends \Exception
{
}

Copyright (c) 2011-2018 by Nikita Popov.

Some rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above
      copyright notice, this list of conditions and the following
      disclaimer in the documentation and/or other materials provided
      with the distribution.

    * The names of the contributors may not be used to endorse or
      promote products derived from this software without specific
      prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

<?php
{
    "name": "nikic/php-parser",
    "description": "A PHP parser written in PHP",
    "keywords": ["php", "parser"],
    "type": "library",
    "license": "BSD-3-Clause",
    "authors": [
        {
            "name": "Nikita Popov"
        }
    ],
    "require": {
        "php": ">=5.5",
        "ext-tokenizer": "*"
    },
    "require-dev": {
        "phpunit/phpunit": "~4.0|~5.0"
    },
    "autoload": {
        "psr-4": {
            "PhpParser\\": "lib/PhpParser"
        }
    },
    "bin": ["bin/php-parse"],
    "extra": {
        "branch-alias": {
            "dev-master": "3.0-dev"
        }
    }
}
<?php

namespace PhpParser;

/**
 * @codeCoverageIgnore
 */
class Autoloader
{
    /** @var bool Whether the autoloader has been registered. */
    private static $registered = false;

    /**
     * Registers PhpParser\Autoloader as an SPL autoloader.
     *
     * @param bool $prepend Whether to prepend the autoloader instead of appending
     */
    static public function register($prepend = false) {
        if (self::$registered === true) {
            return;
        }

        spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);
        self::$registered = true;
    }

    /**
     * Handles autoloading of classes.
     *
     * @param string $class A class name.
     */
    static public function autoload($class) {
        if (0 === strpos($class, 'PhpParser\\')) {
            $fileName = __DIR__ . strtr(substr($class, 9), '\\', '/') . '.php';
            if (file_exists($fileName)) {
                require $fileName;
            }
        }
    }
}
<?php

namespace PhpParser;

interface Builder
{
    /**
     * Returns the built node.
     *
     * @return Node The built node
     */
    public function getNode();
}<?php

namespace PhpParser\Builder;

use PhpParser;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt;

class Class_ extends Declaration
{
    protected $name;

    protected $extends = null;
    protected $implements = array();
    protected $flags = 0;

    protected $uses = array();
    protected $constants = array();
    protected $properties = array();
    protected $methods = array();

    /**
     * Creates a class builder.
     *
     * @param string $name Name of the class
     */
    public function __construct($name) {
        $this->name = $name;
    }

    /**
     * Extends a class.
     *
     * @param Name|string $class Name of class to extend
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function extend($class) {
        $this->extends = $this->normalizeName($class);

        return $this;
    }

    /**
     * Implements one or more interfaces.
     *
     * @param Name|string ...$interfaces Names of interfaces to implement
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function implement() {
        foreach (func_get_args() as $interface) {
            $this->implements[] = $this->normalizeName($interface);
        }

        return $this;
    }

    /**
     * Makes the class abstract.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeAbstract() {
        $this->setModifier(Stmt\Class_::MODIFIER_ABSTRACT);

        return $this;
    }

    /**
     * Makes the class final.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeFinal() {
        $this->setModifier(Stmt\Class_::MODIFIER_FINAL);

        return $this;
    }

    /**
     * Adds a statement.
     *
     * @param Stmt|PhpParser\Builder $stmt The statement to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addStmt($stmt) {
        $stmt = $this->normalizeNode($stmt);

        $targets = array(
            'Stmt_TraitUse'    => &$this->uses,
            'Stmt_ClassConst'  => &$this->constants,
            'Stmt_Property'    => &$this->properties,
            'Stmt_ClassMethod' => &$this->methods,
        );

        $type = $stmt->getType();
        if (!isset($targets[$type])) {
            throw new \LogicException(sprintf('Unexpected node of type "%s"', $type));
        }

        $targets[$type][] = $stmt;

        return $this;
    }

    /**
     * Returns the built class node.
     *
     * @return Stmt\Class_ The built class node
     */
    public function getNode() {
        return new Stmt\Class_($this->name, array(
            'flags' => $this->flags,
            'extends' => $this->extends,
            'implements' => $this->implements,
            'stmts' => array_merge($this->uses, $this->constants, $this->properties, $this->methods),
        ), $this->attributes);
    }
}<?php

namespace PhpParser\Builder;

use PhpParser;

abstract class Declaration extends PhpParser\BuilderAbstract
{
    protected $attributes = array();

    abstract public function addStmt($stmt);

    /**
     * Adds multiple statements.
     *
     * @param array $stmts The statements to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addStmts(array $stmts) {
        foreach ($stmts as $stmt) {
            $this->addStmt($stmt);
        }

        return $this;
    }

    /**
     * Sets doc comment for the declaration.
     *
     * @param PhpParser\Comment\Doc|string $docComment Doc comment to set
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function setDocComment($docComment) {
        $this->attributes['comments'] = array(
            $this->normalizeDocComment($docComment)
        );

        return $this;
    }
}<?php

namespace PhpParser\Builder;

use PhpParser;
use PhpParser\Node;

abstract class FunctionLike extends Declaration
{
    protected $returnByRef = false;
    protected $params = array();

    /** @var string|Node\Name|Node\NullableType|null */
    protected $returnType = null;

    /**
     * Make the function return by reference.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeReturnByRef() {
        $this->returnByRef = true;

        return $this;
    }

    /**
     * Adds a parameter.
     *
     * @param Node\Param|Param $param The parameter to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addParam($param) {
        $param = $this->normalizeNode($param);

        if (!$param instanceof Node\Param) {
            throw new \LogicException(sprintf('Expected parameter node, got "%s"', $param->getType()));
        }

        $this->params[] = $param;

        return $this;
    }

    /**
     * Adds multiple parameters.
     *
     * @param array $params The parameters to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addParams(array $params) {
        foreach ($params as $param) {
            $this->addParam($param);
        }

        return $this;
    }

    /**
     * Sets the return type for PHP 7.
     *
     * @param string|Node\Name|Node\NullableType $type One of array, callable, string, int, float, bool, iterable,
     *                               or a class/interface name.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function setReturnType($type)
    {
        $this->returnType = $this->normalizeType($type);

        return $this;
    }
}
<?php

namespace PhpParser\Builder;

use PhpParser;
use PhpParser\Node;
use PhpParser\Node\Stmt;

class Function_ extends FunctionLike
{
    protected $name;
    protected $stmts = array();

    /**
     * Creates a function builder.
     *
     * @param string $name Name of the function
     */
    public function __construct($name) {
        $this->name = $name;
    }

    /**
     * Adds a statement.
     *
     * @param Node|PhpParser\Builder $stmt The statement to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addStmt($stmt) {
        $this->stmts[] = $this->normalizeNode($stmt);

        return $this;
    }

    /**
     * Returns the built function node.
     *
     * @return Stmt\Function_ The built function node
     */
    public function getNode() {
        return new Stmt\Function_($this->name, array(
            'byRef'      => $this->returnByRef,
            'params'     => $this->params,
            'returnType' => $this->returnType,
            'stmts'      => $this->stmts,
        ), $this->attributes);
    }
}
<?php

namespace PhpParser\Builder;

use PhpParser;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt;

class Interface_ extends Declaration
{
    protected $name;
    protected $extends = array();
    protected $constants = array();
    protected $methods = array();

    /**
     * Creates an interface builder.
     *
     * @param string $name Name of the interface
     */
    public function __construct($name) {
        $this->name = $name;
    }

    /**
     * Extends one or more interfaces.
     *
     * @param Name|string ...$interfaces Names of interfaces to extend
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function extend() {
        foreach (func_get_args() as $interface) {
            $this->extends[] = $this->normalizeName($interface);
        }

        return $this;
    }

    /**
     * Adds a statement.
     *
     * @param Stmt|PhpParser\Builder $stmt The statement to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addStmt($stmt) {
        $stmt = $this->normalizeNode($stmt);

        $type = $stmt->getType();
        switch ($type) {
            case 'Stmt_ClassConst':
                $this->constants[] = $stmt;
                break;

            case 'Stmt_ClassMethod':
                // we erase all statements in the body of an interface method
                $stmt->stmts = null;
                $this->methods[] = $stmt;
                break;

            default:
                throw new \LogicException(sprintf('Unexpected node of type "%s"', $type));
        }

        return $this;
    }

    /**
     * Returns the built interface node.
     *
     * @return Stmt\Interface_ The built interface node
     */
    public function getNode() {
        return new Stmt\Interface_($this->name, array(
            'extends' => $this->extends,
            'stmts' => array_merge($this->constants, $this->methods),
        ), $this->attributes);
    }
}<?php

namespace PhpParser\Builder;

use PhpParser;
use PhpParser\Node;
use PhpParser\Node\Stmt;

class Method extends FunctionLike
{
    protected $name;
    protected $flags = 0;

    /** @var array|null */
    protected $stmts = array();

    /**
     * Creates a method builder.
     *
     * @param string $name Name of the method
     */
    public function __construct($name) {
        $this->name = $name;
    }

    /**
     * Makes the method public.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makePublic() {
        $this->setModifier(Stmt\Class_::MODIFIER_PUBLIC);

        return $this;
    }

    /**
     * Makes the method protected.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeProtected() {
        $this->setModifier(Stmt\Class_::MODIFIER_PROTECTED);

        return $this;
    }

    /**
     * Makes the method private.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makePrivate() {
        $this->setModifier(Stmt\Class_::MODIFIER_PRIVATE);

        return $this;
    }

    /**
     * Makes the method static.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeStatic() {
        $this->setModifier(Stmt\Class_::MODIFIER_STATIC);

        return $this;
    }

    /**
     * Makes the method abstract.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeAbstract() {
        if (!empty($this->stmts)) {
            throw new \LogicException('Cannot make method with statements abstract');
        }

        $this->setModifier(Stmt\Class_::MODIFIER_ABSTRACT);
        $this->stmts = null; // abstract methods don't have statements

        return $this;
    }

    /**
     * Makes the method final.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeFinal() {
        $this->setModifier(Stmt\Class_::MODIFIER_FINAL);

        return $this;
    }

    /**
     * Adds a statement.
     *
     * @param Node|PhpParser\Builder $stmt The statement to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addStmt($stmt) {
        if (null === $this->stmts) {
            throw new \LogicException('Cannot add statements to an abstract method');
        }

        $this->stmts[] = $this->normalizeNode($stmt);

        return $this;
    }

    /**
     * Returns the built method node.
     *
     * @return Stmt\ClassMethod The built method node
     */
    public function getNode() {
        return new Stmt\ClassMethod($this->name, array(
            'flags'      => $this->flags,
            'byRef'      => $this->returnByRef,
            'params'     => $this->params,
            'returnType' => $this->returnType,
            'stmts'      => $this->stmts,
        ), $this->attributes);
    }
}
<?php

namespace PhpParser\Builder;

use PhpParser;
use PhpParser\Node;
use PhpParser\Node\Stmt;

class Namespace_ extends Declaration
{
    private $name;
    private $stmts = array();

    /**
     * Creates a namespace builder.
     *
     * @param Node\Name|string|null $name Name of the namespace
     */
    public function __construct($name) {
        $this->name = null !== $name ? $this->normalizeName($name) : null;
    }

    /**
     * Adds a statement.
     *
     * @param Node|PhpParser\Builder $stmt The statement to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addStmt($stmt) {
        $this->stmts[] = $this->normalizeNode($stmt);

        return $this;
    }

    /**
     * Returns the built node.
     *
     * @return Node The built node
     */
    public function getNode() {
        return new Stmt\Namespace_($this->name, $this->stmts, $this->attributes);
    }
}
<?php

namespace PhpParser\Builder;

use PhpParser;
use PhpParser\Node;

class Param extends PhpParser\BuilderAbstract
{
    protected $name;

    protected $default = null;

    /** @var string|Node\Name|Node\NullableType|null */
    protected $type = null;

    protected $byRef = false;

    protected $variadic = false;

    /**
     * Creates a parameter builder.
     *
     * @param string $name Name of the parameter
     */
    public function __construct($name) {
        $this->name = $name;
    }

    /**
     * Sets default value for the parameter.
     *
     * @param mixed $value Default value to use
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function setDefault($value) {
        $this->default = $this->normalizeValue($value);

        return $this;
    }

    /**
     * Sets type hint for the parameter.
     *
     * @param string|Node\Name|Node\NullableType $type Type hint to use
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function setTypeHint($type) {
        $this->type = $this->normalizeType($type);
        if ($this->type === 'void') {
            throw new \LogicException('Parameter type cannot be void');
        }

        return $this;
    }

    /**
     * Make the parameter accept the value by reference.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeByRef() {
        $this->byRef = true;

        return $this;
    }

    /**
     * Make the parameter variadic
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeVariadic() {
        $this->variadic = true;

        return $this;
    }

    /**
     * Returns the built parameter node.
     *
     * @return Node\Param The built parameter node
     */
    public function getNode() {
        return new Node\Param(
            $this->name, $this->default, $this->type, $this->byRef, $this->variadic
        );
    }
}
<?php

namespace PhpParser\Builder;

use PhpParser;
use PhpParser\Node\Stmt;

class Property extends PhpParser\BuilderAbstract
{
    protected $name;

    protected $flags = 0;
    protected $default = null;
    protected $attributes = array();

    /**
     * Creates a property builder.
     *
     * @param string $name Name of the property
     */
    public function __construct($name) {
        $this->name = $name;
    }

    /**
     * Makes the property public.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makePublic() {
        $this->setModifier(Stmt\Class_::MODIFIER_PUBLIC);

        return $this;
    }

    /**
     * Makes the property protected.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeProtected() {
        $this->setModifier(Stmt\Class_::MODIFIER_PROTECTED);

        return $this;
    }

    /**
     * Makes the property private.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makePrivate() {
        $this->setModifier(Stmt\Class_::MODIFIER_PRIVATE);

        return $this;
    }

    /**
     * Makes the property static.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeStatic() {
        $this->setModifier(Stmt\Class_::MODIFIER_STATIC);

        return $this;
    }

    /**
     * Sets default value for the property.
     *
     * @param mixed $value Default value to use
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function setDefault($value) {
        $this->default = $this->normalizeValue($value);

        return $this;
    }

    /**
     * Sets doc comment for the property.
     *
     * @param PhpParser\Comment\Doc|string $docComment Doc comment to set
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function setDocComment($docComment) {
        $this->attributes = array(
            'comments' => array($this->normalizeDocComment($docComment))
        );

        return $this;
    }

    /**
     * Returns the built class node.
     *
     * @return Stmt\Property The built property node
     */
    public function getNode() {
        return new Stmt\Property(
            $this->flags !== 0 ? $this->flags : Stmt\Class_::MODIFIER_PUBLIC,
            array(
                new Stmt\PropertyProperty($this->name, $this->default)
            ),
            $this->attributes
        );
    }
}<?php

namespace PhpParser\Builder;

use PhpParser;
use PhpParser\Node\Stmt;

class Trait_ extends Declaration
{
    protected $name;
    protected $uses = array();
    protected $properties = array();
    protected $methods = array();

    /**
     * Creates an interface builder.
     *
     * @param string $name Name of the interface
     */
    public function __construct($name) {
        $this->name = $name;
    }

    /**
     * Adds a statement.
     *
     * @param Stmt|PhpParser\Builder $stmt The statement to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addStmt($stmt) {
        $stmt = $this->normalizeNode($stmt);

        if ($stmt instanceof Stmt\Property) {
            $this->properties[] = $stmt;
        } else if ($stmt instanceof Stmt\ClassMethod) {
            $this->methods[] = $stmt;
        } else if ($stmt instanceof Stmt\TraitUse) {
            $this->uses[] = $stmt;
        } else {
            throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType()));
        }

        return $this;
    }

    /**
     * Returns the built trait node.
     *
     * @return Stmt\Trait_ The built interface node
     */
    public function getNode() {
        return new Stmt\Trait_(
            $this->name, array(
                'stmts' => array_merge($this->uses, $this->properties, $this->methods)
            ), $this->attributes
        );
    }
}
<?php

namespace PhpParser\Builder;

use PhpParser\BuilderAbstract;
use PhpParser\Node;
use PhpParser\Node\Stmt;

/**
 * @method $this as(string $alias) Sets alias for used name.
 */
class Use_ extends BuilderAbstract {
    protected $name;
    protected $type;
    protected $alias = null;

    /**
     * Creates a name use (alias) builder.
     *
     * @param Node\Name|string $name Name of the entity (namespace, class, function, constant) to alias
     * @param int              $type One of the Stmt\Use_::TYPE_* constants
     */
    public function __construct($name, $type) {
        $this->name = $this->normalizeName($name);
        $this->type = $type;
    }

    /**
     * Sets alias for used name.
     *
     * @param string $alias Alias to use (last component of full name by default)
     *
     * @return $this The builder instance (for fluid interface)
     */
    protected function as_($alias) {
        $this->alias = $alias;
        return $this;
    }
    public function __call($name, $args) {
        if (method_exists($this, $name . '_')) {
            return call_user_func_array(array($this, $name . '_'), $args);
        }

        throw new \LogicException(sprintf('Method "%s" does not exist', $name));
    }

    /**
     * Returns the built node.
     *
     * @return Node The built node
     */
    public function getNode() {
        $alias = null !== $this->alias ? $this->alias : $this->name->getLast();
        return new Stmt\Use_(array(
            new Stmt\UseUse($this->name, $alias)
        ), $this->type);
    }
}
<?php

namespace PhpParser;

use PhpParser\Comment;
use PhpParser\Node\Expr;
use PhpParser\Node\Name;
use PhpParser\Node\NullableType;
use PhpParser\Node\Scalar;
use PhpParser\Node\Stmt;

abstract class BuilderAbstract implements Builder {
    /**
     * Normalizes a node: Converts builder objects to nodes.
     *
     * @param Node|Builder $node The node to normalize
     *
     * @return Node The normalized node
     */
    protected function normalizeNode($node) {
        if ($node instanceof Builder) {
            return $node->getNode();
        } elseif ($node instanceof Node) {
            return $node;
        }

        throw new \LogicException('Expected node or builder object');
    }

    /**
     * Normalizes a name: Converts plain string names to PhpParser\Node\Name.
     *
     * @param Name|string $name The name to normalize
     *
     * @return Name The normalized name
     */
    protected function normalizeName($name) {
        if ($name instanceof Name) {
            return $name;
        } elseif (is_string($name)) {
            if (!$name) {
                throw new \LogicException('Name cannot be empty');
            }

            if ($name[0] == '\\') {
                return new Name\FullyQualified(substr($name, 1));
            } elseif (0 === strpos($name, 'namespace\\')) {
                return new Name\Relative(substr($name, strlen('namespace\\')));
            } else {
                return new Name($name);
            }
        }

        throw new \LogicException('Name must be a string or an instance of PhpParser\Node\Name');
    }

    /**
     * Normalizes a type: Converts plain-text type names into proper AST representation.
     *
     * In particular, builtin types are left as strings, custom types become Names and nullables
     * are wrapped in NullableType nodes.
     *
     * @param Name|string|NullableType $type The type to normalize
     *
     * @return Name|string|NullableType The normalized type
     */
    protected function normalizeType($type) {
        if (!is_string($type)) {
            if (!$type instanceof Name && !$type instanceof NullableType) {
                throw new \LogicException(
                    'Type must be a string, or an instance of Name or NullableType');
            }
            return $type;
        }

        $nullable = false;
        if (strlen($type) > 0 && $type[0] === '?') {
            $nullable = true;
            $type = substr($type, 1);
        }

        $builtinTypes = array(
            'array', 'callable', 'string', 'int', 'float', 'bool', 'iterable', 'void', 'object'
        );

        $lowerType = strtolower($type);
        if (in_array($lowerType, $builtinTypes)) {
            $type = $lowerType;
        } else {
            $type = $this->normalizeName($type);
        }

        if ($nullable && $type === 'void') {
            throw new \LogicException('void type cannot be nullable');
        }

        return $nullable ? new Node\NullableType($type) : $type;
    }

    /**
     * Normalizes a value: Converts nulls, booleans, integers,
     * floats, strings and arrays into their respective nodes
     *
     * @param mixed $value The value to normalize
     *
     * @return Expr The normalized value
     */
    protected function normalizeValue($value) {
        if ($value instanceof Node) {
            return $value;
        } elseif (is_null($value)) {
            return new Expr\ConstFetch(
                new Name('null')
            );
        } elseif (is_bool($value)) {
            return new Expr\ConstFetch(
                new Name($value ? 'true' : 'false')
            );
        } elseif (is_int($value)) {
            return new Scalar\LNumber($value);
        } elseif (is_float($value)) {
            return new Scalar\DNumber($value);
        } elseif (is_string($value)) {
            return new Scalar\String_($value);
        } elseif (is_array($value)) {
            $items = array();
            $lastKey = -1;
            foreach ($value as $itemKey => $itemValue) {
                // for consecutive, numeric keys don't generate keys
                if (null !== $lastKey && ++$lastKey === $itemKey) {
                    $items[] = new Expr\ArrayItem(
                        $this->normalizeValue($itemValue)
                    );
                } else {
                    $lastKey = null;
                    $items[] = new Expr\ArrayItem(
                        $this->normalizeValue($itemValue),
                        $this->normalizeValue($itemKey)
                    );
                }
            }

            return new Expr\Array_($items);
        } else {
            throw new \LogicException('Invalid value');
        }
    }

    /**
     * Normalizes a doc comment: Converts plain strings to PhpParser\Comment\Doc.
     *
     * @param Comment\Doc|string $docComment The doc comment to normalize
     *
     * @return Comment\Doc The normalized doc comment
     */
    protected function normalizeDocComment($docComment) {
        if ($docComment instanceof Comment\Doc) {
            return $docComment;
        } else if (is_string($docComment)) {
            return new Comment\Doc($docComment);
        } else {
            throw new \LogicException('Doc comment must be a string or an instance of PhpParser\Comment\Doc');
        }
    }

    /**
     * Sets a modifier in the $this->type property.
     *
     * @param int $modifier Modifier to set
     */
    protected function setModifier($modifier) {
        Stmt\Class_::verifyModifier($this->flags, $modifier);
        $this->flags |= $modifier;
    }
}
<?php

namespace PhpParser;

use PhpParser\Builder;
use PhpParser\Node\Stmt\Use_;

/**
 * The following methods use reserved keywords, so their implementation is defined with an underscore and made available
 * with the reserved name through __call() magic.
 *
 * @method Builder\Namespace_ namespace(string $name) Creates a namespace builder.
 * @method Builder\Class_     class(string $name)     Creates a class builder.
 * @method Builder\Interface_ interface(string $name) Creates an interface builder.
 * @method Builder\Trait_     trait(string $name)     Creates a trait builder.
 * @method Builder\Function_  function(string $name)  Creates a function builder.
 * @method Builder\Use_       use(string $name)       Creates a namespace/class use builder.
 */
class BuilderFactory
{
    /**
     * Creates a namespace builder.
     *
     * @param null|string|Node\Name $name Name of the namespace
     *
     * @return Builder\Namespace_ The created namespace builder
     */
    protected function _namespace($name) {
        return new Builder\Namespace_($name);
    }

    /**
     * Creates a class builder.
     *
     * @param string $name Name of the class
     *
     * @return Builder\Class_ The created class builder
     */
    protected function _class($name) {
        return new Builder\Class_($name);
    }

    /**
     * Creates an interface builder.
     *
     * @param string $name Name of the interface
     *
     * @return Builder\Interface_ The created interface builder
     */
    protected function _interface($name) {
        return new Builder\Interface_($name);
    }

    /**
     * Creates a trait builder.
     *
     * @param string $name Name of the trait
     *
     * @return Builder\Trait_ The created trait builder
     */
    protected function _trait($name) {
        return new Builder\Trait_($name);
    }

    /**
     * Creates a method builder.
     *
     * @param string $name Name of the method
     *
     * @return Builder\Method The created method builder
     */
    public function method($name) {
        return new Builder\Method($name);
    }

    /**
     * Creates a parameter builder.
     *
     * @param string $name Name of the parameter
     *
     * @return Builder\Param The created parameter builder
     */
    public function param($name) {
        return new Builder\Param($name);
    }

    /**
     * Creates a property builder.
     *
     * @param string $name Name of the property
     *
     * @return Builder\Property The created property builder
     */
    public function property($name) {
        return new Builder\Property($name);
    }

    /**
     * Creates a function builder.
     *
     * @param string $name Name of the function
     *
     * @return Builder\Function_ The created function builder
     */
    protected function _function($name) {
        return new Builder\Function_($name);
    }

    /**
     * Creates a namespace/class use builder.
     *
     * @param string|Node\Name Name to alias
     *
     * @return Builder\Use_ The create use builder
     */
    protected function _use($name) {
        return new Builder\Use_($name, Use_::TYPE_NORMAL);
    }

    public function __call($name, array $args) {
        if (method_exists($this, '_' . $name)) {
            return call_user_func_array(array($this, '_' . $name), $args);
        }

        throw new \LogicException(sprintf('Method "%s" does not exist', $name));
    }
}
<?php

namespace PhpParser;

class Comment implements \JsonSerializable
{
    protected $text;
    protected $line;
    protected $filePos;

    /**
     * Constructs a comment node.
     *
     * @param string $text         Comment text (including comment delimiters like /*)
     * @param int    $startLine    Line number the comment started on
     * @param int    $startFilePos File offset the comment started on
     */
    public function __construct($text, $startLine = -1, $startFilePos = -1) {
        $this->text = $text;
        $this->line = $startLine;
        $this->filePos = $startFilePos;
    }

    /**
     * Gets the comment text.
     *
     * @return string The comment text (including comment delimiters like /*)
     */
    public function getText() {
        return $this->text;
    }

    /**
     * Gets the line number the comment started on.
     *
     * @return int Line number
     */
    public function getLine() {
        return $this->line;
    }

    /**
     * Gets the file offset the comment started on.
     *
     * @return int File offset
     */
    public function getFilePos() {
        return $this->filePos;
    }

    /**
     * Gets the comment text.
     *
     * @return string The comment text (including comment delimiters like /*)
     */
    public function __toString() {
        return $this->text;
    }

    /**
     * Gets the reformatted comment text.
     *
     * "Reformatted" here means that we try to clean up the whitespace at the
     * starts of the lines. This is necessary because we receive the comments
     * without trailing whitespace on the first line, but with trailing whitespace
     * on all subsequent lines.
     *
     * @return mixed|string
     */
    public function getReformattedText() {
        $text = trim($this->text);
        $newlinePos = strpos($text, "\n");
        if (false === $newlinePos) {
            // Single line comments don't need further processing
            return $text;
        } elseif (preg_match('((*BSR_ANYCRLF)(*ANYCRLF)^.*(?:\R\s+\*.*)+$)', $text)) {
            // Multi line comment of the type
            //
            //     /*
            //      * Some text.
            //      * Some more text.
            //      */
            //
            // is handled by replacing the whitespace sequences before the * by a single space
            return preg_replace('(^\s+\*)m', ' *', $this->text);
        } elseif (preg_match('(^/\*\*?\s*[\r\n])', $text) && preg_match('(\n(\s*)\*/$)', $text, $matches)) {
            // Multi line comment of the type
            //
            //    /*
            //        Some text.
            //        Some more text.
            //    */
            //
            // is handled by removing the whitespace sequence on the line before the closing
            // */ on all lines. So if the last line is "    */", then "    " is removed at the
            // start of all lines.
            return preg_replace('(^' . preg_quote($matches[1]) . ')m', '', $text);
        } elseif (preg_match('(^/\*\*?\s*(?!\s))', $text, $matches)) {
            // Multi line comment of the type
            //
            //     /* Some text.
            //        Some more text.
            //          Indented text.
            //        Even more text. */
            //
            // is handled by removing the difference between the shortest whitespace prefix on all
            // lines and the length of the "/* " opening sequence.
            $prefixLen = $this->getShortestWhitespacePrefixLen(substr($text, $newlinePos + 1));
            $removeLen = $prefixLen - strlen($matches[0]);
            return preg_replace('(^\s{' . $removeLen . '})m', '', $text);
        }

        // No idea how to format this comment, so simply return as is
        return $text;
    }

    private function getShortestWhitespacePrefixLen($str) {
        $lines = explode("\n", $str);
        $shortestPrefixLen = INF;
        foreach ($lines as $line) {
            preg_match('(^\s*)', $line, $matches);
            $prefixLen = strlen($matches[0]);
            if ($prefixLen < $shortestPrefixLen) {
                $shortestPrefixLen = $prefixLen;
            }
        }
        return $shortestPrefixLen;
    }

    public function jsonSerialize() {
        // Technically not a node, but we make it look like one anyway
        $type = $this instanceof Comment\Doc ? 'Comment_Doc' : 'Comment';
        return [
            'nodeType' => $type,
            'text' => $this->text,
            'line' => $this->line,
            'filePos' => $this->filePos,
        ];
    }
}<?php

namespace PhpParser\Comment;

class Doc extends \PhpParser\Comment
{
}<?php

namespace PhpParser;

class Error extends \RuntimeException
{
    protected $rawMessage;
    protected $attributes;

    /**
     * Creates an Exception signifying a parse error.
     *
     * @param string    $message    Error message
     * @param array|int $attributes Attributes of node/token where error occurred
     *                              (or start line of error -- deprecated)
     */
    public function __construct($message, $attributes = array()) {
        $this->rawMessage = (string) $message;
        if (is_array($attributes)) {
            $this->attributes = $attributes;
        } else {
            $this->attributes = array('startLine' => $attributes);
        }
        $this->updateMessage();
    }

    /**
     * Gets the error message
     *
     * @return string Error message
     */
    public function getRawMessage() {
        return $this->rawMessage;
    }

    /**
     * Gets the line the error starts in.
     *
     * @return int Error start line
     */
    public function getStartLine() {
        return isset($this->attributes['startLine']) ? $this->attributes['startLine'] : -1;
    }

    /**
     * Gets the line the error ends in.
     *
     * @return int Error end line
     */
    public function getEndLine() {
        return isset($this->attributes['endLine']) ? $this->attributes['endLine'] : -1;
    }


    /**
     * Gets the attributes of the node/token the error occurred at.
     *
     * @return array
     */
    public function getAttributes() {
        return $this->attributes;
    }

    /**
     * Sets the attributes of the node/token the error occured at.
     *
     * @param array $attributes
     */
    public function setAttributes(array $attributes) {
        $this->attributes = $attributes;
        $this->updateMessage();
    }

    /**
     * Sets the line of the PHP file the error occurred in.
     *
     * @param string $message Error message
     */
    public function setRawMessage($message) {
        $this->rawMessage = (string) $message;
        $this->updateMessage();
    }

    /**
     * Sets the line the error starts in.
     *
     * @param int $line Error start line
     */
    public function setStartLine($line) {
        $this->attributes['startLine'] = (int) $line;
        $this->updateMessage();
    }

    /**
     * Returns whether the error has start and end column information.
     *
     * For column information enable the startFilePos and endFilePos in the lexer options.
     *
     * @return bool
     */
    public function hasColumnInfo() {
        return isset($this->attributes['startFilePos']) && isset($this->attributes['endFilePos']);
    }

    /**
     * Gets the start column (1-based) into the line where the error started.
     *
     * @param string $code Source code of the file
     * @return int
     */
    public function getStartColumn($code) {
        if (!$this->hasColumnInfo()) {
            throw new \RuntimeException('Error does not have column information');
        }

        return $this->toColumn($code, $this->attributes['startFilePos']);
    }

    /**
     * Gets the end column (1-based) into the line where the error ended.
     *
     * @param string $code Source code of the file
     * @return int
     */
    public function getEndColumn($code) {
        if (!$this->hasColumnInfo()) {
            throw new \RuntimeException('Error does not have column information');
        }

        return $this->toColumn($code, $this->attributes['endFilePos']);
    }

    public function getMessageWithColumnInfo($code) {
        return sprintf(
            '%s from %d:%d to %d:%d', $this->getRawMessage(),
            $this->getStartLine(), $this->getStartColumn($code),
            $this->getEndLine(), $this->getEndColumn($code)
        );
    }

    private function toColumn($code, $pos) {
        if ($pos > strlen($code)) {
            throw new \RuntimeException('Invalid position information');
        }

        $lineStartPos = strrpos($code, "\n", $pos - strlen($code));
        if (false === $lineStartPos) {
            $lineStartPos = -1;
        }

        return $pos - $lineStartPos;
    }

    /**
     * Updates the exception message after a change to rawMessage or rawLine.
     */
    protected function updateMessage() {
        $this->message = $this->rawMessage;

        if (-1 === $this->getStartLine()) {
            $this->message .= ' on unknown line';
        } else {
            $this->message .= ' on line ' . $this->getStartLine();
        }
    }
}
<?php

namespace PhpParser;

interface ErrorHandler
{
    /**
     * Handle an error generated during lexing, parsing or some other operation.
     *
     * @param Error $error The error that needs to be handled
     */
    public function handleError(Error $error);
}<?php

namespace PhpParser\ErrorHandler;

use PhpParser\Error;
use PhpParser\ErrorHandler;

/**
 * Error handler that collects all errors into an array.
 *
 * This allows graceful handling of errors.
 */
class Collecting implements ErrorHandler
{
    /** @var Error[] Collected errors */
    private $errors = [];

    public function handleError(Error $error) {
        $this->errors[] = $error;
    }

    /**
     * Get collected errors.
     *
     * @return Error[]
     */
    public function getErrors() {
        return $this->errors;
    }

    /**
     * Check whether there are any errors.
     *
     * @return bool
     */
    public function hasErrors() {
        return !empty($this->errors);
    }

    /**
     * Reset/clear collected errors.
     */
    public function clearErrors() {
        $this->errors = [];
    }
}<?php

namespace PhpParser\ErrorHandler;

use PhpParser\Error;
use PhpParser\ErrorHandler;

/**
 * Error handler that handles all errors by throwing them.
 *
 * This is the default strategy used by all components.
 */
class Throwing implements ErrorHandler
{
    public function handleError(Error $error) {
        throw $error;
    }
}<?php

namespace PhpParser;

use PhpParser\Parser\Tokens;

class Lexer
{
    protected $code;
    protected $tokens;
    protected $pos;
    protected $line;
    protected $filePos;
    protected $prevCloseTagHasNewline;

    protected $tokenMap;
    protected $dropTokens;

    protected $usedAttributes;

    /**
     * Creates a Lexer.
     *
     * @param array $options Options array. Currently only the 'usedAttributes' option is supported,
     *                       which is an array of attributes to add to the AST nodes. Possible
     *                       attributes are: 'comments', 'startLine', 'endLine', 'startTokenPos',
     *                       'endTokenPos', 'startFilePos', 'endFilePos'. The option defaults to the
     *                       first three. For more info see getNextToken() docs.
     */
    public function __construct(array $options = array()) {
        // map from internal tokens to PhpParser tokens
        $this->tokenMap = $this->createTokenMap();

        // map of tokens to drop while lexing (the map is only used for isset lookup,
        // that's why the value is simply set to 1; the value is never actually used.)
        $this->dropTokens = array_fill_keys(
            array(T_WHITESPACE, T_OPEN_TAG, T_COMMENT, T_DOC_COMMENT), 1
        );

        // the usedAttributes member is a map of the used attribute names to a dummy
        // value (here "true")
        $options += array(
            'usedAttributes' => array('comments', 'startLine', 'endLine'),
        );
        $this->usedAttributes = array_fill_keys($options['usedAttributes'], true);
    }

    /**
     * Initializes the lexer for lexing the provided source code.
     *
     * This function does not throw if lexing errors occur. Instead, errors may be retrieved using
     * the getErrors() method.
     *
     * @param string $code The source code to lex
     * @param ErrorHandler|null $errorHandler Error handler to use for lexing errors. Defaults to
     *                                        ErrorHandler\Throwing
     */
    public function startLexing($code, ErrorHandler $errorHandler = null) {
        if (null === $errorHandler) {
            $errorHandler = new ErrorHandler\Throwing();
        }

        $this->code = $code; // keep the code around for __halt_compiler() handling
        $this->pos  = -1;
        $this->line =  1;
        $this->filePos = 0;

        // If inline HTML occurs without preceding code, treat it as if it had a leading newline.
        // This ensures proper composability, because having a newline is the "safe" assumption.
        $this->prevCloseTagHasNewline = true;

        $scream = ini_set('xdebug.scream', '0');

        $this->resetErrors();
        $this->tokens = @token_get_all($code);
        $this->handleErrors($errorHandler);

        if (false !== $scream) {
            ini_set('xdebug.scream', $scream);
        }
    }

    protected function resetErrors() {
        if (function_exists('error_clear_last')) {
            error_clear_last();
        } else {
            // set error_get_last() to defined state by forcing an undefined variable error
            set_error_handler(function() { return false; }, 0);
            @$undefinedVariable;
            restore_error_handler();
        }
    }

    private function handleInvalidCharacterRange($start, $end, $line, ErrorHandler $errorHandler) {
        for ($i = $start; $i < $end; $i++) {
            $chr = $this->code[$i];
            if ($chr === 'b' || $chr === 'B') {
                // HHVM does not treat b" tokens correctly, so ignore these
                continue;
            }

            if ($chr === "\0") {
                // PHP cuts error message after null byte, so need special case
                $errorMsg = 'Unexpected null byte';
            } else {
                $errorMsg = sprintf(
                    'Unexpected character "%s" (ASCII %d)', $chr, ord($chr)
                );
            }

            $errorHandler->handleError(new Error($errorMsg, [
                'startLine' => $line,
                'endLine' => $line,
                'startFilePos' => $i,
                'endFilePos' => $i,
            ]));
        }
    }

    private function isUnterminatedComment($token) {
        return ($token[0] === T_COMMENT || $token[0] === T_DOC_COMMENT)
            && substr($token[1], 0, 2) === '/*'
            && substr($token[1], -2) !== '*/';
    }

    private function errorMayHaveOccurred() {
        if (defined('HHVM_VERSION')) {
            // In HHVM token_get_all() does not throw warnings, so we need to conservatively
            // assume that an error occurred
            return true;
        }

        $error = error_get_last();
        return null !== $error
            && false === strpos($error['message'], 'Undefined variable');
    }

    protected function handleErrors(ErrorHandler $errorHandler) {
        if (!$this->errorMayHaveOccurred()) {
            return;
        }

        // PHP's error handling for token_get_all() is rather bad, so if we want detailed
        // error information we need to compute it ourselves. Invalid character errors are
        // detected by finding "gaps" in the token array. Unterminated comments are detected
        // by checking if a trailing comment has a "*/" at the end.

        $filePos = 0;
        $line = 1;
        foreach ($this->tokens as $i => $token) {
            $tokenValue = \is_string($token) ? $token : $token[1];
            $tokenLen = \strlen($tokenValue);

            if (substr($this->code, $filePos, $tokenLen) !== $tokenValue) {
                // Something is missing, must be an invalid character
                $nextFilePos = strpos($this->code, $tokenValue, $filePos);
                $this->handleInvalidCharacterRange(
                    $filePos, $nextFilePos, $line, $errorHandler);
                $filePos = $nextFilePos;
            }

            $filePos += $tokenLen;
            $line += substr_count($tokenValue, "\n");
        }

        if ($filePos !== \strlen($this->code)) {
            if (substr($this->code, $filePos, 2) === '/*') {
                // Unlike PHP, HHVM will drop unterminated comments entirely
                $comment = substr($this->code, $filePos);
                $errorHandler->handleError(new Error('Unterminated comment', [
                    'startLine' => $line,
                    'endLine' => $line + substr_count($comment, "\n"),
                    'startFilePos' => $filePos,
                    'endFilePos' => $filePos + \strlen($comment),
                ]));

                // Emulate the PHP behavior
                $isDocComment = isset($comment[3]) && $comment[3] === '*';
                $this->tokens[] = [$isDocComment ? T_DOC_COMMENT : T_COMMENT, $comment, $line];
            } else {
                // Invalid characters at the end of the input
                $this->handleInvalidCharacterRange(
                    $filePos, \strlen($this->code), $line, $errorHandler);
            }
            return;
        }

        if (count($this->tokens) > 0) {
            // Check for unterminated comment
            $lastToken = $this->tokens[count($this->tokens) - 1];
            if ($this->isUnterminatedComment($lastToken)) {
                $errorHandler->handleError(new Error('Unterminated comment', [
                    'startLine' => $line - substr_count($lastToken[1], "\n"),
                    'endLine' => $line,
                    'startFilePos' => $filePos - \strlen($lastToken[1]),
                    'endFilePos' => $filePos,
                ]));
            }
        }
    }

    /**
     * Fetches the next token.
     *
     * The available attributes are determined by the 'usedAttributes' option, which can
     * be specified in the constructor. The following attributes are supported:
     *
     *  * 'comments'      => Array of PhpParser\Comment or PhpParser\Comment\Doc instances,
     *                       representing all comments that occurred between the previous
     *                       non-discarded token and the current one.
     *  * 'startLine'     => Line in which the node starts.
     *  * 'endLine'       => Line in which the node ends.
     *  * 'startTokenPos' => Offset into the token array of the first token in the node.
     *  * 'endTokenPos'   => Offset into the token array of the last token in the node.
     *  * 'startFilePos'  => Offset into the code string of the first character that is part of the node.
     *  * 'endFilePos'    => Offset into the code string of the last character that is part of the node.
     *
     * @param mixed $value           Variable to store token content in
     * @param mixed $startAttributes Variable to store start attributes in
     * @param mixed $endAttributes   Variable to store end attributes in
     *
     * @return int Token id
     */
    public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) {
        $startAttributes = array();
        $endAttributes   = array();

        while (1) {
            if (isset($this->tokens[++$this->pos])) {
                $token = $this->tokens[$this->pos];
            } else {
                // EOF token with ID 0
                $token = "\0";
            }

            if (isset($this->usedAttributes['startLine'])) {
                $startAttributes['startLine'] = $this->line;
            }
            if (isset($this->usedAttributes['startTokenPos'])) {
                $startAttributes['startTokenPos'] = $this->pos;
            }
            if (isset($this->usedAttributes['startFilePos'])) {
                $startAttributes['startFilePos'] = $this->filePos;
            }

            if (\is_string($token)) {
                $value = $token;
                if (isset($token[1])) {
                    // bug in token_get_all
                    $this->filePos += 2;
                    $id = ord('"');
                } else {
                    $this->filePos += 1;
                    $id = ord($token);
                }
            } elseif (!isset($this->dropTokens[$token[0]])) {
                $value = $token[1];
                $id = $this->tokenMap[$token[0]];
                if (T_CLOSE_TAG === $token[0]) {
                    $this->prevCloseTagHasNewline = false !== strpos($token[1], "\n");
                } else if (T_INLINE_HTML === $token[0]) {
                    $startAttributes['hasLeadingNewline'] = $this->prevCloseTagHasNewline;
                }

                $this->line += substr_count($value, "\n");
                $this->filePos += \strlen($value);
            } else {
                if (T_COMMENT === $token[0] || T_DOC_COMMENT === $token[0]) {
                    if (isset($this->usedAttributes['comments'])) {
                        $comment = T_DOC_COMMENT === $token[0]
                            ? new Comment\Doc($token[1], $this->line, $this->filePos)
                            : new Comment($token[1], $this->line, $this->filePos);
                        $startAttributes['comments'][] = $comment;
                    }
                }

                $this->line += substr_count($token[1], "\n");
                $this->filePos += \strlen($token[1]);
                continue;
            }

            if (isset($this->usedAttributes['endLine'])) {
                $endAttributes['endLine'] = $this->line;
            }
            if (isset($this->usedAttributes['endTokenPos'])) {
                $endAttributes['endTokenPos'] = $this->pos;
            }
            if (isset($this->usedAttributes['endFilePos'])) {
                $endAttributes['endFilePos'] = $this->filePos - 1;
            }

            return $id;
        }

        throw new \RuntimeException('Reached end of lexer loop');
    }

    /**
     * Returns the token array for current code.
     *
     * The token array is in the same format as provided by the
     * token_get_all() function and does not discard tokens (i.e.
     * whitespace and comments are included). The token position
     * attributes are against this token array.
     *
     * @return array Array of tokens in token_get_all() format
     */
    public function getTokens() {
        return $this->tokens;
    }

    /**
     * Handles __halt_compiler() by returning the text after it.
     *
     * @return string Remaining text
     */
    public function handleHaltCompiler() {
        // text after T_HALT_COMPILER, still including ();
        $textAfter = substr($this->code, $this->filePos);

        // ensure that it is followed by ();
        // this simplifies the situation, by not allowing any comments
        // in between of the tokens.
        if (!preg_match('~^\s*\(\s*\)\s*(?:;|\?>\r?\n?)~', $textAfter, $matches)) {
            throw new Error('__HALT_COMPILER must be followed by "();"');
        }

        // prevent the lexer from returning any further tokens
        $this->pos = count($this->tokens);

        // return with (); removed
        return (string) substr($textAfter, strlen($matches[0])); // (string) converts false to ''
    }

    /**
     * Creates the token map.
     *
     * The token map maps the PHP internal token identifiers
     * to the identifiers used by the Parser. Additionally it
     * maps T_OPEN_TAG_WITH_ECHO to T_ECHO and T_CLOSE_TAG to ';'.
     *
     * @return array The token map
     */
    protected function createTokenMap() {
        $tokenMap = array();

        // 256 is the minimum possible token number, as everything below
        // it is an ASCII value
        for ($i = 256; $i < 1000; ++$i) {
            if (T_DOUBLE_COLON === $i) {
                // T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM
                $tokenMap[$i] = Tokens::T_PAAMAYIM_NEKUDOTAYIM;
            } elseif(T_OPEN_TAG_WITH_ECHO === $i) {
                // T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO
                $tokenMap[$i] = Tokens::T_ECHO;
            } elseif(T_CLOSE_TAG === $i) {
                // T_CLOSE_TAG is equivalent to ';'
                $tokenMap[$i] = ord(';');
            } elseif ('UNKNOWN' !== $name = token_name($i)) {
                if ('T_HASHBANG' === $name) {
                    // HHVM uses a special token for #! hashbang lines
                    $tokenMap[$i] = Tokens::T_INLINE_HTML;
                } else if (defined($name = Tokens::class . '::' . $name)) {
                    // Other tokens can be mapped directly
                    $tokenMap[$i] = constant($name);
                }
            }
        }

        // HHVM uses a special token for numbers that overflow to double
        if (defined('T_ONUMBER')) {
            $tokenMap[T_ONUMBER] = Tokens::T_DNUMBER;
        }
        // HHVM also has a separate token for the __COMPILER_HALT_OFFSET__ constant
        if (defined('T_COMPILER_HALT_OFFSET')) {
            $tokenMap[T_COMPILER_HALT_OFFSET] = Tokens::T_STRING;
        }

        return $tokenMap;
    }
}
<?php

namespace PhpParser\Lexer;

use PhpParser\ErrorHandler;
use PhpParser\Parser\Tokens;

class Emulative extends \PhpParser\Lexer
{
    protected $newKeywords;
    protected $inObjectAccess;

    const T_ELLIPSIS   = 1001;
    const T_POW        = 1002;
    const T_POW_EQUAL  = 1003;
    const T_COALESCE   = 1004;
    const T_SPACESHIP  = 1005;
    const T_YIELD_FROM = 1006;

    const PHP_7_0 = '7.0.0dev';
    const PHP_5_6 = '5.6.0rc1';

    public function __construct(array $options = array()) {
        parent::__construct($options);

        $newKeywordsPerVersion = array(
            // No new keywords since PHP 5.5
        );

        $this->newKeywords = array();
        foreach ($newKeywordsPerVersion as $version => $newKeywords) {
            if (version_compare(PHP_VERSION, $version, '>=')) {
                break;
            }

            $this->newKeywords += $newKeywords;
        }

        if (version_compare(PHP_VERSION, self::PHP_7_0, '>=')) {
            return;
        }
        $this->tokenMap[self::T_COALESCE]   = Tokens::T_COALESCE;
        $this->tokenMap[self::T_SPACESHIP]  = Tokens::T_SPACESHIP;
        $this->tokenMap[self::T_YIELD_FROM] = Tokens::T_YIELD_FROM;

        if (version_compare(PHP_VERSION, self::PHP_5_6, '>=')) {
            return;
        }
        $this->tokenMap[self::T_ELLIPSIS]  = Tokens::T_ELLIPSIS;
        $this->tokenMap[self::T_POW]       = Tokens::T_POW;
        $this->tokenMap[self::T_POW_EQUAL] = Tokens::T_POW_EQUAL;
    }

    public function startLexing($code, ErrorHandler $errorHandler = null) {
        $this->inObjectAccess = false;

        parent::startLexing($code, $errorHandler);
        if ($this->requiresEmulation($code)) {
            $this->emulateTokens();
        }
    }

    /*
     * Checks if the code is potentially using features that require emulation.
     */
    protected function requiresEmulation($code) {
        if (version_compare(PHP_VERSION, self::PHP_7_0, '>=')) {
            return false;
        }

        if (preg_match('(\?\?|<=>|yield[ \n\r\t]+from)', $code)) {
            return true;
        }

        if (version_compare(PHP_VERSION, self::PHP_5_6, '>=')) {
            return false;
        }

        return preg_match('(\.\.\.|(?<!/)\*\*(?!/))', $code);
    }

    /*
     * Emulates tokens for newer PHP versions.
     */
    protected function emulateTokens() {
        // We need to manually iterate and manage a count because we'll change
        // the tokens array on the way
        $line = 1;
        for ($i = 0, $c = count($this->tokens); $i < $c; ++$i) {
            $replace = null;
            if (isset($this->tokens[$i + 1])) {
                if ($this->tokens[$i] === '?' && $this->tokens[$i + 1] === '?') {
                    array_splice($this->tokens, $i, 2, array(
                        array(self::T_COALESCE, '??', $line)
                    ));
                    $c--;
                    continue;
                }
                if ($this->tokens[$i][0] === T_IS_SMALLER_OR_EQUAL
                    && $this->tokens[$i + 1] === '>'
                ) {
                    array_splice($this->tokens, $i, 2, array(
                        array(self::T_SPACESHIP, '<=>', $line)
                    ));
                    $c--;
                    continue;
                }
                if ($this->tokens[$i] === '*' && $this->tokens[$i + 1] === '*') {
                    array_splice($this->tokens, $i, 2, array(
                        array(self::T_POW, '**', $line)
                    ));
                    $c--;
                    continue;
                }
                if ($this->tokens[$i] === '*' && $this->tokens[$i + 1][0] === T_MUL_EQUAL) {
                    array_splice($this->tokens, $i, 2, array(
                        array(self::T_POW_EQUAL, '**=', $line)
                    ));
                    $c--;
                    continue;
                }
            }

            if (isset($this->tokens[$i + 2])) {
                if ($this->tokens[$i][0] === T_YIELD && $this->tokens[$i + 1][0] === T_WHITESPACE
                    && $this->tokens[$i + 2][0] === T_STRING
                    && !strcasecmp($this->tokens[$i + 2][1], 'from')
                ) {
                    array_splice($this->tokens, $i, 3, array(
                        array(
                            self::T_YIELD_FROM,
                            $this->tokens[$i][1] . $this->tokens[$i + 1][1] . $this->tokens[$i + 2][1],
                            $line
                        )
                    ));
                    $c -= 2;
                    $line += substr_count($this->tokens[$i][1], "\n");
                    continue;
                }
                if ($this->tokens[$i] === '.' && $this->tokens[$i + 1] === '.'
                    && $this->tokens[$i + 2] === '.'
                ) {
                    array_splice($this->tokens, $i, 3, array(
                        array(self::T_ELLIPSIS, '...', $line)
                    ));
                    $c -= 2;
                    continue;
                }
            }

            if (\is_array($this->tokens[$i])) {
                $line += substr_count($this->tokens[$i][1], "\n");
            }
        }
    }

    public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) {
        $token = parent::getNextToken($value, $startAttributes, $endAttributes);

        // replace new keywords by their respective tokens. This is not done
        // if we currently are in an object access (e.g. in $obj->namespace
        // "namespace" stays a T_STRING tokens and isn't converted to T_NAMESPACE)
        if (Tokens::T_STRING === $token && !$this->inObjectAccess) {
            if (isset($this->newKeywords[strtolower($value)])) {
                return $this->newKeywords[strtolower($value)];
            }
        } else {
            // keep track of whether we currently are in an object access (after ->)
            $this->inObjectAccess = Tokens::T_OBJECT_OPERATOR === $token;
        }

        return $token;
    }
}
<?php

namespace PhpParser;

interface Node
{
    /**
     * Gets the type of the node.
     *
     * @return string Type of the node
     */
    public function getType();

    /**
     * Gets the names of the sub nodes.
     *
     * @return array Names of sub nodes
     */
    public function getSubNodeNames();

    /**
     * Gets line the node started in.
     *
     * @return int Line
     */
    public function getLine();

    /**
     * Sets line the node started in.
     *
     * @param int $line Line
     *
     * @deprecated
     */
    public function setLine($line);

    /**
     * Gets the doc comment of the node.
     *
     * The doc comment has to be the last comment associated with the node.
     *
     * @return null|Comment\Doc Doc comment object or null
     */
    public function getDocComment();

    /**
     * Sets the doc comment of the node.
     *
     * This will either replace an existing doc comment or add it to the comments array.
     *
     * @param Comment\Doc $docComment Doc comment to set
     */
    public function setDocComment(Comment\Doc $docComment);

    /**
     * Sets an attribute on a node.
     *
     * @param string $key
     * @param mixed  $value
     */
    public function setAttribute($key, $value);

    /**
     * Returns whether an attribute exists.
     *
     * @param string $key
     *
     * @return bool
     */
    public function hasAttribute($key);

    /**
     * Returns the value of an attribute.
     *
     * @param string $key
     * @param mixed  $default
     *
     * @return mixed
     */
    public function &getAttribute($key, $default = null);

    /**
     * Returns all attributes for the given node.
     *
     * @return array
     */
    public function getAttributes();
}<?php

namespace PhpParser\Node;

use PhpParser\NodeAbstract;

class Arg extends NodeAbstract
{
    /** @var Expr Value to pass */
    public $value;
    /** @var bool Whether to pass by ref */
    public $byRef;
    /** @var bool Whether to unpack the argument */
    public $unpack;

    /**
     * Constructs a function call argument node.
     *
     * @param Expr  $value      Value to pass
     * @param bool  $byRef      Whether to pass by ref
     * @param bool  $unpack     Whether to unpack the argument
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $value, $byRef = false, $unpack = false, array $attributes = array()) {
        parent::__construct($attributes);
        $this->value = $value;
        $this->byRef = $byRef;
        $this->unpack = $unpack;
    }

    public function getSubNodeNames() {
        return array('value', 'byRef', 'unpack');
    }
}
<?php

namespace PhpParser\Node;

use PhpParser\NodeAbstract;

class Const_ extends NodeAbstract
{
    /** @var string Name */
    public $name;
    /** @var Expr Value */
    public $value;

    /**
     * Constructs a const node for use in class const and const statements.
     *
     * @param string  $name       Name
     * @param Expr    $value      Value
     * @param array   $attributes Additional attributes
     */
    public function __construct($name, Expr $value, array $attributes = array()) {
        parent::__construct($attributes);
        $this->name = $name;
        $this->value = $value;
    }

    public function getSubNodeNames() {
        return array('name', 'value');
    }
}
<?php

namespace PhpParser\Node;

use PhpParser\NodeAbstract;

abstract class Expr extends NodeAbstract
{
}<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class ArrayDimFetch extends Expr
{
    /** @var Expr Variable */
    public $var;
    /** @var null|Expr Array index / dim */
    public $dim;

    /**
     * Constructs an array index fetch node.
     *
     * @param Expr      $var        Variable
     * @param null|Expr $dim        Array index / dim
     * @param array     $attributes Additional attributes
     */
    public function __construct(Expr $var, Expr $dim = null, array $attributes = array()) {
        parent::__construct($attributes);
        $this->var = $var;
        $this->dim = $dim;
    }

    public function getSubNodeNames() {
        return array('var', 'dim');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class ArrayItem extends Expr
{
    /** @var null|Expr Key */
    public $key;
    /** @var Expr Value */
    public $value;
    /** @var bool Whether to assign by reference */
    public $byRef;

    /**
     * Constructs an array item node.
     *
     * @param Expr      $value      Value
     * @param null|Expr $key        Key
     * @param bool      $byRef      Whether to assign by reference
     * @param array     $attributes Additional attributes
     */
    public function __construct(Expr $value, Expr $key = null, $byRef = false, array $attributes = array()) {
        parent::__construct($attributes);
        $this->key = $key;
        $this->value = $value;
        $this->byRef = $byRef;
    }

    public function getSubNodeNames() {
        return array('key', 'value', 'byRef');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class Array_ extends Expr
{
    // For use in "kind" attribute
    const KIND_LONG = 1;  // array() syntax
    const KIND_SHORT = 2; // [] syntax

    /** @var ArrayItem[] Items */
    public $items;

    /**
     * Constructs an array node.
     *
     * @param ArrayItem[] $items      Items of the array
     * @param array       $attributes Additional attributes
     */
    public function __construct(array $items = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->items = $items;
    }

    public function getSubNodeNames() {
        return array('items');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class Assign extends Expr
{
    /** @var Expr Variable */
    public $var;
    /** @var Expr Expression */
    public $expr;

    /**
     * Constructs an assignment node.
     *
     * @param Expr  $var        Variable
     * @param Expr  $expr       Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, Expr $expr, array $attributes = array()) {
        parent::__construct($attributes);
        $this->var = $var;
        $this->expr = $expr;
    }

    public function getSubNodeNames() {
        return array('var', 'expr');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

abstract class AssignOp extends Expr
{
    /** @var Expr Variable */
    public $var;
    /** @var Expr Expression */
    public $expr;

    /**
     * Constructs a compound assignment operation node.
     *
     * @param Expr  $var        Variable
     * @param Expr  $expr       Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, Expr $expr, array $attributes = array()) {
        parent::__construct($attributes);
        $this->var = $var;
        $this->expr = $expr;
    }

    public function getSubNodeNames() {
        return array('var', 'expr');
    }
}
<?php

namespace PhpParser\Node\Expr\AssignOp;

use PhpParser\Node\Expr\AssignOp;

class BitwiseAnd extends AssignOp
{
}<?php

namespace PhpParser\Node\Expr\AssignOp;

use PhpParser\Node\Expr\AssignOp;

class BitwiseOr extends AssignOp
{
}<?php

namespace PhpParser\Node\Expr\AssignOp;

use PhpParser\Node\Expr\AssignOp;

class BitwiseXor extends AssignOp
{
}<?php

namespace PhpParser\Node\Expr\AssignOp;

use PhpParser\Node\Expr\AssignOp;

class Concat extends AssignOp
{
}<?php

namespace PhpParser\Node\Expr\AssignOp;

use PhpParser\Node\Expr\AssignOp;

class Div extends AssignOp
{
}<?php

namespace PhpParser\Node\Expr\AssignOp;

use PhpParser\Node\Expr\AssignOp;

class Minus extends AssignOp
{
}<?php

namespace PhpParser\Node\Expr\AssignOp;

use PhpParser\Node\Expr\AssignOp;

class Mod extends AssignOp
{
}<?php

namespace PhpParser\Node\Expr\AssignOp;

use PhpParser\Node\Expr\AssignOp;

class Mul extends AssignOp
{
}<?php

namespace PhpParser\Node\Expr\AssignOp;

use PhpParser\Node\Expr\AssignOp;

class Plus extends AssignOp
{
}<?php

namespace PhpParser\Node\Expr\AssignOp;

use PhpParser\Node\Expr\AssignOp;

class Pow extends AssignOp
{
}<?php

namespace PhpParser\Node\Expr\AssignOp;

use PhpParser\Node\Expr\AssignOp;

class ShiftLeft extends AssignOp
{
}<?php

namespace PhpParser\Node\Expr\AssignOp;

use PhpParser\Node\Expr\AssignOp;

class ShiftRight extends AssignOp
{
}<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class AssignRef extends Expr
{
    /** @var Expr Variable reference is assigned to */
    public $var;
    /** @var Expr Variable which is referenced */
    public $expr;

    /**
     * Constructs an assignment node.
     *
     * @param Expr  $var        Variable
     * @param Expr  $expr       Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, Expr $expr, array $attributes = array()) {
        parent::__construct($attributes);
        $this->var = $var;
        $this->expr = $expr;
    }

    public function getSubNodeNames() {
        return array('var', 'expr');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

abstract class BinaryOp extends Expr
{
    /** @var Expr The left hand side expression */
    public $left;
    /** @var Expr The right hand side expression */
    public $right;

    /**
     * Constructs a bitwise and node.
     *
     * @param Expr  $left       The left hand side expression
     * @param Expr  $right      The right hand side expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $left, Expr $right, array $attributes = array()) {
        parent::__construct($attributes);
        $this->left = $left;
        $this->right = $right;
    }

    public function getSubNodeNames() {
        return array('left', 'right');
    }
}
<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class BitwiseAnd extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class BitwiseOr extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class BitwiseXor extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class BooleanAnd extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class BooleanOr extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class Coalesce extends BinaryOp
{
}
<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class Concat extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class Div extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class Equal extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class Greater extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class GreaterOrEqual extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class Identical extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class LogicalAnd extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class LogicalOr extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class LogicalXor extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class Minus extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class Mod extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class Mul extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class NotEqual extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class NotIdentical extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class Plus extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class Pow extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class ShiftLeft extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class ShiftRight extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class Smaller extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class SmallerOrEqual extends BinaryOp
{
}<?php

namespace PhpParser\Node\Expr\BinaryOp;

use PhpParser\Node\Expr\BinaryOp;

class Spaceship extends BinaryOp
{
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class BitwiseNot extends Expr
{
    /** @var Expr Expression */
    public $expr;

    /**
     * Constructs a bitwise not node.
     *
     * @param Expr  $expr       Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = array()) {
        parent::__construct($attributes);
        $this->expr = $expr;
    }

    public function getSubNodeNames() {
        return array('expr');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class BooleanNot extends Expr
{
    /** @var Expr Expression */
    public $expr;

    /**
     * Constructs a boolean not node.
     *
     * @param Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = array()) {
        parent::__construct($attributes);
        $this->expr = $expr;
    }

    public function getSubNodeNames() {
        return array('expr');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

abstract class Cast extends Expr
{
    /** @var Expr Expression */
    public $expr;

    /**
     * Constructs a cast node.
     *
     * @param Expr  $expr       Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = array()) {
        parent::__construct($attributes);
        $this->expr = $expr;
    }

    public function getSubNodeNames() {
        return array('expr');
    }
}
<?php

namespace PhpParser\Node\Expr\Cast;

use PhpParser\Node\Expr\Cast;

class Array_ extends Cast
{
}<?php

namespace PhpParser\Node\Expr\Cast;

use PhpParser\Node\Expr\Cast;

class Bool_ extends Cast
{
}
<?php

namespace PhpParser\Node\Expr\Cast;

use PhpParser\Node\Expr\Cast;

class Double extends Cast
{
}
<?php

namespace PhpParser\Node\Expr\Cast;

use PhpParser\Node\Expr\Cast;

class Int_ extends Cast
{
}
<?php

namespace PhpParser\Node\Expr\Cast;

use PhpParser\Node\Expr\Cast;

class Object_ extends Cast
{
}
<?php

namespace PhpParser\Node\Expr\Cast;

use PhpParser\Node\Expr\Cast;

class String_ extends Cast
{
}
<?php

namespace PhpParser\Node\Expr\Cast;

use PhpParser\Node\Expr\Cast;

class Unset_ extends Cast
{
}<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;
use PhpParser\Node\Name;

class ClassConstFetch extends Expr
{
    /** @var Name|Expr Class name */
    public $class;
    /** @var string|Error Constant name */
    public $name;

    /**
     * Constructs a class const fetch node.
     *
     * @param Name|Expr    $class      Class name
     * @param string|Error $name       Constant name
     * @param array        $attributes Additional attributes
     */
    public function __construct($class, $name, array $attributes = array()) {
        parent::__construct($attributes);
        $this->class = $class;
        $this->name = $name;
    }

    public function getSubNodeNames() {
        return array('class', 'name');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class Clone_ extends Expr
{
    /** @var Expr Expression */
    public $expr;

    /**
     * Constructs a clone node.
     *
     * @param Expr  $expr       Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = array()) {
        parent::__construct($attributes);
        $this->expr = $expr;
    }

    public function getSubNodeNames() {
        return array('expr');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\FunctionLike;

class Closure extends Expr implements FunctionLike
{
    /** @var bool Whether the closure is static */
    public $static;
    /** @var bool Whether to return by reference */
    public $byRef;
    /** @var Node\Param[] Parameters */
    public $params;
    /** @var ClosureUse[] use()s */
    public $uses;
    /** @var null|string|Node\Name|Node\NullableType Return type */
    public $returnType;
    /** @var Node[] Statements */
    public $stmts;

    /**
     * Constructs a lambda function node.
     *
     * @param array $subNodes   Array of the following optional subnodes:
     *                          'static'     => false  : Whether the closure is static
     *                          'byRef'      => false  : Whether to return by reference
     *                          'params'     => array(): Parameters
     *                          'uses'       => array(): use()s
     *                          'returnType' => null   : Return type
     *                          'stmts'      => array(): Statements
     * @param array $attributes Additional attributes
     */
    public function __construct(array $subNodes = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->static = isset($subNodes['static']) ? $subNodes['static'] : false;
        $this->byRef = isset($subNodes['byRef']) ? $subNodes['byRef'] : false;
        $this->params = isset($subNodes['params']) ? $subNodes['params'] : array();
        $this->uses = isset($subNodes['uses']) ? $subNodes['uses'] : array();
        $this->returnType = isset($subNodes['returnType']) ? $subNodes['returnType'] : null;
        $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array();
    }

    public function getSubNodeNames() {
        return array('static', 'byRef', 'params', 'uses', 'returnType', 'stmts');
    }

    public function returnsByRef() {
        return $this->byRef;
    }

    public function getParams() {
        return $this->params;
    }

    public function getReturnType() {
        return $this->returnType;
    }

    public function getStmts() {
        return $this->stmts;
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class ClosureUse extends Expr
{
    /** @var string Name of variable */
    public $var;
    /** @var bool Whether to use by reference */
    public $byRef;

    /**
     * Constructs a closure use node.
     *
     * @param string      $var        Name of variable
     * @param bool        $byRef      Whether to use by reference
     * @param array       $attributes Additional attributes
     */
    public function __construct($var, $byRef = false, array $attributes = array()) {
        parent::__construct($attributes);
        $this->var = $var;
        $this->byRef = $byRef;
    }

    public function getSubNodeNames() {
        return array('var', 'byRef');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;
use PhpParser\Node\Name;

class ConstFetch extends Expr
{
    /** @var Name Constant name */
    public $name;

    /**
     * Constructs a const fetch node.
     *
     * @param Name  $name       Constant name
     * @param array $attributes Additional attributes
     */
    public function __construct(Name $name, array $attributes = array()) {
        parent::__construct($attributes);
        $this->name = $name;
    }

    public function getSubNodeNames() {
        return array('name');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class Empty_ extends Expr
{
    /** @var Expr Expression */
    public $expr;

    /**
     * Constructs an empty() node.
     *
     * @param Expr  $expr       Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = array()) {
        parent::__construct($attributes);
        $this->expr = $expr;
    }

    public function getSubNodeNames() {
        return array('expr');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

/**
 * Error node used during parsing with error recovery.
 *
 * An error node may be placed at a position where an expression is required, but an error occurred.
 * Error nodes will not be present if the parser is run in throwOnError mode (the default).
 */
class Error extends Expr
{
    /**
     * Constructs an error node.
     *
     * @param array $attributes Additional attributes
     */
    public function __construct(array $attributes = array()) {
        parent::__construct($attributes);
    }

    public function getSubNodeNames() {
        return array();
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class ErrorSuppress extends Expr
{
    /** @var Expr Expression */
    public $expr;

    /**
     * Constructs an error suppress node.
     *
     * @param Expr  $expr       Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = array()) {
        parent::__construct($attributes);
        $this->expr = $expr;
    }

    public function getSubNodeNames() {
        return array('expr');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class Eval_ extends Expr
{
    /** @var Expr Expression */
    public $expr;

    /**
     * Constructs an eval() node.
     *
     * @param Expr  $expr       Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = array()) {
        parent::__construct($attributes);
        $this->expr = $expr;
    }

    public function getSubNodeNames() {
        return array('expr');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class Exit_ extends Expr
{
    /* For use in "kind" attribute */
    const KIND_EXIT = 1;
    const KIND_DIE = 2;

    /** @var null|Expr Expression */
    public $expr;

    /**
     * Constructs an exit() node.
     *
     * @param null|Expr $expr       Expression
     * @param array                    $attributes Additional attributes
     */
    public function __construct(Expr $expr = null, array $attributes = array()) {
        parent::__construct($attributes);
        $this->expr = $expr;
    }

    public function getSubNodeNames() {
        return array('expr');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node;
use PhpParser\Node\Expr;

class FuncCall extends Expr
{
    /** @var Node\Name|Expr Function name */
    public $name;
    /** @var Node\Arg[] Arguments */
    public $args;

    /**
     * Constructs a function call node.
     *
     * @param Node\Name|Expr $name       Function name
     * @param Node\Arg[]                    $args       Arguments
     * @param array                                   $attributes Additional attributes
     */
    public function __construct($name, array $args = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->name = $name;
        $this->args = $args;
    }

    public function getSubNodeNames() {
        return array('name', 'args');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class Include_ extends Expr
{
    const TYPE_INCLUDE      = 1;
    const TYPE_INCLUDE_ONCE = 2;
    const TYPE_REQUIRE      = 3;
    const TYPE_REQUIRE_ONCE = 4;

    /** @var Expr Expression */
    public $expr;
    /** @var int Type of include */
    public $type;

    /**
     * Constructs an include node.
     *
     * @param Expr  $expr       Expression
     * @param int   $type       Type of include
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, $type, array $attributes = array()) {
        parent::__construct($attributes);
        $this->expr = $expr;
        $this->type = $type;
    }

    public function getSubNodeNames() {
        return array('expr', 'type');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;
use PhpParser\Node\Name;

class Instanceof_ extends Expr
{
    /** @var Expr Expression */
    public $expr;
    /** @var Name|Expr Class name */
    public $class;

    /**
     * Constructs an instanceof check node.
     *
     * @param Expr      $expr       Expression
     * @param Name|Expr $class      Class name
     * @param array     $attributes Additional attributes
     */
    public function __construct(Expr $expr, $class, array $attributes = array()) {
        parent::__construct($attributes);
        $this->expr = $expr;
        $this->class = $class;
    }

    public function getSubNodeNames() {
        return array('expr', 'class');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class Isset_ extends Expr
{
    /** @var Expr[] Variables */
    public $vars;

    /**
     * Constructs an array node.
     *
     * @param Expr[] $vars       Variables
     * @param array  $attributes Additional attributes
     */
    public function __construct(array $vars, array $attributes = array()) {
        parent::__construct($attributes);
        $this->vars = $vars;
    }

    public function getSubNodeNames() {
        return array('vars');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class List_ extends Expr
{
    /** @var ArrayItem[] List of items to assign to */
    public $items;

    /**
     * Constructs a list() destructuring node.
     *
     * @param ArrayItem[] $items      List of items to assign to
     * @param array       $attributes Additional attributes
     */
    public function __construct(array $items, array $attributes = array()) {
        parent::__construct($attributes);
        $this->items = $items;
    }

    public function getSubNodeNames() {
        return array('items');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Arg;
use PhpParser\Node\Expr;

class MethodCall extends Expr
{
    /** @var Expr Variable holding object */
    public $var;
    /** @var string|Expr Method name */
    public $name;
    /** @var Arg[] Arguments */
    public $args;

    /**
     * Constructs a function call node.
     *
     * @param Expr        $var        Variable holding object
     * @param string|Expr $name       Method name
     * @param Arg[]       $args       Arguments
     * @param array       $attributes Additional attributes
     */
    public function __construct(Expr $var, $name, array $args = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->var = $var;
        $this->name = $name;
        $this->args = $args;
    }

    public function getSubNodeNames() {
        return array('var', 'name', 'args');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node;
use PhpParser\Node\Expr;

class New_ extends Expr
{
    /** @var Node\Name|Expr|Node\Stmt\Class_ Class name */
    public $class;
    /** @var Node\Arg[] Arguments */
    public $args;

    /**
     * Constructs a function call node.
     *
     * @param Node\Name|Expr|Node\Stmt\Class_ $class      Class name (or class node for anonymous classes)
     * @param Node\Arg[]                      $args       Arguments
     * @param array                           $attributes Additional attributes
     */
    public function __construct($class, array $args = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->class = $class;
        $this->args = $args;
    }

    public function getSubNodeNames() {
        return array('class', 'args');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class PostDec extends Expr
{
    /** @var Expr Variable */
    public $var;

    /**
     * Constructs a post decrement node.
     *
     * @param Expr  $var        Variable
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, array $attributes = array()) {
        parent::__construct($attributes);
        $this->var = $var;
    }

    public function getSubNodeNames() {
        return array('var');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class PostInc extends Expr
{
    /** @var Expr Variable */
    public $var;

    /**
     * Constructs a post increment node.
     *
     * @param Expr  $var        Variable
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, array $attributes = array()) {
        parent::__construct($attributes);
        $this->var = $var;
    }

    public function getSubNodeNames() {
        return array('var');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class PreDec extends Expr
{
    /** @var Expr Variable */
    public $var;

    /**
     * Constructs a pre decrement node.
     *
     * @param Expr  $var        Variable
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, array $attributes = array()) {
        parent::__construct($attributes);
        $this->var = $var;
    }

    public function getSubNodeNames() {
        return array('var');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class PreInc extends Expr
{
    /** @var Expr Variable */
    public $var;

    /**
     * Constructs a pre increment node.
     *
     * @param Expr  $var        Variable
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, array $attributes = array()) {
        parent::__construct($attributes);
        $this->var = $var;
    }

    public function getSubNodeNames() {
        return array('var');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class Print_ extends Expr
{
    /** @var Expr Expression */
    public $expr;

    /**
     * Constructs an print() node.
     *
     * @param Expr  $expr       Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = array()) {
        parent::__construct($attributes);
        $this->expr = $expr;
    }

    public function getSubNodeNames() {
        return array('expr');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class PropertyFetch extends Expr
{
    /** @var Expr Variable holding object */
    public $var;
    /** @var string|Expr Property name */
    public $name;

    /**
     * Constructs a function call node.
     *
     * @param Expr        $var        Variable holding object
     * @param string|Expr $name       Property name
     * @param array       $attributes Additional attributes
     */
    public function __construct(Expr $var, $name, array $attributes = array()) {
        parent::__construct($attributes);
        $this->var = $var;
        $this->name = $name;
    }

    public function getSubNodeNames() {
        return array('var', 'name');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class ShellExec extends Expr
{
    /** @var array Encapsed string array */
    public $parts;

    /**
     * Constructs a shell exec (backtick) node.
     *
     * @param array $parts      Encapsed string array
     * @param array $attributes Additional attributes
     */
    public function __construct(array $parts, array $attributes = array()) {
        parent::__construct($attributes);
        $this->parts = $parts;
    }

    public function getSubNodeNames() {
        return array('parts');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node;
use PhpParser\Node\Expr;

class StaticCall extends Expr
{
    /** @var Node\Name|Expr Class name */
    public $class;
    /** @var string|Expr Method name */
    public $name;
    /** @var Node\Arg[] Arguments */
    public $args;

    /**
     * Constructs a static method call node.
     *
     * @param Node\Name|Expr $class      Class name
     * @param string|Expr    $name       Method name
     * @param Node\Arg[]     $args       Arguments
     * @param array          $attributes Additional attributes
     */
    public function __construct($class, $name, array $args = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->class = $class;
        $this->name = $name;
        $this->args = $args;
    }

    public function getSubNodeNames() {
        return array('class', 'name', 'args');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;
use PhpParser\Node\Name;

class StaticPropertyFetch extends Expr
{
    /** @var Name|Expr Class name */
    public $class;
    /** @var string|Expr Property name */
    public $name;

    /**
     * Constructs a static property fetch node.
     *
     * @param Name|Expr   $class      Class name
     * @param string|Expr $name       Property name
     * @param array       $attributes Additional attributes
     */
    public function __construct($class, $name, array $attributes = array()) {
        parent::__construct($attributes);
        $this->class = $class;
        $this->name = $name;
    }

    public function getSubNodeNames() {
        return array('class', 'name');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class Ternary extends Expr
{
    /** @var Expr Condition */
    public $cond;
    /** @var null|Expr Expression for true */
    public $if;
    /** @var Expr Expression for false */
    public $else;

    /**
     * Constructs a ternary operator node.
     *
     * @param Expr      $cond       Condition
     * @param null|Expr $if         Expression for true
     * @param Expr      $else       Expression for false
     * @param array                    $attributes Additional attributes
     */
    public function __construct(Expr $cond, $if, Expr $else, array $attributes = array()) {
        parent::__construct($attributes);
        $this->cond = $cond;
        $this->if = $if;
        $this->else = $else;
    }

    public function getSubNodeNames() {
        return array('cond', 'if', 'else');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class UnaryMinus extends Expr
{
    /** @var Expr Expression */
    public $expr;

    /**
     * Constructs a unary minus node.
     *
     * @param Expr  $expr       Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = array()) {
        parent::__construct($attributes);
        $this->expr = $expr;
    }

    public function getSubNodeNames() {
        return array('expr');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class UnaryPlus extends Expr
{
    /** @var Expr Expression */
    public $expr;

    /**
     * Constructs a unary plus node.
     *
     * @param Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = array()) {
        parent::__construct($attributes);
        $this->expr = $expr;
    }

    public function getSubNodeNames() {
        return array('expr');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class Variable extends Expr
{
    /** @var string|Expr Name */
    public $name;

    /**
     * Constructs a variable node.
     *
     * @param string|Expr $name       Name
     * @param array                      $attributes Additional attributes
     */
    public function __construct($name, array $attributes = array()) {
        parent::__construct($attributes);
        $this->name = $name;
    }

    public function getSubNodeNames() {
        return array('name');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class YieldFrom extends Expr
{
    /** @var Expr Expression to yield from */
    public $expr;

    /**
     * Constructs an "yield from" node.
     *
     * @param Expr  $expr       Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = array()) {
        parent::__construct($attributes);
        $this->expr = $expr;
    }

    public function getSubNodeNames() {
        return array('expr');
    }
}
<?php

namespace PhpParser\Node\Expr;

use PhpParser\Node\Expr;

class Yield_ extends Expr
{
    /** @var null|Expr Key expression */
    public $key;
    /** @var null|Expr Value expression */
    public $value;

    /**
     * Constructs a yield expression node.
     *
     * @param null|Expr $value      Value expression
     * @param null|Expr $key        Key expression
     * @param array     $attributes Additional attributes
     */
    public function __construct(Expr $value = null, Expr $key = null, array $attributes = array()) {
        parent::__construct($attributes);
        $this->key = $key;
        $this->value = $value;
    }

    public function getSubNodeNames() {
        return array('key', 'value');
    }
}
<?php

namespace PhpParser\Node;

use PhpParser\Node;

interface FunctionLike extends Node
{
    /**
     * Whether to return by reference
     *
     * @return bool
     */
    public function returnsByRef();

    /**
     * List of parameters
     *
     * @return Node\Param[]
     */
    public function getParams();

    /**
     * Get the declared return type or null
     * 
     * @return null|string|Node\Name|Node\NullableType
     */
    public function getReturnType();

    /**
     * The function body
     *
     * @return Node\Stmt[]
     */
    public function getStmts();
}
<?php

namespace PhpParser\Node;

use PhpParser\NodeAbstract;

class Name extends NodeAbstract
{
    /**
     * @var string[] Parts of the name
     */
    public $parts;

    /**
     * Constructs a name node.
     *
     * @param string|array|self $name       Name as string, part array or Name instance (copy ctor)
     * @param array             $attributes Additional attributes
     */
    public function __construct($name, array $attributes = array()) {
        parent::__construct($attributes);
        $this->parts = self::prepareName($name);
    }

    public function getSubNodeNames() {
        return array('parts');
    }

    /**
     * Gets the first part of the name, i.e. everything before the first namespace separator.
     *
     * @return string First part of the name
     */
    public function getFirst() {
        return $this->parts[0];
    }

    /**
     * Gets the last part of the name, i.e. everything after the last namespace separator.
     *
     * @return string Last part of the name
     */
    public function getLast() {
        return $this->parts[count($this->parts) - 1];
    }

    /**
     * Checks whether the name is unqualified. (E.g. Name)
     *
     * @return bool Whether the name is unqualified
     */
    public function isUnqualified() {
        return 1 == count($this->parts);
    }

    /**
     * Checks whether the name is qualified. (E.g. Name\Name)
     *
     * @return bool Whether the name is qualified
     */
    public function isQualified() {
        return 1 < count($this->parts);
    }

    /**
     * Checks whether the name is fully qualified. (E.g. \Name)
     *
     * @return bool Whether the name is fully qualified
     */
    public function isFullyQualified() {
        return false;
    }

    /**
     * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
     *
     * @return bool Whether the name is relative
     */
    public function isRelative() {
        return false;
    }

    /**
     * Returns a string representation of the name by imploding the namespace parts with the
     * namespace separator.
     *
     * @return string String representation
     */
    public function toString() {
        return implode('\\', $this->parts);
    }

    /**
     * Returns a string representation of the name by imploding the namespace parts with the
     * namespace separator.
     *
     * @return string String representation
     */
    public function __toString() {
        return implode('\\', $this->parts);
    }

    /**
     * Gets a slice of a name (similar to array_slice).
     *
     * This method returns a new instance of the same type as the original and with the same
     * attributes.
     *
     * If the slice is empty, null is returned. The null value will be correctly handled in
     * concatenations using concat().
     *
     * Offset and length have the same meaning as in array_slice().
     *
     * @param int      $offset Offset to start the slice at (may be negative)
     * @param int|null $length Length of the slice (may be negative)
     *
     * @return static|null Sliced name
     */
    public function slice($offset, $length = null) {
        $numParts = count($this->parts);

        $realOffset = $offset < 0 ? $offset + $numParts : $offset;
        if ($realOffset < 0 || $realOffset > $numParts) {
            throw new \OutOfBoundsException(sprintf('Offset %d is out of bounds', $offset));
        }

        if (null === $length) {
            $realLength = $numParts - $realOffset;
        } else {
            $realLength = $length < 0 ? $length + $numParts - $realOffset : $length;
            if ($realLength < 0 || $realLength > $numParts) {
                throw new \OutOfBoundsException(sprintf('Length %d is out of bounds', $length));
            }
        }

        if ($realLength === 0) {
            // Empty slice is represented as null
            return null;
        }

        return new static(array_slice($this->parts, $realOffset, $realLength), $this->attributes);
    }

    /**
     * Concatenate two names, yielding a new Name instance.
     *
     * The type of the generated instance depends on which class this method is called on, for
     * example Name\FullyQualified::concat() will yield a Name\FullyQualified instance.
     *
     * If one of the arguments is null, a new instance of the other name will be returned. If both
     * arguments are null, null will be returned. As such, writing
     *     Name::concat($namespace, $shortName)
     * where $namespace is a Name node or null will work as expected.
     *
     * @param string|array|self|null $name1      The first name
     * @param string|array|self|null $name2      The second name
     * @param array                  $attributes Attributes to assign to concatenated name
     *
     * @return static|null Concatenated name
     */
    public static function concat($name1, $name2, array $attributes = []) {
        if (null === $name1 && null === $name2) {
            return null;
        } elseif (null === $name1) {
            return new static(self::prepareName($name2), $attributes);
        } else if (null === $name2) {
            return new static(self::prepareName($name1), $attributes);
        } else {
            return new static(
                array_merge(self::prepareName($name1), self::prepareName($name2)), $attributes
            );
        }
    }

    /**
     * Prepares a (string, array or Name node) name for use in name changing methods by converting
     * it to an array.
     *
     * @param string|array|self $name Name to prepare
     *
     * @return array Prepared name
     */
    private static function prepareName($name) {
        if (\is_string($name)) {
            return explode('\\', $name);
        } elseif (\is_array($name)) {
            return $name;
        } elseif ($name instanceof self) {
            return $name->parts;
        }

        throw new \InvalidArgumentException(
            'Expected string, array of parts or Name instance'
        );
    }
}
<?php

namespace PhpParser\Node\Name;

class FullyQualified extends \PhpParser\Node\Name
{
    /**
     * Checks whether the name is unqualified. (E.g. Name)
     *
     * @return bool Whether the name is unqualified
     */
    public function isUnqualified() {
        return false;
    }

    /**
     * Checks whether the name is qualified. (E.g. Name\Name)
     *
     * @return bool Whether the name is qualified
     */
    public function isQualified() {
        return false;
    }

    /**
     * Checks whether the name is fully qualified. (E.g. \Name)
     *
     * @return bool Whether the name is fully qualified
     */
    public function isFullyQualified() {
        return true;
    }

    /**
     * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
     *
     * @return bool Whether the name is relative
     */
    public function isRelative() {
        return false;
    }
}<?php

namespace PhpParser\Node\Name;

class Relative extends \PhpParser\Node\Name
{
    /**
     * Checks whether the name is unqualified. (E.g. Name)
     *
     * @return bool Whether the name is unqualified
     */
    public function isUnqualified() {
        return false;
    }

    /**
     * Checks whether the name is qualified. (E.g. Name\Name)
     *
     * @return bool Whether the name is qualified
     */
    public function isQualified() {
        return false;
    }

    /**
     * Checks whether the name is fully qualified. (E.g. \Name)
     *
     * @return bool Whether the name is fully qualified
     */
    public function isFullyQualified() {
        return false;
    }

    /**
     * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
     *
     * @return bool Whether the name is relative
     */
    public function isRelative() {
        return true;
    }
}<?php

namespace PhpParser\Node;

use PhpParser\NodeAbstract;

class NullableType extends NodeAbstract
{
    /** @var string|Name Type */
    public $type;

    /**
     * Constructs a nullable type (wrapping another type).
     *
     * @param string|Name $type       Type
     * @param array       $attributes Additional attributes
     */
    public function __construct($type, array $attributes = array()) {
        parent::__construct($attributes);
        $this->type = $type;
    }

    public function getSubNodeNames() {
        return array('type');
    }
}
<?php

namespace PhpParser\Node;

use PhpParser\NodeAbstract;

class Param extends NodeAbstract
{
    /** @var null|string|Name|NullableType Typehint */
    public $type;
    /** @var bool Whether parameter is passed by reference */
    public $byRef;
    /** @var bool Whether this is a variadic argument */
    public $variadic;
    /** @var string Name */
    public $name;
    /** @var null|Expr Default value */
    public $default;

    /**
     * Constructs a parameter node.
     *
     * @param string                        $name       Name
     * @param null|Expr                     $default    Default value
     * @param null|string|Name|NullableType $type       Typehint
     * @param bool                          $byRef      Whether is passed by reference
     * @param bool                          $variadic   Whether this is a variadic argument
     * @param array                         $attributes Additional attributes
     */
    public function __construct($name, Expr $default = null, $type = null, $byRef = false, $variadic = false, array $attributes = array()) {
        parent::__construct($attributes);
        $this->type = $type;
        $this->byRef = $byRef;
        $this->variadic = $variadic;
        $this->name = $name;
        $this->default = $default;
    }

    public function getSubNodeNames() {
        return array('type', 'byRef', 'variadic', 'name', 'default');
    }
}
<?php

namespace PhpParser\Node;

abstract class Scalar extends Expr
{
}<?php

namespace PhpParser\Node\Scalar;

use PhpParser\Node\Scalar;

class DNumber extends Scalar
{
    /** @var float Number value */
    public $value;

    /**
     * Constructs a float number scalar node.
     *
     * @param float $value      Value of the number
     * @param array $attributes Additional attributes
     */
    public function __construct($value, array $attributes = array()) {
        parent::__construct($attributes);
        $this->value = $value;
    }

    public function getSubNodeNames() {
        return array('value');
    }

    /**
     * @internal
     *
     * Parses a DNUMBER token like PHP would.
     *
     * @param string $str A string number
     *
     * @return float The parsed number
     */
    public static function parse($str) {
        // if string contains any of .eE just cast it to float
        if (false !== strpbrk($str, '.eE')) {
            return (float) $str;
        }

        // otherwise it's an integer notation that overflowed into a float
        // if it starts with 0 it's one of the special integer notations
        if ('0' === $str[0]) {
            // hex
            if ('x' === $str[1] || 'X' === $str[1]) {
                return hexdec($str);
            }

            // bin
            if ('b' === $str[1] || 'B' === $str[1]) {
                return bindec($str);
            }

            // oct
            // substr($str, 0, strcspn($str, '89')) cuts the string at the first invalid digit (8 or 9)
            // so that only the digits before that are used
            return octdec(substr($str, 0, strcspn($str, '89')));
        }

        // dec
        return (float) $str;
    }
}
<?php

namespace PhpParser\Node\Scalar;

use PhpParser\Node\Expr;
use PhpParser\Node\Scalar;

class Encapsed extends Scalar
{
    /** @var Expr[] list of string parts */
    public $parts;

    /**
     * Constructs an encapsed string node.
     *
     * @param array $parts      Encaps list
     * @param array $attributes Additional attributes
     */
    public function __construct(array $parts, array $attributes = array()) {
        parent::__construct($attributes);
        $this->parts = $parts;
    }

    public function getSubNodeNames() {
        return array('parts');
    }
}
<?php

namespace PhpParser\Node\Scalar;

use PhpParser\Node\Scalar;

class EncapsedStringPart extends Scalar
{
    /** @var string String value */
    public $value;

    /**
     * Constructs a node representing a string part of an encapsed string.
     *
     * @param string $value      String value
     * @param array  $attributes Additional attributes
     */
    public function __construct($value, array $attributes = array()) {
        parent::__construct($attributes);
        $this->value = $value;
    }

    public function getSubNodeNames() {
        return array('value');
    }
}
<?php

namespace PhpParser\Node\Scalar;

use PhpParser\Error;
use PhpParser\Node\Scalar;

class LNumber extends Scalar
{
    /* For use in "kind" attribute */
    const KIND_BIN = 2;
    const KIND_OCT = 8;
    const KIND_DEC = 10;
    const KIND_HEX = 16;

    /** @var int Number value */
    public $value;

    /**
     * Constructs an integer number scalar node.
     *
     * @param int   $value      Value of the number
     * @param array $attributes Additional attributes
     */
    public function __construct($value, array $attributes = array()) {
        parent::__construct($attributes);
        $this->value = $value;
    }

    public function getSubNodeNames() {
        return array('value');
    }

    /**
     * Constructs an LNumber node from a string number literal.
     *
     * @param string $str               String number literal (decimal, octal, hex or binary)
     * @param array  $attributes        Additional attributes
     * @param bool   $allowInvalidOctal Whether to allow invalid octal numbers (PHP 5)
     *
     * @return LNumber The constructed LNumber, including kind attribute
     */
    public static function fromString($str, array $attributes = array(), $allowInvalidOctal = false) {
        if ('0' !== $str[0] || '0' === $str) {
            $attributes['kind'] = LNumber::KIND_DEC;
            return new LNumber((int) $str, $attributes);
        }

        if ('x' === $str[1] || 'X' === $str[1]) {
            $attributes['kind'] = LNumber::KIND_HEX;
            return new LNumber(hexdec($str), $attributes);
        }

        if ('b' === $str[1] || 'B' === $str[1]) {
            $attributes['kind'] = LNumber::KIND_BIN;
            return new LNumber(bindec($str), $attributes);
        }

        if (!$allowInvalidOctal && strpbrk($str, '89')) {
            throw new Error('Invalid numeric literal', $attributes);
        }

        // use intval instead of octdec to get proper cutting behavior with malformed numbers
        $attributes['kind'] = LNumber::KIND_OCT;
        return new LNumber(intval($str, 8), $attributes);
    }
}
<?php

namespace PhpParser\Node\Scalar;

use PhpParser\Node\Scalar;

abstract class MagicConst extends Scalar
{
    /**
     * Constructs a magic constant node.
     *
     * @param array $attributes Additional attributes
     */
    public function __construct(array $attributes = array()) {
        parent::__construct($attributes);
    }

    public function getSubNodeNames() {
        return array();
    }

    /**
     * Get name of magic constant.
     *
     * @return string Name of magic constant
     */
    abstract public function getName();
}
<?php

namespace PhpParser\Node\Scalar\MagicConst;

use PhpParser\Node\Scalar\MagicConst;

class Class_ extends MagicConst
{
    public function getName() {
        return '__CLASS__';
    }
}<?php

namespace PhpParser\Node\Scalar\MagicConst;

use PhpParser\Node\Scalar\MagicConst;

class Dir extends MagicConst
{
    public function getName() {
        return '__DIR__';
    }
}<?php

namespace PhpParser\Node\Scalar\MagicConst;

use PhpParser\Node\Scalar\MagicConst;

class File extends MagicConst
{
    public function getName() {
        return '__FILE__';
    }
}<?php

namespace PhpParser\Node\Scalar\MagicConst;

use PhpParser\Node\Scalar\MagicConst;

class Function_ extends MagicConst
{
    public function getName() {
        return '__FUNCTION__';
    }
}<?php

namespace PhpParser\Node\Scalar\MagicConst;

use PhpParser\Node\Scalar\MagicConst;

class Line extends MagicConst
{
    public function getName() {
        return '__LINE__';
    }
}<?php

namespace PhpParser\Node\Scalar\MagicConst;

use PhpParser\Node\Scalar\MagicConst;

class Method extends MagicConst
{
    public function getName() {
        return '__METHOD__';
    }
}<?php

namespace PhpParser\Node\Scalar\MagicConst;

use PhpParser\Node\Scalar\MagicConst;

class Namespace_ extends MagicConst
{
    public function getName() {
        return '__NAMESPACE__';
    }
}<?php

namespace PhpParser\Node\Scalar\MagicConst;

use PhpParser\Node\Scalar\MagicConst;

class Trait_ extends MagicConst
{
    public function getName() {
        return '__TRAIT__';
    }
}<?php

namespace PhpParser\Node\Scalar;

use PhpParser\Error;
use PhpParser\Node\Scalar;

class String_ extends Scalar
{
    /* For use in "kind" attribute */
    const KIND_SINGLE_QUOTED = 1;
    const KIND_DOUBLE_QUOTED = 2;
    const KIND_HEREDOC = 3;
    const KIND_NOWDOC = 4;

    /** @var string String value */
    public $value;

    protected static $replacements = array(
        '\\' => '\\',
        '$'  =>  '$',
        'n'  => "\n",
        'r'  => "\r",
        't'  => "\t",
        'f'  => "\f",
        'v'  => "\v",
        'e'  => "\x1B",
    );

    /**
     * Constructs a string scalar node.
     *
     * @param string $value      Value of the string
     * @param array  $attributes Additional attributes
     */
    public function __construct($value, array $attributes = array()) {
        parent::__construct($attributes);
        $this->value = $value;
    }

    public function getSubNodeNames() {
        return array('value');
    }

    /**
     * @internal
     *
     * Parses a string token.
     *
     * @param string $str String token content
     * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes
     *
     * @return string The parsed string
     */
    public static function parse($str, $parseUnicodeEscape = true) {
        $bLength = 0;
        if ('b' === $str[0] || 'B' === $str[0]) {
            $bLength = 1;
        }

        if ('\'' === $str[$bLength]) {
            return str_replace(
                array('\\\\', '\\\''),
                array(  '\\',   '\''),
                substr($str, $bLength + 1, -1)
            );
        } else {
            return self::parseEscapeSequences(
                substr($str, $bLength + 1, -1), '"', $parseUnicodeEscape
            );
        }
    }

    /**
     * @internal
     *
     * Parses escape sequences in strings (all string types apart from single quoted).
     *
     * @param string      $str   String without quotes
     * @param null|string $quote Quote type
     * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes
     *
     * @return string String with escape sequences parsed
     */
    public static function parseEscapeSequences($str, $quote, $parseUnicodeEscape = true) {
        if (null !== $quote) {
            $str = str_replace('\\' . $quote, $quote, $str);
        }

        $extra = '';
        if ($parseUnicodeEscape) {
            $extra = '|u\{([0-9a-fA-F]+)\}';
        }

        return preg_replace_callback(
            '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}' . $extra . ')~',
            function($matches) {
                $str = $matches[1];

                if (isset(self::$replacements[$str])) {
                    return self::$replacements[$str];
                } elseif ('x' === $str[0] || 'X' === $str[0]) {
                    return chr(hexdec($str));
                } elseif ('u' === $str[0]) {
                    return self::codePointToUtf8(hexdec($matches[2]));
                } else {
                    return chr(octdec($str));
                }
            },
            $str
        );
    }

    private static function codePointToUtf8($num) {
        if ($num <= 0x7F) {
            return chr($num);
        }
        if ($num <= 0x7FF) {
            return chr(($num>>6) + 0xC0) . chr(($num&0x3F) + 0x80);
        }
        if ($num <= 0xFFFF) {
            return chr(($num>>12) + 0xE0) . chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80);
        }
        if ($num <= 0x1FFFFF) {
            return chr(($num>>18) + 0xF0) . chr((($num>>12)&0x3F) + 0x80)
                 . chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80);
        }
        throw new Error('Invalid UTF-8 codepoint escape sequence: Codepoint too large');
    }

    /**
     * @internal
     *
     * Parses a constant doc string.
     *
     * @param string $startToken Doc string start token content (<<<SMTHG)
     * @param string $str        String token content
     * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes
     *
     * @return string Parsed string
     */
    public static function parseDocString($startToken, $str, $parseUnicodeEscape = true) {
        // strip last newline (thanks tokenizer for sticking it into the string!)
        $str = preg_replace('~(\r\n|\n|\r)\z~', '', $str);

        // nowdoc string
        if (false !== strpos($startToken, '\'')) {
            return $str;
        }

        return self::parseEscapeSequences($str, null, $parseUnicodeEscape);
    }
}
<?php

namespace PhpParser\Node;

use PhpParser\NodeAbstract;

abstract class Stmt extends NodeAbstract
{
}<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Break_ extends Node\Stmt
{
    /** @var null|Node\Expr Number of loops to break */
    public $num;

    /**
     * Constructs a break node.
     *
     * @param null|Node\Expr $num        Number of loops to break
     * @param array          $attributes Additional attributes
     */
    public function __construct(Node\Expr $num = null, array $attributes = array()) {
        parent::__construct($attributes);
        $this->num = $num;
    }

    public function getSubNodeNames() {
        return array('num');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Case_ extends Node\Stmt
{
    /** @var null|Node\Expr $cond Condition (null for default) */
    public $cond;
    /** @var Node[] Statements */
    public $stmts;

    /**
     * Constructs a case node.
     *
     * @param null|Node\Expr $cond       Condition (null for default)
     * @param Node[]         $stmts      Statements
     * @param array          $attributes Additional attributes
     */
    public function __construct($cond, array $stmts = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->cond = $cond;
        $this->stmts = $stmts;
    }

    public function getSubNodeNames() {
        return array('cond', 'stmts');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Catch_ extends Node\Stmt
{
    /** @var Node\Name[] Types of exceptions to catch */
    public $types;
    /** @var string Variable for exception */
    public $var;
    /** @var Node[] Statements */
    public $stmts;

    /**
     * Constructs a catch node.
     *
     * @param Node\Name[] $types      Types of exceptions to catch
     * @param string      $var        Variable for exception
     * @param Node[]      $stmts      Statements
     * @param array       $attributes Additional attributes
     */
    public function __construct(array $types, $var, array $stmts = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->types = $types;
        $this->var = $var;
        $this->stmts = $stmts;
    }

    public function getSubNodeNames() {
        return array('types', 'var', 'stmts');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class ClassConst extends Node\Stmt
{
    /** @var int Modifiers */
    public $flags;
    /** @var Node\Const_[] Constant declarations */
    public $consts;

    /**
     * Constructs a class const list node.
     *
     * @param Node\Const_[] $consts     Constant declarations
     * @param int           $flags      Modifiers
     * @param array         $attributes Additional attributes
     */
    public function __construct(array $consts, $flags = 0, array $attributes = array()) {
        parent::__construct($attributes);
        $this->flags = $flags;
        $this->consts = $consts;
    }

    public function getSubNodeNames() {
        return array('flags', 'consts');
    }

    public function isPublic() {
        return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0
            || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0;
    }

    public function isProtected() {
        return (bool) ($this->flags & Class_::MODIFIER_PROTECTED);
    }

    public function isPrivate() {
        return (bool) ($this->flags & Class_::MODIFIER_PRIVATE);
    }

    public function isStatic() {
        return (bool) ($this->flags & Class_::MODIFIER_STATIC);
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

abstract class ClassLike extends Node\Stmt {
    /** @var string|null Name */
    public $name;
    /** @var Node[] Statements */
    public $stmts;

    /**
     * Gets all methods defined directly in this class/interface/trait
     *
     * @return ClassMethod[]
     */
    public function getMethods() {
        $methods = array();
        foreach ($this->stmts as $stmt) {
            if ($stmt instanceof ClassMethod) {
                $methods[] = $stmt;
            }
        }
        return $methods;
    }

    /**
     * Gets method with the given name defined directly in this class/interface/trait.
     *
     * @param string $name Name of the method (compared case-insensitively)
     *
     * @return ClassMethod|null Method node or null if the method does not exist
     */
    public function getMethod($name) {
        $lowerName = strtolower($name);
        foreach ($this->stmts as $stmt) {
            if ($stmt instanceof ClassMethod && $lowerName === strtolower($stmt->name)) {
                return $stmt;
            }
        }
        return null;
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;
use PhpParser\Node\FunctionLike;

class ClassMethod extends Node\Stmt implements FunctionLike
{
    /** @var int Flags */
    public $flags;
    /** @var bool Whether to return by reference */
    public $byRef;
    /** @var string Name */
    public $name;
    /** @var Node\Param[] Parameters */
    public $params;
    /** @var null|string|Node\Name|Node\NullableType Return type */
    public $returnType;
    /** @var Node[]|null Statements */
    public $stmts;

    /** @deprecated Use $flags instead */
    public $type;

    /**
     * Constructs a class method node.
     *
     * @param string      $name       Name
     * @param array       $subNodes   Array of the following optional subnodes:
     *                                'flags       => MODIFIER_PUBLIC: Flags
     *                                'byRef'      => false          : Whether to return by reference
     *                                'params'     => array()        : Parameters
     *                                'returnType' => null           : Return type
     *                                'stmts'      => array()        : Statements
     * @param array       $attributes Additional attributes
     */
    public function __construct($name, array $subNodes = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->flags = isset($subNodes['flags']) ? $subNodes['flags']
            : (isset($subNodes['type']) ? $subNodes['type'] : 0);
        $this->type = $this->flags;
        $this->byRef = isset($subNodes['byRef'])  ? $subNodes['byRef']  : false;
        $this->name = $name;
        $this->params = isset($subNodes['params']) ? $subNodes['params'] : array();
        $this->returnType = isset($subNodes['returnType']) ? $subNodes['returnType'] : null;
        $this->stmts = array_key_exists('stmts', $subNodes) ? $subNodes['stmts'] : array();
    }

    public function getSubNodeNames() {
        return array('flags', 'byRef', 'name', 'params', 'returnType', 'stmts');
    }

    public function returnsByRef() {
        return $this->byRef;
    }

    public function getParams() {
        return $this->params;
    }

    public function getReturnType() {
        return $this->returnType;
    }

    public function getStmts() {
        return $this->stmts;
    }

    public function isPublic() {
        return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0
            || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0;
    }

    public function isProtected() {
        return (bool) ($this->flags & Class_::MODIFIER_PROTECTED);
    }

    public function isPrivate() {
        return (bool) ($this->flags & Class_::MODIFIER_PRIVATE);
    }

    public function isAbstract() {
        return (bool) ($this->flags & Class_::MODIFIER_ABSTRACT);
    }

    public function isFinal() {
        return (bool) ($this->flags & Class_::MODIFIER_FINAL);
    }

    public function isStatic() {
        return (bool) ($this->flags & Class_::MODIFIER_STATIC);
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Error;
use PhpParser\Node;

class Class_ extends ClassLike
{
    const MODIFIER_PUBLIC    =  1;
    const MODIFIER_PROTECTED =  2;
    const MODIFIER_PRIVATE   =  4;
    const MODIFIER_STATIC    =  8;
    const MODIFIER_ABSTRACT  = 16;
    const MODIFIER_FINAL     = 32;

    const VISIBILITY_MODIFIER_MASK = 7; // 1 | 2 | 4
    /** @deprecated */
    const VISIBILITY_MODIFER_MASK = self::VISIBILITY_MODIFIER_MASK;

    /** @var int Type */
    public $flags;
    /** @var null|Node\Name Name of extended class */
    public $extends;
    /** @var Node\Name[] Names of implemented interfaces */
    public $implements;

    /** @deprecated Use $flags instead */
    public $type;

    protected static $specialNames = array(
        'self'   => true,
        'parent' => true,
        'static' => true,
    );

    /**
     * Constructs a class node.
     *
     * @param string|null $name       Name
     * @param array       $subNodes   Array of the following optional subnodes:
     *                                'flags'      => 0      : Flags
     *                                'extends'    => null   : Name of extended class
     *                                'implements' => array(): Names of implemented interfaces
     *                                'stmts'      => array(): Statements
     * @param array       $attributes Additional attributes
     */
    public function __construct($name, array $subNodes = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->flags = isset($subNodes['flags']) ? $subNodes['flags']
            : (isset($subNodes['type']) ? $subNodes['type'] : 0);
        $this->type = $this->flags;
        $this->name = $name;
        $this->extends = isset($subNodes['extends']) ? $subNodes['extends'] : null;
        $this->implements = isset($subNodes['implements']) ? $subNodes['implements'] : array();
        $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array();
    }

    public function getSubNodeNames() {
        return array('flags', 'name', 'extends', 'implements', 'stmts');
    }

    public function isAbstract() {
        return (bool) ($this->flags & self::MODIFIER_ABSTRACT);
    }

    public function isFinal() {
        return (bool) ($this->flags & self::MODIFIER_FINAL);
    }

    public function isAnonymous() {
        return null === $this->name;
    }

    /**
     * @internal
     */
    public static function verifyModifier($a, $b) {
        if ($a & self::VISIBILITY_MODIFIER_MASK && $b & self::VISIBILITY_MODIFIER_MASK) {
            throw new Error('Multiple access type modifiers are not allowed');
        }

        if ($a & self::MODIFIER_ABSTRACT && $b & self::MODIFIER_ABSTRACT) {
            throw new Error('Multiple abstract modifiers are not allowed');
        }

        if ($a & self::MODIFIER_STATIC && $b & self::MODIFIER_STATIC) {
            throw new Error('Multiple static modifiers are not allowed');
        }

        if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) {
            throw new Error('Multiple final modifiers are not allowed');
        }

        if ($a & 48 && $b & 48) {
            throw new Error('Cannot use the final modifier on an abstract class member');
        }
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Const_ extends Node\Stmt
{
    /** @var Node\Const_[] Constant declarations */
    public $consts;

    /**
     * Constructs a const list node.
     *
     * @param Node\Const_[] $consts     Constant declarations
     * @param array         $attributes Additional attributes
     */
    public function __construct(array $consts, array $attributes = array()) {
        parent::__construct($attributes);
        $this->consts = $consts;
    }

    public function getSubNodeNames() {
        return array('consts');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Continue_ extends Node\Stmt
{
    /** @var null|Node\Expr Number of loops to continue */
    public $num;

    /**
     * Constructs a continue node.
     *
     * @param null|Node\Expr $num        Number of loops to continue
     * @param array          $attributes Additional attributes
     */
    public function __construct(Node\Expr $num = null, array $attributes = array()) {
        parent::__construct($attributes);
        $this->num = $num;
    }

    public function getSubNodeNames() {
        return array('num');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class DeclareDeclare extends Node\Stmt
{
    /** @var string Key */
    public $key;
    /** @var Node\Expr Value */
    public $value;

    /**
     * Constructs a declare key=>value pair node.
     *
     * @param string    $key        Key
     * @param Node\Expr $value      Value
     * @param array     $attributes Additional attributes
     */
    public function __construct($key, Node\Expr $value, array $attributes = array()) {
        parent::__construct($attributes);
        $this->key = $key;
        $this->value = $value;
    }

    public function getSubNodeNames() {
        return array('key', 'value');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Declare_ extends Node\Stmt
{
    /** @var DeclareDeclare[] List of declares */
    public $declares;
    /** @var Node[] Statements */
    public $stmts;

    /**
     * Constructs a declare node.
     *
     * @param DeclareDeclare[] $declares   List of declares
     * @param Node[]|null      $stmts      Statements
     * @param array            $attributes Additional attributes
     */
    public function __construct(array $declares, array $stmts = null, array $attributes = array()) {
        parent::__construct($attributes);
        $this->declares = $declares;
        $this->stmts = $stmts;
    }

    public function getSubNodeNames() {
        return array('declares', 'stmts');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Do_ extends Node\Stmt
{
    /** @var Node\Expr Condition */
    public $cond;
    /** @var Node[] Statements */
    public $stmts;

    /**
     * Constructs a do while node.
     *
     * @param Node\Expr $cond       Condition
     * @param Node[]    $stmts      Statements
     * @param array     $attributes Additional attributes
     */
    public function __construct(Node\Expr $cond, array $stmts = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->cond = $cond;
        $this->stmts = $stmts;
    }

    public function getSubNodeNames() {
        return array('cond', 'stmts');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Echo_ extends Node\Stmt
{
    /** @var Node\Expr[] Expressions */
    public $exprs;

    /**
     * Constructs an echo node.
     *
     * @param Node\Expr[] $exprs      Expressions
     * @param array       $attributes Additional attributes
     */
    public function __construct(array $exprs, array $attributes = array()) {
        parent::__construct($attributes);
        $this->exprs = $exprs;
    }

    public function getSubNodeNames() {
        return array('exprs');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class ElseIf_ extends Node\Stmt
{
    /** @var Node\Expr Condition */
    public $cond;
    /** @var Node[] Statements */
    public $stmts;

    /**
     * Constructs an elseif node.
     *
     * @param Node\Expr $cond       Condition
     * @param Node[]    $stmts      Statements
     * @param array     $attributes Additional attributes
     */
    public function __construct(Node\Expr $cond, array $stmts = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->cond = $cond;
        $this->stmts = $stmts;
    }

    public function getSubNodeNames() {
        return array('cond', 'stmts');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Else_ extends Node\Stmt
{
    /** @var Node[] Statements */
    public $stmts;

    /**
     * Constructs an else node.
     *
     * @param Node[] $stmts      Statements
     * @param array  $attributes Additional attributes
     */
    public function __construct(array $stmts = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->stmts = $stmts;
    }

    public function getSubNodeNames() {
        return array('stmts');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Finally_ extends Node\Stmt
{
    /** @var Node[] Statements */
    public $stmts;

    /**
     * Constructs a finally node.
     *
     * @param Node[] $stmts      Statements
     * @param array  $attributes Additional attributes
     */
    public function __construct(array $stmts = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->stmts = $stmts;
    }

    public function getSubNodeNames() {
        return array('stmts');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class For_ extends Node\Stmt
{
    /** @var Node\Expr[] Init expressions */
    public $init;
    /** @var Node\Expr[] Loop conditions */
    public $cond;
    /** @var Node\Expr[] Loop expressions */
    public $loop;
    /** @var Node[] Statements */
    public $stmts;

    /**
     * Constructs a for loop node.
     *
     * @param array $subNodes   Array of the following optional subnodes:
     *                          'init'  => array(): Init expressions
     *                          'cond'  => array(): Loop conditions
     *                          'loop'  => array(): Loop expressions
     *                          'stmts' => array(): Statements
     * @param array $attributes Additional attributes
     */
    public function __construct(array $subNodes = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->init = isset($subNodes['init']) ? $subNodes['init'] : array();
        $this->cond = isset($subNodes['cond']) ? $subNodes['cond'] : array();
        $this->loop = isset($subNodes['loop']) ? $subNodes['loop'] : array();
        $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array();
    }

    public function getSubNodeNames() {
        return array('init', 'cond', 'loop', 'stmts');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Foreach_ extends Node\Stmt
{
    /** @var Node\Expr Expression to iterate */
    public $expr;
    /** @var null|Node\Expr Variable to assign key to */
    public $keyVar;
    /** @var bool Whether to assign value by reference */
    public $byRef;
    /** @var Node\Expr Variable to assign value to */
    public $valueVar;
    /** @var Node[] Statements */
    public $stmts;

    /**
     * Constructs a foreach node.
     *
     * @param Node\Expr $expr       Expression to iterate
     * @param Node\Expr $valueVar   Variable to assign value to
     * @param array     $subNodes   Array of the following optional subnodes:
     *                              'keyVar' => null   : Variable to assign key to
     *                              'byRef'  => false  : Whether to assign value by reference
     *                              'stmts'  => array(): Statements
     * @param array     $attributes Additional attributes
     */
    public function __construct(Node\Expr $expr, Node\Expr $valueVar, array $subNodes = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->expr = $expr;
        $this->keyVar = isset($subNodes['keyVar']) ? $subNodes['keyVar'] : null;
        $this->byRef = isset($subNodes['byRef']) ? $subNodes['byRef'] : false;
        $this->valueVar = $valueVar;
        $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array();
    }

    public function getSubNodeNames() {
        return array('expr', 'keyVar', 'byRef', 'valueVar', 'stmts');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;
use PhpParser\Node\FunctionLike;

class Function_ extends Node\Stmt implements FunctionLike
{
    /** @var bool Whether function returns by reference */
    public $byRef;
    /** @var string Name */
    public $name;
    /** @var Node\Param[] Parameters */
    public $params;
    /** @var null|string|Node\Name|Node\NullableType Return type */
    public $returnType;
    /** @var Node[] Statements */
    public $stmts;

    /**
     * Constructs a function node.
     *
     * @param string $name       Name
     * @param array  $subNodes   Array of the following optional subnodes:
     *                           'byRef'      => false  : Whether to return by reference
     *                           'params'     => array(): Parameters
     *                           'returnType' => null   : Return type
     *                           'stmts'      => array(): Statements
     * @param array  $attributes Additional attributes
     */
    public function __construct($name, array $subNodes = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->byRef = isset($subNodes['byRef']) ? $subNodes['byRef'] : false;
        $this->name = $name;
        $this->params = isset($subNodes['params']) ? $subNodes['params'] : array();
        $this->returnType = isset($subNodes['returnType']) ? $subNodes['returnType'] : null;
        $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array();
    }

    public function getSubNodeNames() {
        return array('byRef', 'name', 'params', 'returnType', 'stmts');
    }

    public function returnsByRef() {
        return $this->byRef;
    }

    public function getParams() {
        return $this->params;
    }

    public function getReturnType() {
        return $this->returnType;
    }

    public function getStmts() {
        return $this->stmts;
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Global_ extends Node\Stmt
{
    /** @var Node\Expr[] Variables */
    public $vars;

    /**
     * Constructs a global variables list node.
     *
     * @param Node\Expr[] $vars       Variables to unset
     * @param array       $attributes Additional attributes
     */
    public function __construct(array $vars, array $attributes = array()) {
        parent::__construct($attributes);
        $this->vars = $vars;
    }

    public function getSubNodeNames() {
        return array('vars');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node\Stmt;

class Goto_ extends Stmt
{
    /** @var string Name of label to jump to */
    public $name;

    /**
     * Constructs a goto node.
     *
     * @param string $name       Name of label to jump to
     * @param array  $attributes Additional attributes
     */
    public function __construct($name, array $attributes = array()) {
        parent::__construct($attributes);
        $this->name = $name;
    }

    public function getSubNodeNames() {
        return array('name');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node\Name;
use PhpParser\Node\Stmt;

class GroupUse extends Stmt
{
    /** @var int Type of group use */
    public $type;
    /** @var Name Prefix for uses */
    public $prefix;
    /** @var UseUse[] Uses */
    public $uses;

    /**
     * Constructs a group use node.
     *
     * @param Name     $prefix     Prefix for uses
     * @param UseUse[] $uses       Uses
     * @param int      $type       Type of group use
     * @param array    $attributes Additional attributes
     */
    public function __construct(Name $prefix, array $uses, $type = Use_::TYPE_NORMAL, array $attributes = array()) {
        parent::__construct($attributes);
        $this->type = $type;
        $this->prefix = $prefix;
        $this->uses = $uses;
    }

    public function getSubNodeNames() {
        return array('type', 'prefix', 'uses');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node\Stmt;

class HaltCompiler extends Stmt
{
    /** @var string Remaining text after halt compiler statement. */
    public $remaining;

    /**
     * Constructs a __halt_compiler node.
     *
     * @param string $remaining  Remaining text after halt compiler statement.
     * @param array  $attributes Additional attributes
     */
    public function __construct($remaining, array $attributes = array()) {
        parent::__construct($attributes);
        $this->remaining = $remaining;
    }

    public function getSubNodeNames() {
        return array('remaining');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class If_ extends Node\Stmt
{
    /** @var Node\Expr Condition expression */
    public $cond;
    /** @var Node[] Statements */
    public $stmts;
    /** @var ElseIf_[] Elseif clauses */
    public $elseifs;
    /** @var null|Else_ Else clause */
    public $else;

    /**
     * Constructs an if node.
     *
     * @param Node\Expr $cond       Condition
     * @param array     $subNodes   Array of the following optional subnodes:
     *                              'stmts'   => array(): Statements
     *                              'elseifs' => array(): Elseif clauses
     *                              'else'    => null   : Else clause
     * @param array     $attributes Additional attributes
     */
    public function __construct(Node\Expr $cond, array $subNodes = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->cond = $cond;
        $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array();
        $this->elseifs = isset($subNodes['elseifs']) ? $subNodes['elseifs'] : array();
        $this->else = isset($subNodes['else']) ? $subNodes['else'] : null;
    }

    public function getSubNodeNames() {
        return array('cond', 'stmts', 'elseifs', 'else');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node\Stmt;

class InlineHTML extends Stmt
{
    /** @var string String */
    public $value;

    /**
     * Constructs an inline HTML node.
     *
     * @param string $value      String
     * @param array  $attributes Additional attributes
     */
    public function __construct($value, array $attributes = array()) {
        parent::__construct($attributes);
        $this->value = $value;
    }

    public function getSubNodeNames() {
        return array('value');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Interface_ extends ClassLike
{
    /** @var Node\Name[] Extended interfaces */
    public $extends;

    /**
     * Constructs a class node.
     *
     * @param string $name       Name
     * @param array  $subNodes   Array of the following optional subnodes:
     *                           'extends' => array(): Name of extended interfaces
     *                           'stmts'   => array(): Statements
     * @param array  $attributes Additional attributes
     */
    public function __construct($name, array $subNodes = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->name = $name;
        $this->extends = isset($subNodes['extends']) ? $subNodes['extends'] : array();
        $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array();
    }

    public function getSubNodeNames() {
        return array('name', 'extends', 'stmts');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node\Stmt;

class Label extends Stmt
{
    /** @var string Name */
    public $name;

    /**
     * Constructs a label node.
     *
     * @param string $name       Name
     * @param array  $attributes Additional attributes
     */
    public function __construct($name, array $attributes = array()) {
        parent::__construct($attributes);
        $this->name = $name;
    }

    public function getSubNodeNames() {
        return array('name');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Namespace_ extends Node\Stmt
{
    /* For use in the "kind" attribute */
    const KIND_SEMICOLON = 1;
    const KIND_BRACED = 2;

    /** @var null|Node\Name Name */
    public $name;
    /** @var Node[] Statements */
    public $stmts;

    /**
     * Constructs a namespace node.
     *
     * @param null|Node\Name $name       Name
     * @param null|Node[]    $stmts      Statements
     * @param array          $attributes Additional attributes
     */
    public function __construct(Node\Name $name = null, $stmts = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->name = $name;
        $this->stmts = $stmts;
    }

    public function getSubNodeNames() {
        return array('name', 'stmts');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

/** Nop/empty statement (;). */
class Nop extends Node\Stmt
{
    public function getSubNodeNames() {
        return array();
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Property extends Node\Stmt
{
    /** @var int Modifiers */
    public $flags;
    /** @var PropertyProperty[] Properties */
    public $props;

    /** @deprecated Use $flags instead */
    public $type;

    /**
     * Constructs a class property list node.
     *
     * @param int                $flags      Modifiers
     * @param PropertyProperty[] $props      Properties
     * @param array              $attributes Additional attributes
     */
    public function __construct($flags, array $props, array $attributes = array()) {
        parent::__construct($attributes);
        $this->flags = $flags;
        $this->type = $flags;
        $this->props = $props;
    }

    public function getSubNodeNames() {
        return array('flags', 'props');
    }

    public function isPublic() {
        return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0
            || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0;
    }

    public function isProtected() {
        return (bool) ($this->flags & Class_::MODIFIER_PROTECTED);
    }

    public function isPrivate() {
        return (bool) ($this->flags & Class_::MODIFIER_PRIVATE);
    }

    public function isStatic() {
        return (bool) ($this->flags & Class_::MODIFIER_STATIC);
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class PropertyProperty extends Node\Stmt
{
    /** @var string Name */
    public $name;
    /** @var null|Node\Expr Default */
    public $default;

    /**
     * Constructs a class property node.
     *
     * @param string         $name       Name
     * @param null|Node\Expr $default    Default value
     * @param array          $attributes Additional attributes
     */
    public function __construct($name, Node\Expr $default = null, array $attributes = array()) {
        parent::__construct($attributes);
        $this->name = $name;
        $this->default = $default;
    }

    public function getSubNodeNames() {
        return array('name', 'default');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Return_ extends Node\Stmt
{
    /** @var null|Node\Expr Expression */
    public $expr;

    /**
     * Constructs a return node.
     *
     * @param null|Node\Expr $expr       Expression
     * @param array          $attributes Additional attributes
     */
    public function __construct(Node\Expr $expr = null, array $attributes = array()) {
        parent::__construct($attributes);
        $this->expr = $expr;
    }

    public function getSubNodeNames() {
        return array('expr');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class StaticVar extends Node\Stmt
{
    /** @var string Name */
    public $name;
    /** @var null|Node\Expr Default value */
    public $default;

    /**
     * Constructs a static variable node.
     *
     * @param string         $name       Name
     * @param null|Node\Expr $default    Default value
     * @param array          $attributes Additional attributes
     */
    public function __construct($name, Node\Expr $default = null, array $attributes = array()) {
        parent::__construct($attributes);
        $this->name = $name;
        $this->default = $default;
    }

    public function getSubNodeNames() {
        return array('name', 'default');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node\Stmt;

class Static_ extends Stmt
{
    /** @var StaticVar[] Variable definitions */
    public $vars;

    /**
     * Constructs a static variables list node.
     *
     * @param StaticVar[] $vars       Variable definitions
     * @param array       $attributes Additional attributes
     */
    public function __construct(array $vars, array $attributes = array()) {
        parent::__construct($attributes);
        $this->vars = $vars;
    }

    public function getSubNodeNames() {
        return array('vars');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Switch_ extends Node\Stmt
{
    /** @var Node\Expr Condition */
    public $cond;
    /** @var Case_[] Case list */
    public $cases;

    /**
     * Constructs a case node.
     *
     * @param Node\Expr $cond       Condition
     * @param Case_[]   $cases      Case list
     * @param array     $attributes Additional attributes
     */
    public function __construct(Node\Expr $cond, array $cases, array $attributes = array()) {
        parent::__construct($attributes);
        $this->cond = $cond;
        $this->cases = $cases;
    }

    public function getSubNodeNames() {
        return array('cond', 'cases');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Throw_ extends Node\Stmt
{
    /** @var Node\Expr Expression */
    public $expr;

    /**
     * Constructs a throw node.
     *
     * @param Node\Expr $expr       Expression
     * @param array     $attributes Additional attributes
     */
    public function __construct(Node\Expr $expr, array $attributes = array()) {
        parent::__construct($attributes);
        $this->expr = $expr;
    }

    public function getSubNodeNames() {
        return array('expr');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;


class TraitUse extends Node\Stmt
{
    /** @var Node\Name[] Traits */
    public $traits;
    /** @var TraitUseAdaptation[] Adaptations */
    public $adaptations;

    /**
     * Constructs a trait use node.
     *
     * @param Node\Name[]          $traits      Traits
     * @param TraitUseAdaptation[] $adaptations Adaptations
     * @param array                $attributes  Additional attributes
     */
    public function __construct(array $traits, array $adaptations = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->traits = $traits;
        $this->adaptations = $adaptations;
    }

    public function getSubNodeNames() {
        return array('traits', 'adaptations');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

abstract class TraitUseAdaptation extends Node\Stmt
{
    /** @var Node\Name Trait name */
    public $trait;
    /** @var string Method name */
    public $method;
}
<?php

namespace PhpParser\Node\Stmt\TraitUseAdaptation;

use PhpParser\Node;

class Alias extends Node\Stmt\TraitUseAdaptation
{
    /** @var null|int New modifier */
    public $newModifier;
    /** @var null|string New name */
    public $newName;

    /**
     * Constructs a trait use precedence adaptation node.
     *
     * @param null|Node\Name $trait       Trait name
     * @param string         $method      Method name
     * @param null|int       $newModifier New modifier
     * @param null|string    $newName     New name
     * @param array          $attributes  Additional attributes
     */
    public function __construct($trait, $method, $newModifier, $newName, array $attributes = array()) {
        parent::__construct($attributes);
        $this->trait = $trait;
        $this->method = $method;
        $this->newModifier = $newModifier;
        $this->newName = $newName;
    }

    public function getSubNodeNames() {
        return array('trait', 'method', 'newModifier', 'newName');
    }
}
<?php

namespace PhpParser\Node\Stmt\TraitUseAdaptation;

use PhpParser\Node;

class Precedence extends Node\Stmt\TraitUseAdaptation
{
    /** @var Node\Name[] Overwritten traits */
    public $insteadof;

    /**
     * Constructs a trait use precedence adaptation node.
     *
     * @param Node\Name   $trait       Trait name
     * @param string      $method      Method name
     * @param Node\Name[] $insteadof   Overwritten traits
     * @param array       $attributes  Additional attributes
     */
    public function __construct(Node\Name $trait, $method, array $insteadof, array $attributes = array()) {
        parent::__construct($attributes);
        $this->trait = $trait;
        $this->method = $method;
        $this->insteadof = $insteadof;
    }

    public function getSubNodeNames() {
        return array('trait', 'method', 'insteadof');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Trait_ extends ClassLike
{
    /**
     * Constructs a trait node.
     *
     * @param string $name       Name
     * @param array  $subNodes   Array of the following optional subnodes:
     *                           'stmts' => array(): Statements
     * @param array  $attributes Additional attributes
     */
    public function __construct($name, array $subNodes = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->name = $name;
        $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array();
    }

    public function getSubNodeNames() {
        return array('name', 'stmts');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class TryCatch extends Node\Stmt
{
    /** @var Node[] Statements */
    public $stmts;
    /** @var Catch_[] Catches */
    public $catches;
    /** @var null|Finally_ Optional finally node */
    public $finally;

    /**
     * Constructs a try catch node.
     *
     * @param Node[]        $stmts      Statements
     * @param Catch_[]      $catches    Catches
     * @param null|Finally_ $finally    Optionaly finally node
     * @param array|null    $attributes Additional attributes
     */
    public function __construct(array $stmts, array $catches, Finally_ $finally = null, array $attributes = array()) {
        parent::__construct($attributes);
        $this->stmts = $stmts;
        $this->catches = $catches;
        $this->finally = $finally;
    }

    public function getSubNodeNames() {
        return array('stmts', 'catches', 'finally');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class Unset_ extends Node\Stmt
{
    /** @var Node\Expr[] Variables to unset */
    public $vars;

    /**
     * Constructs an unset node.
     *
     * @param Node\Expr[] $vars       Variables to unset
     * @param array       $attributes Additional attributes
     */
    public function __construct(array $vars, array $attributes = array()) {
        parent::__construct($attributes);
        $this->vars = $vars;
    }

    public function getSubNodeNames() {
        return array('vars');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class UseUse extends Node\Stmt
{
    /** @var int One of the Stmt\Use_::TYPE_* constants. Will only differ from TYPE_UNKNOWN for mixed group uses */
    public $type;
    /** @var Node\Name Namespace, class, function or constant to alias */
    public $name;
    /** @var string Alias */
    public $alias;

    /**
     * Constructs an alias (use) node.
     *
     * @param Node\Name   $name       Namespace/Class to alias
     * @param null|string $alias      Alias
     * @param int         $type       Type of the use element (for mixed group use declarations only)
     * @param array       $attributes Additional attributes
     */
    public function __construct(Node\Name $name, $alias = null, $type = Use_::TYPE_UNKNOWN, array $attributes = array()) {
        if (null === $alias) {
            $alias = $name->getLast();
        }

        parent::__construct($attributes);
        $this->type = $type;
        $this->name = $name;
        $this->alias = $alias;
    }

    public function getSubNodeNames() {
        return array('type', 'name', 'alias');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node\Stmt;

class Use_ extends Stmt
{
    /**
     * Unknown type. Both Stmt\Use_ / Stmt\GroupUse and Stmt\UseUse have a $type property, one of them will always be
     * TYPE_UNKNOWN while the other has one of the three other possible types. For normal use statements the type on the
     * Stmt\UseUse is unknown. It's only the other way around for mixed group use declarations.
     */
    const TYPE_UNKNOWN = 0;
    /** Class or namespace import */
    const TYPE_NORMAL = 1;
    /** Function import */
    const TYPE_FUNCTION = 2;
    /** Constant import */
    const TYPE_CONSTANT = 3;

    /** @var int Type of alias */
    public $type;
    /** @var UseUse[] Aliases */
    public $uses;

    /**
     * Constructs an alias (use) list node.
     *
     * @param UseUse[] $uses       Aliases
     * @param int      $type       Type of alias
     * @param array    $attributes Additional attributes
     */
    public function __construct(array $uses, $type = self::TYPE_NORMAL, array $attributes = array()) {
        parent::__construct($attributes);
        $this->type = $type;
        $this->uses = $uses;
    }

    public function getSubNodeNames() {
        return array('type', 'uses');
    }
}
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;

class While_ extends Node\Stmt
{
    /** @var Node\Expr Condition */
    public $cond;
    /** @var Node[] Statements */
    public $stmts;

    /**
     * Constructs a while node.
     *
     * @param Node\Expr $cond       Condition
     * @param Node[]    $stmts      Statements
     * @param array     $attributes Additional attributes
     */
    public function __construct(Node\Expr $cond, array $stmts = array(), array $attributes = array()) {
        parent::__construct($attributes);
        $this->cond = $cond;
        $this->stmts = $stmts;
    }

    public function getSubNodeNames() {
        return array('cond', 'stmts');
    }
}
<?php

namespace PhpParser;

abstract class NodeAbstract implements Node, \JsonSerializable
{
    protected $attributes;

    /**
     * Creates a Node.
     *
     * @param array $attributes Array of attributes
     */
    public function __construct(array $attributes = array()) {
        $this->attributes = $attributes;
    }

    /**
     * Gets the type of the node.
     *
     * @return string Type of the node
     */
    public function getType() {
        $className = rtrim(get_class($this), '_');
        return strtr(
            substr(
                $className,
                strpos($className, 'PhpParser\Node') + 15
            ),
            '\\',
            '_'
        );
    }

    /**
     * Gets line the node started in.
     *
     * @return int Line
     */
    public function getLine() {
        return $this->getAttribute('startLine', -1);
    }

    /**
     * Sets line the node started in.
     *
     * @param int $line Line
     *
     * @deprecated
     */
    public function setLine($line) {
        $this->setAttribute('startLine', (int) $line);
    }

    /**
     * Gets the doc comment of the node.
     *
     * The doc comment has to be the last comment associated with the node.
     *
     * @return null|Comment\Doc Doc comment object or null
     */
    public function getDocComment() {
        $comments = $this->getAttribute('comments');
        if (!$comments) {
            return null;
        }

        $lastComment = $comments[count($comments) - 1];
        if (!$lastComment instanceof Comment\Doc) {
            return null;
        }

        return $lastComment;
    }

    /**
     * Sets the doc comment of the node.
     *
     * This will either replace an existing doc comment or add it to the comments array.
     *
     * @param Comment\Doc $docComment Doc comment to set
     */
    public function setDocComment(Comment\Doc $docComment) {
        $comments = $this->getAttribute('comments', []);

        $numComments = count($comments);
        if ($numComments > 0 && $comments[$numComments - 1] instanceof Comment\Doc) {
            // Replace existing doc comment
            $comments[$numComments - 1] = $docComment;
        } else {
            // Append new comment
            $comments[] = $docComment;
        }

        $this->setAttribute('comments', $comments);
    }

    public function setAttribute($key, $value) {
        $this->attributes[$key] = $value;
    }

    public function hasAttribute($key) {
        return array_key_exists($key, $this->attributes);
    }

    public function &getAttribute($key, $default = null) {
        if (!array_key_exists($key, $this->attributes)) {
            return $default;
        } else {
            return $this->attributes[$key];
        }
    }

    public function getAttributes() {
        return $this->attributes;
    }

    public function jsonSerialize() {
        return ['nodeType' => $this->getType()] + get_object_vars($this);
    }
}
<?php

namespace PhpParser;

use PhpParser\Node\Expr\Include_;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\GroupUse;
use PhpParser\Node\Stmt\Use_;
use PhpParser\Node\Stmt\UseUse;

class NodeDumper
{
    private $dumpComments;
    private $dumpPositions;
    private $code;

    /**
     * Constructs a NodeDumper.
     *
     * Supported options:
     *  * bool dumpComments: Whether comments should be dumped.
     *  * bool dumpPositions: Whether line/offset information should be dumped. To dump offset
     *                        information, the code needs to be passed to dump().
     *
     * @param array $options Options (see description)
     */
    public function __construct(array $options = []) {
        $this->dumpComments = !empty($options['dumpComments']);
        $this->dumpPositions = !empty($options['dumpPositions']);
    }

    /**
     * Dumps a node or array.
     *
     * @param array|Node  $node Node or array to dump
     * @param string|null $code Code corresponding to dumped AST. This only needs to be passed if
     *                          the dumpPositions option is enabled and the dumping of node offsets
     *                          is desired.
     *
     * @return string Dumped value
     */
    public function dump($node, $code = null) {
        $this->code = $code;
        return $this->dumpRecursive($node);
    }

    protected function dumpRecursive($node) {
        if ($node instanceof Node) {
            $r = $node->getType();
            if ($this->dumpPositions && null !== $p = $this->dumpPosition($node)) {
                $r .= $p;
            }
            $r .= '(';

            foreach ($node->getSubNodeNames() as $key) {
                $r .= "\n    " . $key . ': ';

                $value = $node->$key;
                if (null === $value) {
                    $r .= 'null';
                } elseif (false === $value) {
                    $r .= 'false';
                } elseif (true === $value) {
                    $r .= 'true';
                } elseif (is_scalar($value)) {
                    if ('flags' === $key || 'newModifier' === $key) {
                        $r .= $this->dumpFlags($value);
                    } else if ('type' === $key && $node instanceof Include_) {
                        $r .= $this->dumpIncludeType($value);
                    } else if ('type' === $key
                            && ($node instanceof Use_ || $node instanceof UseUse || $node instanceof GroupUse)) {
                        $r .= $this->dumpUseType($value);
                    } else {
                        $r .= $value;
                    }
                } else {
                    $r .= str_replace("\n", "\n    ", $this->dumpRecursive($value));
                }
            }

            if ($this->dumpComments && $comments = $node->getAttribute('comments')) {
                $r .= "\n    comments: " . str_replace("\n", "\n    ", $this->dumpRecursive($comments));
            }
        } elseif (is_array($node)) {
            $r = 'array(';

            foreach ($node as $key => $value) {
                $r .= "\n    " . $key . ': ';

                if (null === $value) {
                    $r .= 'null';
                } elseif (false === $value) {
                    $r .= 'false';
                } elseif (true === $value) {
                    $r .= 'true';
                } elseif (is_scalar($value)) {
                    $r .= $value;
                } else {
                    $r .= str_replace("\n", "\n    ", $this->dumpRecursive($value));
                }
            }
        } elseif ($node instanceof Comment) {
            return $node->getReformattedText();
        } else {
            throw new \InvalidArgumentException('Can only dump nodes and arrays.');
        }

        return $r . "\n)";
    }

    protected function dumpFlags($flags) {
        $strs = [];
        if ($flags & Class_::MODIFIER_PUBLIC) {
            $strs[] = 'MODIFIER_PUBLIC';
        }
        if ($flags & Class_::MODIFIER_PROTECTED) {
            $strs[] = 'MODIFIER_PROTECTED';
        }
        if ($flags & Class_::MODIFIER_PRIVATE) {
            $strs[] = 'MODIFIER_PRIVATE';
        }
        if ($flags & Class_::MODIFIER_ABSTRACT) {
            $strs[] = 'MODIFIER_ABSTRACT';
        }
        if ($flags & Class_::MODIFIER_STATIC) {
            $strs[] = 'MODIFIER_STATIC';
        }
        if ($flags & Class_::MODIFIER_FINAL) {
            $strs[] = 'MODIFIER_FINAL';
        }

        if ($strs) {
            return implode(' | ', $strs) . ' (' . $flags . ')';
        } else {
            return $flags;
        }
    }

    protected function dumpIncludeType($type) {
        $map = [
            Include_::TYPE_INCLUDE      => 'TYPE_INCLUDE',
            Include_::TYPE_INCLUDE_ONCE => 'TYPE_INCLUDE_ONCE',
            Include_::TYPE_REQUIRE      => 'TYPE_REQUIRE',
            Include_::TYPE_REQUIRE_ONCE => 'TYPE_REQURE_ONCE',
        ];

        if (!isset($map[$type])) {
            return $type;
        }
        return $map[$type] . ' (' . $type . ')';
    }

    protected function dumpUseType($type) {
        $map = [
            Use_::TYPE_UNKNOWN  => 'TYPE_UNKNOWN',
            Use_::TYPE_NORMAL   => 'TYPE_NORMAL',
            Use_::TYPE_FUNCTION => 'TYPE_FUNCTION',
            Use_::TYPE_CONSTANT => 'TYPE_CONSTANT',
        ];

        if (!isset($map[$type])) {
            return $type;
        }
        return $map[$type] . ' (' . $type . ')';
    }

    protected function dumpPosition(Node $node) {
        if (!$node->hasAttribute('startLine') || !$node->hasAttribute('endLine')) {
            return null;
        }

        $start = $node->getAttribute('startLine');
        $end = $node->getAttribute('endLine');
        if ($node->hasAttribute('startFilePos') && $node->hasAttribute('endFilePos')
            && null !== $this->code
        ) {
            $start .= ':' . $this->toColumn($this->code, $node->getAttribute('startFilePos'));
            $end .= ':' . $this->toColumn($this->code, $node->getAttribute('endFilePos'));
        }
        return "[$start - $end]";
    }

    // Copied from Error class
    private function toColumn($code, $pos) {
        if ($pos > strlen($code)) {
            throw new \RuntimeException('Invalid position information');
        }

        $lineStartPos = strrpos($code, "\n", $pos - strlen($code));
        if (false === $lineStartPos) {
            $lineStartPos = -1;
        }

        return $pos - $lineStartPos;
    }
}
<?php

namespace PhpParser;

class NodeTraverser implements NodeTraverserInterface
{
    /**
     * If NodeVisitor::enterNode() returns DONT_TRAVERSE_CHILDREN, child nodes
     * of the current node will not be traversed for any visitors.
     *
     * For subsequent visitors enterNode() will still be called on the current
     * node and leaveNode() will also be invoked for the current node.
     */
    const DONT_TRAVERSE_CHILDREN = 1;

    /**
     * If NodeVisitor::enterNode() or NodeVisitor::leaveNode() returns
     * STOP_TRAVERSAL, traversal is aborted.
     *
     * The afterTraverse() method will still be invoked.
     */
    const STOP_TRAVERSAL = 2;

    /**
     * If NodeVisitor::leaveNode() returns REMOVE_NODE for a node that occurs
     * in an array, it will be removed from the array.
     *
     * For subsequent visitors leaveNode() will still be invoked for the
     * removed node.
     */
    const REMOVE_NODE = false;

    /** @var NodeVisitor[] Visitors */
    protected $visitors;

    /** @var bool Whether traversal should be stopped */
    protected $stopTraversal;

    /**
     * Constructs a node traverser.
     */
    public function __construct() {
        $this->visitors = array();
    }

    /**
     * Adds a visitor.
     *
     * @param NodeVisitor $visitor Visitor to add
     */
    public function addVisitor(NodeVisitor $visitor) {
        $this->visitors[] = $visitor;
    }

    /**
     * Removes an added visitor.
     *
     * @param NodeVisitor $visitor
     */
    public function removeVisitor(NodeVisitor $visitor) {
        foreach ($this->visitors as $index => $storedVisitor) {
            if ($storedVisitor === $visitor) {
                unset($this->visitors[$index]);
                break;
            }
        }
    }

    /**
     * Traverses an array of nodes using the registered visitors.
     *
     * @param Node[] $nodes Array of nodes
     *
     * @return Node[] Traversed array of nodes
     */
    public function traverse(array $nodes) {
        $this->stopTraversal = false;

        foreach ($this->visitors as $visitor) {
            if (null !== $return = $visitor->beforeTraverse($nodes)) {
                $nodes = $return;
            }
        }

        $nodes = $this->traverseArray($nodes);

        foreach ($this->visitors as $visitor) {
            if (null !== $return = $visitor->afterTraverse($nodes)) {
                $nodes = $return;
            }
        }

        return $nodes;
    }

    protected function traverseNode(Node $node) {
        foreach ($node->getSubNodeNames() as $name) {
            $subNode =& $node->$name;

            if (is_array($subNode)) {
                $subNode = $this->traverseArray($subNode);
                if ($this->stopTraversal) {
                    break;
                }
            } elseif ($subNode instanceof Node) {
                $traverseChildren = true;
                foreach ($this->visitors as $visitor) {
                    $return = $visitor->enterNode($subNode);
                    if (self::DONT_TRAVERSE_CHILDREN === $return) {
                        $traverseChildren = false;
                    } else if (self::STOP_TRAVERSAL === $return) {
                        $this->stopTraversal = true;
                        break 2;
                    } else if (null !== $return) {
                        $subNode = $return;
                    }
                }

                if ($traverseChildren) {
                    $subNode = $this->traverseNode($subNode);
                    if ($this->stopTraversal) {
                        break;
                    }
                }

                foreach ($this->visitors as $visitor) {
                    $return = $visitor->leaveNode($subNode);
                    if (self::STOP_TRAVERSAL === $return) {
                        $this->stopTraversal = true;
                        break 2;
                    } else if (null !== $return) {
                        if (is_array($return)) {
                            throw new \LogicException(
                                'leaveNode() may only return an array ' .
                                'if the parent structure is an array'
                            );
                        }
                        $subNode = $return;
                    }
                }
            }
        }

        return $node;
    }

    protected function traverseArray(array $nodes) {
        $doNodes = array();

        foreach ($nodes as $i => &$node) {
            if (is_array($node)) {
                $node = $this->traverseArray($node);
                if ($this->stopTraversal) {
                    break;
                }
            } elseif ($node instanceof Node) {
                $traverseChildren = true;
                foreach ($this->visitors as $visitor) {
                    $return = $visitor->enterNode($node);
                    if (self::DONT_TRAVERSE_CHILDREN === $return) {
                        $traverseChildren = false;
                    } else if (self::STOP_TRAVERSAL === $return) {
                        $this->stopTraversal = true;
                        break 2;
                    } else if (null !== $return) {
                        $node = $return;
                    }
                }

                if ($traverseChildren) {
                    $node = $this->traverseNode($node);
                    if ($this->stopTraversal) {
                        break;
                    }
                }

                foreach ($this->visitors as $visitor) {
                    $return = $visitor->leaveNode($node);

                    if (self::REMOVE_NODE === $return) {
                        $doNodes[] = array($i, array());
                        break;
                    } else if (self::STOP_TRAVERSAL === $return) {
                        $this->stopTraversal = true;
                        break 2;
                    } elseif (is_array($return)) {
                        $doNodes[] = array($i, $return);
                        break;
                    } elseif (null !== $return) {
                        $node = $return;
                    }
                }
            }
        }

        if (!empty($doNodes)) {
            while (list($i, $replace) = array_pop($doNodes)) {
                array_splice($nodes, $i, 1, $replace);
            }
        }

        return $nodes;
    }
}
<?php

namespace PhpParser;

interface NodeTraverserInterface
{
    /**
     * Adds a visitor.
     *
     * @param NodeVisitor $visitor Visitor to add
     */
    function addVisitor(NodeVisitor $visitor);

    /**
     * Removes an added visitor.
     *
     * @param NodeVisitor $visitor
     */
    function removeVisitor(NodeVisitor $visitor);

    /**
     * Traverses an array of nodes using the registered visitors.
     *
     * @param Node[] $nodes Array of nodes
     *
     * @return Node[] Traversed array of nodes
     */
    function traverse(array $nodes);
}

<?php

namespace PhpParser;

interface NodeVisitor
{
    /**
     * Called once before traversal.
     *
     * Return value semantics:
     *  * null:      $nodes stays as-is
     *  * otherwise: $nodes is set to the return value
     *
     * @param Node[] $nodes Array of nodes
     *
     * @return null|Node[] Array of nodes
     */
    public function beforeTraverse(array $nodes);

    /**
     * Called when entering a node.
     *
     * Return value semantics:
     *  * null
     *        => $node stays as-is
     *  * NodeTraverser::DONT_TRAVERSE_CHILDREN
     *        => Children of $node are not traversed. $node stays as-is
     *  * NodeTraverser::STOP_TRAVERSAL
     *        => Traversal is aborted. $node stays as-is
     *  * otherwise
     *        => $node is set to the return value
     *
     * @param Node $node Node
     *
     * @return null|int|Node Node
     */
    public function enterNode(Node $node);

    /**
     * Called when leaving a node.
     *
     * Return value semantics:
     *  * null
     *        => $node stays as-is
     *  * NodeTraverser::REMOVE_NODE
     *        => $node is removed from the parent array
     *  * NodeTraverser::STOP_TRAVERSAL
     *        => Traversal is aborted. $node stays as-is
     *  * array (of Nodes)
     *        => The return value is merged into the parent array (at the position of the $node)
     *  * otherwise
     *        => $node is set to the return value
     *
     * @param Node $node Node
     *
     * @return null|false|int|Node|Node[] Node
     */
    public function leaveNode(Node $node);

    /**
     * Called once after traversal.
     *
     * Return value semantics:
     *  * null:      $nodes stays as-is
     *  * otherwise: $nodes is set to the return value
     *
     * @param Node[] $nodes Array of nodes
     *
     * @return null|Node[] Array of nodes
     */
    public function afterTraverse(array $nodes);
}<?php

namespace PhpParser\NodeVisitor;

use PhpParser\Error;
use PhpParser\ErrorHandler;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt;
use PhpParser\NodeVisitorAbstract;

class NameResolver extends NodeVisitorAbstract
{
    /** @var null|Name Current namespace */
    protected $namespace;

    /** @var array Map of format [aliasType => [aliasName => originalName]] */
    protected $aliases;

    /** @var ErrorHandler Error handler */
    protected $errorHandler;

    /** @var bool Whether to preserve original names */
    protected $preserveOriginalNames;

    /**
     * Constructs a name resolution visitor.
     *
     * Options: If "preserveOriginalNames" is enabled, an "originalName" attribute will be added to
     * all name nodes that underwent resolution.
     *
     * @param ErrorHandler|null $errorHandler Error handler
     * @param array $options Options
     */
    public function __construct(ErrorHandler $errorHandler = null, array $options = []) {
        $this->errorHandler = $errorHandler ?: new ErrorHandler\Throwing;
        $this->preserveOriginalNames = !empty($options['preserveOriginalNames']);
    }

    public function beforeTraverse(array $nodes) {
        $this->resetState();
    }

    public function enterNode(Node $node) {
        if ($node instanceof Stmt\Namespace_) {
            $this->resetState($node->name);
        } elseif ($node instanceof Stmt\Use_) {
            foreach ($node->uses as $use) {
                $this->addAlias($use, $node->type, null);
            }
        } elseif ($node instanceof Stmt\GroupUse) {
            foreach ($node->uses as $use) {
                $this->addAlias($use, $node->type, $node->prefix);
            }
        } elseif ($node instanceof Stmt\Class_) {
            if (null !== $node->extends) {
                $node->extends = $this->resolveClassName($node->extends);
            }

            foreach ($node->implements as &$interface) {
                $interface = $this->resolveClassName($interface);
            }

            if (null !== $node->name) {
                $this->addNamespacedName($node);
            }
        } elseif ($node instanceof Stmt\Interface_) {
            foreach ($node->extends as &$interface) {
                $interface = $this->resolveClassName($interface);
            }

            $this->addNamespacedName($node);
        } elseif ($node instanceof Stmt\Trait_) {
            $this->addNamespacedName($node);
        } elseif ($node instanceof Stmt\Function_) {
            $this->addNamespacedName($node);
            $this->resolveSignature($node);
        } elseif ($node instanceof Stmt\ClassMethod
                  || $node instanceof Expr\Closure
        ) {
            $this->resolveSignature($node);
        } elseif ($node instanceof Stmt\Const_) {
            foreach ($node->consts as $const) {
                $this->addNamespacedName($const);
            }
        } elseif ($node instanceof Expr\StaticCall
                  || $node instanceof Expr\StaticPropertyFetch
                  || $node instanceof Expr\ClassConstFetch
                  || $node instanceof Expr\New_
                  || $node instanceof Expr\Instanceof_
        ) {
            if ($node->class instanceof Name) {
                $node->class = $this->resolveClassName($node->class);
            }
        } elseif ($node instanceof Stmt\Catch_) {
            foreach ($node->types as &$type) {
                $type = $this->resolveClassName($type);
            }
        } elseif ($node instanceof Expr\FuncCall) {
            if ($node->name instanceof Name) {
                $node->name = $this->resolveOtherName($node->name, Stmt\Use_::TYPE_FUNCTION);
            }
        } elseif ($node instanceof Expr\ConstFetch) {
            $node->name = $this->resolveOtherName($node->name, Stmt\Use_::TYPE_CONSTANT);
        } elseif ($node instanceof Stmt\TraitUse) {
            foreach ($node->traits as &$trait) {
                $trait = $this->resolveClassName($trait);
            }

            foreach ($node->adaptations as $adaptation) {
                if (null !== $adaptation->trait) {
                    $adaptation->trait = $this->resolveClassName($adaptation->trait);
                }

                if ($adaptation instanceof Stmt\TraitUseAdaptation\Precedence) {
                    foreach ($adaptation->insteadof as &$insteadof) {
                        $insteadof = $this->resolveClassName($insteadof);
                    }
                }
            }
        }
    }

    protected function resetState(Name $namespace = null) {
        $this->namespace = $namespace;
        $this->aliases   = array(
            Stmt\Use_::TYPE_NORMAL   => array(),
            Stmt\Use_::TYPE_FUNCTION => array(),
            Stmt\Use_::TYPE_CONSTANT => array(),
        );
    }

    protected function addAlias(Stmt\UseUse $use, $type, Name $prefix = null) {
        // Add prefix for group uses
        $name = $prefix ? Name::concat($prefix, $use->name) : $use->name;
        // Type is determined either by individual element or whole use declaration
        $type |= $use->type;

        // Constant names are case sensitive, everything else case insensitive
        if ($type === Stmt\Use_::TYPE_CONSTANT) {
            $aliasName = $use->alias;
        } else {
            $aliasName = strtolower($use->alias);
        }

        if (isset($this->aliases[$type][$aliasName])) {
            $typeStringMap = array(
                Stmt\Use_::TYPE_NORMAL   => '',
                Stmt\Use_::TYPE_FUNCTION => 'function ',
                Stmt\Use_::TYPE_CONSTANT => 'const ',
            );

            $this->errorHandler->handleError(new Error(
                sprintf(
                    'Cannot use %s%s as %s because the name is already in use',
                    $typeStringMap[$type], $name, $use->alias
                ),
                $use->getAttributes()
            ));
            return;
        }

        $this->aliases[$type][$aliasName] = $name;
    }

    /** @param Stmt\Function_|Stmt\ClassMethod|Expr\Closure $node */
    private function resolveSignature($node) {
        foreach ($node->params as $param) {
            $param->type = $this->resolveType($param->type);
        }
        $node->returnType = $this->resolveType($node->returnType);
    }

    private function resolveType($node) {
        if ($node instanceof Node\NullableType) {
            $node->type = $this->resolveType($node->type);
            return $node;
        }
        if ($node instanceof Name) {
            return $this->resolveClassName($node);
        }
        return $node;
    }

    protected function resolveClassName(Name $name) {
        if ($this->preserveOriginalNames) {
            // Save the original name
            $originalName = $name;
            $name = clone $originalName;
            $name->setAttribute('originalName', $originalName);
        }

        // don't resolve special class names
        if (in_array(strtolower($name->toString()), array('self', 'parent', 'static'))) {
            if (!$name->isUnqualified()) {
                $this->errorHandler->handleError(new Error(
                    sprintf("'\\%s' is an invalid class name", $name->toString()),
                    $name->getAttributes()
                ));
            }
            return $name;
        }

        // fully qualified names are already resolved
        if ($name->isFullyQualified()) {
            return $name;
        }

        $aliasName = strtolower($name->getFirst());
        if (!$name->isRelative() && isset($this->aliases[Stmt\Use_::TYPE_NORMAL][$aliasName])) {
            // resolve aliases (for non-relative names)
            $alias = $this->aliases[Stmt\Use_::TYPE_NORMAL][$aliasName];
            return FullyQualified::concat($alias, $name->slice(1), $name->getAttributes());
        }

        // if no alias exists prepend current namespace
        return FullyQualified::concat($this->namespace, $name, $name->getAttributes());
    }

    protected function resolveOtherName(Name $name, $type) {
        if ($this->preserveOriginalNames) {
            // Save the original name
            $originalName = $name;
            $name = clone $originalName;
            $name->setAttribute('originalName', $originalName);
        }

        // fully qualified names are already resolved
        if ($name->isFullyQualified()) {
            return $name;
        }

        // resolve aliases for qualified names
        $aliasName = strtolower($name->getFirst());
        if ($name->isQualified() && isset($this->aliases[Stmt\Use_::TYPE_NORMAL][$aliasName])) {
            $alias = $this->aliases[Stmt\Use_::TYPE_NORMAL][$aliasName];
            return FullyQualified::concat($alias, $name->slice(1), $name->getAttributes());
        }

        if ($name->isUnqualified()) {
            if ($type === Stmt\Use_::TYPE_CONSTANT) {
                // constant aliases are case-sensitive, function aliases case-insensitive
                $aliasName = $name->getFirst();
            }

            if (isset($this->aliases[$type][$aliasName])) {
                // resolve unqualified aliases
                return new FullyQualified($this->aliases[$type][$aliasName], $name->getAttributes());
            }

            if (null === $this->namespace) {
                // outside of a namespace unaliased unqualified is same as fully qualified
                return new FullyQualified($name, $name->getAttributes());
            }

            // unqualified names inside a namespace cannot be resolved at compile-time
            // add the namespaced version of the name as an attribute
            $name->setAttribute('namespacedName',
                FullyQualified::concat($this->namespace, $name, $name->getAttributes()));
            return $name;
        }

        // if no alias exists prepend current namespace
        return FullyQualified::concat($this->namespace, $name, $name->getAttributes());
    }

    protected function addNamespacedName(Node $node) {
        $node->namespacedName = Name::concat($this->namespace, $node->name);
    }
}
<?php

namespace PhpParser;

/**
 * @codeCoverageIgnore
 */
class NodeVisitorAbstract implements NodeVisitor
{
    public function beforeTraverse(array $nodes)    { }
    public function enterNode(Node $node) { }
    public function leaveNode(Node $node) { }
    public function afterTraverse(array $nodes)     { }
}<?php

namespace PhpParser;

interface Parser {
    /**
     * Parses PHP code into a node tree.
     *
     * @param string $code The source code to parse
     * @param ErrorHandler|null $errorHandler Error handler to use for lexer/parser errors, defaults
     *                                        to ErrorHandler\Throwing.
     *
     * @return Node[]|null Array of statements (or null if the 'throwOnError' option is disabled and the parser was
     *                     unable to recover from an error).
     */
    public function parse($code, ErrorHandler $errorHandler = null);
}
<?php

namespace PhpParser\Parser;

use PhpParser\Error;
use PhpParser\ErrorHandler;
use PhpParser\Parser;

class Multiple implements Parser {
    /** @var Parser[] List of parsers to try, in order of preference */
    private $parsers;

    /**
     * Create a parser which will try multiple parsers in an order of preference.
     *
     * Parsers will be invoked in the order they're provided to the constructor. If one of the
     * parsers runs without throwing, it's output is returned. Otherwise the exception that the
     * first parser generated is thrown.
     *
     * @param Parser[] $parsers
     */
    public function __construct(array $parsers) {
        $this->parsers = $parsers;
    }

    public function parse($code, ErrorHandler $errorHandler = null) {
        if (null === $errorHandler) {
            $errorHandler = new ErrorHandler\Throwing;
        }

        list($firstStmts, $firstError) = $this->tryParse($this->parsers[0], $errorHandler, $code);
        if ($firstError === null) {
            return $firstStmts;
        }

        for ($i = 1, $c = count($this->parsers); $i < $c; ++$i) {
            list($stmts, $error) = $this->tryParse($this->parsers[$i], $errorHandler, $code);
            if ($error === null) {
                return $stmts;
            }
        }

        throw $firstError;
    }

    private function tryParse(Parser $parser, ErrorHandler $errorHandler, $code) {
        $stmts = null;
        $error = null;
        try {
            $stmts = $parser->parse($code, $errorHandler);
        } catch (Error $error) {}
        return [$stmts, $error];
    }
}
<?php

namespace PhpParser\Parser;

use PhpParser\Error;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar;
use PhpParser\Node\Stmt;

/* This is an automatically GENERATED file, which should not be manually edited.
 * Instead edit one of the following:
 *  * the grammar files grammar/php5.y or grammar/php7.y
 *  * the skeleton file grammar/parser.template
 *  * the preprocessing script grammar/rebuildParsers.php
 */
class Php5 extends \PhpParser\ParserAbstract
{
    protected $tokenToSymbolMapSize = 392;
    protected $actionTableSize = 1020;
    protected $gotoTableSize = 591;

    protected $invalidSymbol = 157;
    protected $errorSymbol = 1;
    protected $defaultAction = -32766;
    protected $unexpectedTokenRule = 32767;

    protected $YY2TBLSTATE  = 405;
    protected $YYNLSTATES   = 667;

    protected $symbolToName = array(
        "EOF",
        "error",
        "T_INCLUDE",
        "T_INCLUDE_ONCE",
        "T_EVAL",
        "T_REQUIRE",
        "T_REQUIRE_ONCE",
        "','",
        "T_LOGICAL_OR",
        "T_LOGICAL_XOR",
        "T_LOGICAL_AND",
        "T_PRINT",
        "T_YIELD",
        "T_DOUBLE_ARROW",
        "T_YIELD_FROM",
        "'='",
        "T_PLUS_EQUAL",
        "T_MINUS_EQUAL",
        "T_MUL_EQUAL",
        "T_DIV_EQUAL",
        "T_CONCAT_EQUAL",
        "T_MOD_EQUAL",
        "T_AND_EQUAL",
        "T_OR_EQUAL",
        "T_XOR_EQUAL",
        "T_SL_EQUAL",
        "T_SR_EQUAL",
        "T_POW_EQUAL",
        "'?'",
        "':'",
        "T_COALESCE",
        "T_BOOLEAN_OR",
        "T_BOOLEAN_AND",
        "'|'",
        "'^'",
        "'&'",
        "T_IS_EQUAL",
        "T_IS_NOT_EQUAL",
        "T_IS_IDENTICAL",
        "T_IS_NOT_IDENTICAL",
        "T_SPACESHIP",
        "'<'",
        "T_IS_SMALLER_OR_EQUAL",
        "'>'",
        "T_IS_GREATER_OR_EQUAL",
        "T_SL",
        "T_SR",
        "'+'",
        "'-'",
        "'.'",
        "'*'",
        "'/'",
        "'%'",
        "'!'",
        "T_INSTANCEOF",
        "'~'",
        "T_INC",
        "T_DEC",
        "T_INT_CAST",
        "T_DOUBLE_CAST",
        "T_STRING_CAST",
        "T_ARRAY_CAST",
        "T_OBJECT_CAST",
        "T_BOOL_CAST",
        "T_UNSET_CAST",
        "'@'",
        "T_POW",
        "'['",
        "T_NEW",
        "T_CLONE",
        "T_EXIT",
        "T_IF",
        "T_ELSEIF",
        "T_ELSE",
        "T_ENDIF",
        "T_LNUMBER",
        "T_DNUMBER",
        "T_STRING",
        "T_STRING_VARNAME",
        "T_VARIABLE",
        "T_NUM_STRING",
        "T_INLINE_HTML",
        "T_ENCAPSED_AND_WHITESPACE",
        "T_CONSTANT_ENCAPSED_STRING",
        "T_ECHO",
        "T_DO",
        "T_WHILE",
        "T_ENDWHILE",
        "T_FOR",
        "T_ENDFOR",
        "T_FOREACH",
        "T_ENDFOREACH",
        "T_DECLARE",
        "T_ENDDECLARE",
        "T_AS",
        "T_SWITCH",
        "T_ENDSWITCH",
        "T_CASE",
        "T_DEFAULT",
        "T_BREAK",
        "T_CONTINUE",
        "T_GOTO",
        "T_FUNCTION",
        "T_CONST",
        "T_RETURN",
        "T_TRY",
        "T_CATCH",
        "T_FINALLY",
        "T_THROW",
        "T_USE",
        "T_INSTEADOF",
        "T_GLOBAL",
        "T_STATIC",
        "T_ABSTRACT",
        "T_FINAL",
        "T_PRIVATE",
        "T_PROTECTED",
        "T_PUBLIC",
        "T_VAR",
        "T_UNSET",
        "T_ISSET",
        "T_EMPTY",
        "T_HALT_COMPILER",
        "T_CLASS",
        "T_TRAIT",
        "T_INTERFACE",
        "T_EXTENDS",
        "T_IMPLEMENTS",
        "T_OBJECT_OPERATOR",
        "T_LIST",
        "T_ARRAY",
        "T_CALLABLE",
        "T_CLASS_C",
        "T_TRAIT_C",
        "T_METHOD_C",
        "T_FUNC_C",
        "T_LINE",
        "T_FILE",
        "T_START_HEREDOC",
        "T_END_HEREDOC",
        "T_DOLLAR_OPEN_CURLY_BRACES",
        "T_CURLY_OPEN",
        "T_PAAMAYIM_NEKUDOTAYIM",
        "T_NAMESPACE",
        "T_NS_C",
        "T_DIR",
        "T_NS_SEPARATOR",
        "T_ELLIPSIS",
        "';'",
        "'{'",
        "'}'",
        "'('",
        "')'",
        "'$'",
        "'`'",
        "']'",
        "'\"'"
    );

    protected $tokenToSymbol = array(
            0,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,   53,  156,  157,  153,   52,   35,  157,
          151,  152,   50,   47,    7,   48,   49,   51,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,   29,  148,
           41,   15,   43,   28,   65,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,   67,  157,  155,   34,  157,  154,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  149,   33,  150,   55,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,    1,    2,    3,    4,
            5,    6,    8,    9,   10,   11,   12,   13,   14,   16,
           17,   18,   19,   20,   21,   22,   23,   24,   25,   26,
           27,   30,   31,   32,   36,   37,   38,   39,   40,   42,
           44,   45,   46,   54,   56,   57,   58,   59,   60,   61,
           62,   63,   64,   66,   68,   69,   70,   71,   72,   73,
           74,   75,   76,   77,   78,   79,   80,   81,  157,  157,
           82,   83,   84,   85,   86,   87,   88,   89,   90,   91,
           92,   93,   94,   95,   96,   97,   98,   99,  100,  101,
          102,  103,  104,  105,  106,  107,  108,  109,  110,  111,
          112,  113,  114,  115,  116,  117,  118,  119,  120,  121,
          122,  123,  124,  125,  126,  127,  128,  129,  130,  131,
          132,  133,  134,  135,  136,  137,  157,  157,  157,  157,
          157,  157,  138,  139,  140,  141,  142,  143,  144,  145,
          146,  147
    );

    protected $action = array(
          672,  673,  674,  675,  676,-32766,  677,  678,  679,  715,
          716,  216,  217,  218,  219,  220,  221,  222,  223,  224,
            0,  225,  226,  227,  228,  229,  230,  231,  232,  233,
          234,  235,  236,-32766,-32766,-32766,-32766,-32766,-32766,-32766,
        -32766,-32767,-32767,-32767,-32767,  441,  237,  238,-32766,-32766,
        -32766,-32766,  680,-32766, 1036,-32766,-32766,-32766,-32766,-32766,
        -32766,-32767,-32767,-32767,-32767,-32767,  681,  682,  683,  684,
          685,  686,  687,  909,  329,  747,-32766,-32766,-32766,-32766,
        -32766,  282,  688,  689,  690,  691,  692,  693,  694,  695,
          696,  697,  698,  718,  719,  720,  721,  722,  710,  711,
          712,  713,  714,  699,  700,  701,  702,  703,  704,  705,
          741,  742,  743,  744,  745,  746,  706,  707,  708,  709,
          739,  730,  728,  729,  725,  726, 1178,  717,  723,  724,
          731,  732,  734,  733,  735,  736,   52,   53,  420,   54,
           55,  727,  738,  737,   23,   56,   57,  284,   58,-32766,
        -32766,-32766,-32766,-32766,-32766,-32766,-32766,-32766,    7,-32767,
        -32767,-32767,-32767,   50,  325,-32766,  585,  945,  946,  947,
          944,  943,  942,  937, 1213,   27, 1215, 1214,  763,  764,
          821,   59,   60,-32766,-32766,-32766,  809,   61, 1172,   62,
          291,  292,   63,   64,   65,   66,   67,   68,   69,   70,
          334,   24,  299,   71,  413,-32766,-32766,-32766, 1185, 1087,
         1088,  749,  633, 1178,  213,  214,  215,  464,-32766,-32766,
        -32766,  822,  407, 1099,  311,-32766, 1186,-32766,-32766,-32766,
        -32766,-32766,-32766, 1036,  200, -269,  428,-32766,-32766,-32766,
        -32766,-32766,-32766,-32766,-32766,  120,  491,  945,  946,  947,
          944,  943,  942,  306,  473,  474,  293,  623,  125,-32766,
          893,  894,  339,  477,  478,-32766, 1093, 1094, 1095, 1096,
         1090, 1091,  307,  492,-32766,  440,  425,  492, 1097, 1092,
          425,  121, -220,  869, 1182,   39,  280,  334,  321,  900,
          322,  421, -122, -122, -122,   -4,  822,  463,   99,  100,
          101,  811,  301,  119,   38,   19,  422, -122,  465, -122,
          466, -122,  467, -122,  102,  423, -122, -122, -122,   28,
           29,  468,  424,  624,   30,  469,  425,  812,   72,  297,
          923,  349,  350,  470,  471,-32766,-32766,-32766,  419,  472,
         1036,  447,  793,  840,  475,  476,-32767,-32767,-32767,-32767,
           94,   95,   96,   97,   98,-32766,  126,-32766,-32766,-32766,
        -32766, 1137,  213,  214,  215,  295,  421,  239,  824,  638,
         -122, 1036,  463,  893,  894, 1205,  811, 1036, 1204,   38,
           19,  422,  200,  465,  356,  466,  492,  467,  127,  425,
          423,  213,  214,  215,   28,   29,  468,  424,  414,   30,
          469, 1036,  870,   72,  320,  822,  349,  350,  470,  471,
           34,  200,  214,  215,  472,  460,  762,  755,  840,  475,
          476,  213,  214,  215,  295, -216,   76,   77,   78,   46,
          298,  200,  412,  653,  338,  438,   31,  294,  333,    8,
          348,  200,  241,  824,  638,   -4,   32,  332,   79,   80,
           81,   82,   83,   84,   85,   86,   87,   88,   89,   90,
           91,   92,   93,   94,   95,   96,   97,   98,   99,  100,
          101, 1210,  301,  204,  822,  421,  805,  124,-32766,-32766,
        -32766,  463,  899, 1054,  102,  811,   18,  206,   38,   19,
          422,  518,  465, 1172,  466,  546,  467,   47,-32766,  423,
        -32766,-32766,  647,   28,   29,  468,  822,  801,   30,  469,
          415,  116,   72,  803,   49,  349,  350,-32766,-32766,-32766,
        -32766,-32766,-32766,  472,  477,  808,  234,  235,  236,  213,
          214,  215, 1036,  215,  644, 1138,  124,-32766,-32766,-32766,
        -32766,-32766,  237,  238,  421,  231,  232,  233, 1099,  200,
          463,  200,  824,  638,  811,  439,  918,   38,   19,  422,
         1036,  465,  242,  466,  749,  467, 1178,  339,  423,   96,
           97,   98,   28,   29,  468,  822,  421,   30,  469,  117,
          919,   72,  463,  283,  349,  350,  811,  244, 1036,   38,
           19,  422,  472,  465,  243,  466,  118,  467,  377, 1064,
          423, 1036,  207,  642,   28,   29,  468,  822,  129,   30,
          469,  296,  576,   72,-32766,-32766,  349,  350,  123,  205,
          492,  824,  638,  425,  472,  115,-32766,-32766,-32766,  434,
          492,  200,  640,  425,  820,  641,-32766,-32766,  429,-32766,
          334,  237,  238,  454,  591,  421,-32766,  130,  357,  449,
           20,  463,  128,  856,  638,  811,  763,  764,   38,   19,
          422,  313,  465,  646,  466,  650,  467,  599,  600,  423,
          833,  301,  605,   28,   29,  468,  822,  421,   30,  469,
          756,  643,   72,  463,  299,  349,  350,  811,  922,  666,
           38,   19,  422,  472,  465,  102,  466,   51,  467,  934,
          656,  423,  512,  433,   48,   28,   29,  468,   41,   42,
           30,  469,   43,   44,   72,   45,  435,  349,  350, 1057,
          750, 1208,  824,  638,  776,  472,  749,   33,  103,  104,
          105,  106,  107,  108,  109,  110,  111,  112,  113,  114,
          534,  533,  517,  513,  524,  437,  421,  602,  516,  622,
          612,  619,  463,  582,  824,  638,  811,  595,-32766,   38,
           19,  422,  632,  465,  579,  466,  240,  467,  975,  977,
          423,  609, 1144,  279,   28,   29,  468,   12,  -80,   30,
          469,  537,  432,   72,  208,  209,  349,  350,  458, 1098,
          210,  596,  211,  328,  472,  326,   11,  842,  323,  393,
            4,  385,  408,  303,  202, 1034,    0,    0,  324,  208,
          209,  841, 1087, 1088,    0,  210,-32766,  211, -497, -498,
         1089,  312,  310,  824,  638,  477,    0,    0,    0,  202,
            0, -398,    0,    0,    9,    0,    0, 1087, 1088,    3,
         -497,-32766, -406,  370, -407, 1089,  835,  639,    0,  384,
          372,  409,  526,  434,    0,    0,  864,  857,  863,  872,
            0,  813,  798,  819,  807,  761,  661,  565,  760, 1093,
         1094, 1095, 1096, 1090, 1091,  383,   37,   36,  759,  926,
          810, 1097, 1092,  854,  852,  302,  806,  929,  212,  818,
        -32766,  930,  565,  928, 1093, 1094, 1095, 1096, 1090, 1091,
          383,  927,  796,  804,  660,  802, 1097, 1092,  649,  651,
           75,    0,  652,  212,  654,-32766,  655,  658,  663,  664,
          665,  405,  122,  330,  331,  406,    0, 1211,  757,  758,
          839,  838,  766,  453, 1209, 1179, 1177, 1163, 1175, 1078,
          911, 1183, 1173,  829,  836, 1038, 1039,  827,  935, 1212,
          765,  837,  794,  662, 1050,  768,  767,  861,  862,    0,
          304,  290,  289,   25,   26,  281,  203,   74,  305,  336,
          411,  417,   35,   73,-32766,   40,   22,    0, 1015,  569,
         -217, 1016, 1103, 1080,  901, 1040, 1044, 1041,  629,  559,
          461,  457,  455,  450,  378,   16,   15,   14, -216,    0,
            0, -416,    0, 1045,  603, 1157, 1104, 1207, 1077, 1174,
         1158, 1162, 1176, 1063, 1048, 1049, 1046, 1047,    0, 1143
    );

    protected $actionCheck = array(
            2,    3,    4,    5,    6,    8,    8,    9,   10,   11,
           12,   31,   32,   33,   34,   35,   36,   37,   38,   39,
            0,   41,   42,   43,   44,   45,   46,   47,   48,   49,
           50,   51,   52,    8,    9,   10,   31,   32,   33,   34,
           35,   36,   37,   38,   39,    7,   66,   67,   31,   32,
           33,   34,   54,   28,   12,   30,   31,   32,   33,   34,
           35,   36,   37,   38,   39,   40,   68,   69,   70,   71,
           72,   73,   74,   79,    7,   77,   31,   32,   33,   34,
           35,    7,   84,   85,   86,   87,   88,   89,   90,   91,
           92,   93,   94,   95,   96,   97,   98,   99,  100,  101,
          102,  103,  104,  105,  106,  107,  108,  109,  110,  111,
          112,  113,  114,  115,  116,  117,  118,  119,  120,  121,
          122,  123,  124,  125,  126,  127,   79,  129,  130,  131,
          132,  133,  134,  135,  136,  137,    2,    3,    4,    5,
            6,  143,  144,  145,    7,   11,   12,  153,   14,   31,
           32,   33,   34,   35,   36,   37,   38,   39,  103,   41,
           42,   43,   44,   67,  109,   79,   82,  112,  113,  114,
          115,  116,  117,  118,   77,    7,   79,   80,  102,  103,
            1,   47,   48,    8,    9,   10,  148,   53,   79,   55,
           56,   57,   58,   59,   60,   61,   62,   63,   64,   65,
          153,   67,   68,   69,   70,    8,    9,   10,    1,   75,
           76,   77,   77,   79,    8,    9,   10,   83,    8,    9,
           10,    1,  146,  139,  128,   28,  152,   30,   31,   32,
           33,   34,   35,   12,   28,   79,  102,  151,   28,  153,
           30,   31,   32,   33,   34,  149,  112,  112,  113,  114,
          115,  116,  117,    7,  120,  121,   35,   77,  149,  103,
          130,  131,  153,  129,  130,  109,  132,  133,  134,  135,
          136,  137,  138,  143,  118,    7,  146,  143,  144,  145,
          146,    7,  152,   29,   77,  151,   13,  153,  154,  152,
          156,   71,   72,   73,   74,    0,    1,   77,   50,   51,
           52,   81,   54,   13,   84,   85,   86,   87,   88,   89,
           90,   91,   92,   93,   66,   95,   96,   97,   98,   99,
          100,  101,  102,  143,  104,  105,  146,  148,  108,    7,
          150,  111,  112,  113,  114,    8,    9,   10,    7,  119,
           12,    7,  122,  123,  124,  125,   41,   42,   43,   44,
           45,   46,   47,   48,   49,   28,  149,   30,   31,   32,
           33,  155,    8,    9,   10,   35,   71,   13,  148,  149,
          150,   12,   77,  130,  131,   79,   81,   12,   82,   84,
           85,   86,   28,   88,    7,   90,  143,   92,   67,  146,
           95,    8,    9,   10,   99,  100,  101,  102,  103,  104,
          105,   12,  148,  108,  109,    1,  111,  112,  113,  114,
           13,   28,    9,   10,  119,    7,  148,  122,  123,  124,
          125,    8,    9,   10,   35,  152,    8,    9,   10,   67,
           35,   28,    7,   29,   67,   29,  140,  141,  143,    7,
            7,   28,   29,  148,  149,  150,   28,    7,   30,   31,
           32,   33,   34,   35,   36,   37,   38,   39,   40,   41,
           42,   43,   44,   45,   46,   47,   48,   49,   50,   51,
           52,  150,   54,    7,    1,   71,  148,  147,    8,    9,
           10,   77,  152,  152,   66,   81,  152,   15,   84,   85,
           86,   82,   88,   79,   90,  128,   92,   67,   28,   95,
           30,   31,   29,   99,  100,  101,    1,  148,  104,  105,
          123,  149,  108,  148,   67,  111,  112,    8,    9,   10,
           31,   32,   33,  119,  129,  148,   50,   51,   52,    8,
            9,   10,   12,   10,   29,  152,  147,   28,  151,   30,
           31,   32,   66,   67,   71,   47,   48,   49,  139,   28,
           77,   28,  148,  149,   81,  149,  148,   84,   85,   86,
           12,   88,   15,   90,   77,   92,   79,  153,   95,   47,
           48,   49,   99,  100,  101,    1,   71,  104,  105,  149,
          148,  108,   77,   35,  111,  112,   81,   15,   12,   84,
           85,   86,  119,   88,   15,   90,  149,   92,   78,  112,
           95,   12,   15,   29,   99,  100,  101,    1,  149,  104,
          105,   35,  153,  108,   31,   32,  111,  112,   29,   15,
          143,  148,  149,  146,  119,   15,    8,    9,   10,  146,
          143,   28,  149,  146,   29,   29,    8,    9,  151,   31,
          153,   66,   67,   72,   73,   71,   28,   97,   98,   72,
           73,   77,   29,  148,  149,   81,  102,  103,   84,   85,
           86,   29,   88,   29,   90,   29,   92,  106,  107,   95,
           35,   54,   74,   99,  100,  101,    1,   71,  104,  105,
          148,  149,  108,   77,   68,  111,  112,   81,  148,  149,
           84,   85,   86,  119,   88,   66,   90,   67,   92,  148,
          149,   95,   77,   77,   67,   99,  100,  101,   67,   67,
          104,  105,   67,   67,  108,   67,   77,  111,  112,   79,
           77,   77,  148,  149,   77,  119,   77,   15,   16,   17,
           18,   19,   20,   21,   22,   23,   24,   25,   26,   27,
           77,   77,   77,   77,   82,   86,   71,   79,   79,   79,
           79,   91,   77,   96,  148,  149,   81,   96,   82,   84,
           85,   86,   89,   88,   87,   90,   29,   92,   56,   57,
           95,   93,  139,   94,   99,  100,  101,   94,   94,  104,
          105,   94,  102,  108,   47,   48,  111,  112,  102,  139,
           53,  109,   55,  126,  119,  110,  142,  123,  126,  146,
          142,  146,  146,  151,   67,  154,   -1,   -1,  127,   47,
           48,  123,   75,   76,   -1,   53,   79,   55,  128,  128,
           83,  128,  128,  148,  149,  129,   -1,   -1,   -1,   67,
           -1,  142,   -1,   -1,  142,   -1,   -1,   75,   76,  142,
          128,   79,  142,  142,  142,   83,  147,  149,   -1,  146,
          146,  146,  146,  146,   -1,   -1,  148,  148,  148,  148,
           -1,  148,  148,  148,  148,  148,  148,  130,  148,  132,
          133,  134,  135,  136,  137,  138,  148,  148,  148,  148,
          148,  144,  145,  148,  148,  151,  148,  148,  151,  148,
          153,  148,  130,  148,  132,  133,  134,  135,  136,  137,
          138,  148,  148,  148,  148,  148,  144,  145,  149,  149,
          149,   -1,  149,  151,  149,  153,  149,  149,  149,  149,
          149,  149,  149,  149,  149,  149,   -1,  150,  150,  150,
          150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
          150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
          150,  150,  150,  150,  150,  150,  150,  150,  150,   -1,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,   -1,  152,  152,
          152,  152,  152,  152,  152,  152,  152,  152,  152,  152,
          152,  152,  152,  152,  152,  152,  152,  152,  152,   -1,
           -1,  154,   -1,  155,  155,  155,  155,  155,  155,  155,
          155,  155,  155,  155,  155,  155,  155,  155,   -1,  156
    );

    protected $actionBase = array(
            0,  220,  295,  109,  109,  180,  745,   -2,   -2,   -2,
           -2,   -2,  135,  574,  473,  404,  473,  606,  505,  675,
          675,  675,  330,  389,  221,  221,  831,  221,  359,  365,
          328,  520,  589,  548,  576,   42,   42,   42,   42,  134,
          134,   42,   42,   42,   42,   42,   42,   42,   42,   42,
           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
           42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
           42,  254,  179,  290,  397,  757,  755,  738,  741,  833,
          679,  829,  784,  785,  623,  786,  787,  788,  789,  790,
          783,  791,  849,  792,  418,  418,  418,  418,  418,  418,
          418,  418,  418,  418,  418,   -3,  354,  383,  413,  206,
          628,  521,  521,  521,  521,  521,  521,  521,  175,  175,
          175,  175,  175,  175,  175,  175,  175,  175,  175,  175,
          175,  175,  175,  175,  175,  403,  618,  618,  618,  523,
          737,  603,  762,  762,  762,  762,  762,  762,  762,  762,
          762,  762,  762,  762,  762,  762,  762,  762,  762,  762,
          762,  762,  762,  762,  762,  762,  762,  762,  762,  762,
          762,  762,  762,  762,  762,  762,  762,  762,  762,  762,
          762,  762,  762,  762,  762,  470,  -20,  -20,  509,  608,
          327,  583,  210,  489,  197,   25,   25,   25,   25,   25,
           17,   45,    5,    5,    5,    5,  712,  305,  305,  305,
          305,  118,  118,  118,  118,  780,  781,  801,  804,  395,
          395,  696,  696,  616,  773,  522,  522,  498,  498,  487,
          487,  487,  487,  487,  487,  487,  487,  487,  487,  387,
          156,  823,  130,  130,  130,  130,  243,  409,  633,  863,
          207,  207,  207,  243,  248,  248,  248,  476,  476,  476,
           76,  662,  296,   86,   86,   86,   86,  296,   86,   86,
          554,  554,  554,  483,  761,  676,  477,  430,   97,  459,
          657,  807,  661,  808,  540,  702,   96,  656,  705,   -6,
          680,  577,  571,  561,  689,  406,   -6,  254,  551,  447,
          617,  732,  663,  268,  730,  377,   38,  367,  532,  362,
          414,  334,  774,  720,  827,  826,   74,  321,  691,  617,
          617,  617,  137,   84,  775,  772,  362,  273,  575,  575,
          575,  575,  806,  776,  575,  575,  575,  575,  805,  800,
          432,  408,  782,  331,  731,  649,  649,  649,  649,  649,
          649,  635,  649,  813,  666,  825,  825,  664,  668,  635,
          824,  824,  824,  824,  635,  649,  825,  825,  635,  616,
          825,  168,  635,  672,  649,  667,  667,  824,  756,  718,
          666,  669,  681,  825,  825,  825,  681,  664,  635,  824,
          682,  699,  466,  825,  824,  632,  632,  682,  635,  632,
          668,  632,   20,  605,  641,  821,  822,  820,  625,  698,
          688,  674,  811,  810,  816,  665,  626,  814,  812,  706,
          717,  716,  639,  610,  642,  645,  646,  648,  697,  637,
          694,  680,  707,  629,  629,  629,  690,  658,  690,  629,
          629,  629,  629,  629,  629,  629,  629,  848,  700,  701,
          693,  659,  715,  604,  704,  687,  472,  768,  650,  706,
          706,  802,  835,  842,  847,  651,  643,  734,  837,  690,
          862,  729,  274,  587,  652,  803,  703,  647,  655,  690,
          809,  690,  769,  690,  834,  799,  644,  706,  779,  629,
          832,  861,  860,  859,  858,  857,  856,  855,  854,  630,
          853,  714,  677,  841,  246,  815,  689,  692,  653,  713,
           67,  852,  778,  690,  690,  770,  761,  690,  771,  711,
          728,  845,  710,  840,  851,  650,  839,  690,  686,  850,
           67,  634,  598,  828,  678,  708,  819,  671,  830,  818,
          759,  547,  579,  777,  636,  754,  844,  843,  846,  709,
          760,  763,  572,  660,  640,  670,  793,  765,  817,  735,
          794,  795,  836,  684,  707,  654,  685,  683,  673,  767,
          796,  838,  736,  739,  743,  797,  753,  798,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,  134,  134,
           -2,   -2,   -2,   -2,    0,    0,    0,    0,    0,   -2,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,    0,    0,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  418,  418,
          418,  418,  418,  418,  418,  418,  418,  418,  418,  418,
          418,  418,  418,  418,  418,  418,  418,  418,  418,  418,
          418,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,  418,  -20,  -20,  -20,  -20,  418,  -20,  -20,
          -20,  -20,  -20,  -20,  -20,  418,  418,  418,  418,  418,
          418,  418,  418,  418,  418,  418,  418,  418,  418,  418,
          418,  418,  -20,  418,  418,  418,  -20,  487,  -20,  487,
          487,  487,  487,  487,  487,  487,  487,  487,  487,  487,
          487,  487,  487,  487,  487,  487,  487,  487,  487,  487,
          487,  487,  487,  487,  487,  487,  487,  487,  487,  487,
          487,  487,  487,  487,  487,  487,  487,  487,  487,  487,
          487,  487,  418,    0,    0,  418,  -20,  418,  -20,  418,
          -20,  418,  418,  418,  418,  418,  418,  -20,  -20,  -20,
          -20,  -20,  -20,    0,  248,  248,  248,  248,  -20,  -20,
          -20,  -20,   55,   55,   55,   55,  487,  487,  487,  487,
          487,  487,  248,  248,  476,  476,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,  487,   55,  487,  649,
          649,  649,  649,  649,  296,  296,  296,   47,   47,   47,
          649,    0,    0,    0,    0,    0,    0,  649,  296,    0,
          487,  487,  487,  487,    0,  487,  487,  649,  649,  649,
          649,   47,  296,  649,  825,    0,   47,  550,  550,  550,
          550,   67,  362,    0,  649,  649,    0,  669,    0,    0,
            0,  825,    0,    0,    0,    0,    0,  629,  274,  734,
            0,  433,    0,    0,    0,    0,    0,    0,    0,  643,
          433,  322,  322,    0,    0,  630,  629,  629,  629,    0,
            0,  643,  643,    0,    0,    0,    0,    0,    0,  440,
          643,    0,    0,    0,    0,  440,  425,    0,    0,  425,
            0,   67
    );

    protected $actionDefault = array(
            3,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,  525,  525,32767,  481,32767,32767,
        32767,32767,32767,32767,32767,  287,  287,  287,32767,32767,
        32767,  513,  513,  513,  513,  513,  513,  513,  513,  513,
          513,  513,32767,32767,32767,32767,32767,  369,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,  375,  530,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,  350,  351,  353,  354,  286,  514,
          237,  376,  529,  285,  239,  314,  485,32767,32767,32767,
          316,  116,  248,  193,  484,  119,  284,  224,  368,  370,
          315,  291,  296,  297,  298,  299,  300,  301,  302,  303,
          304,  305,  306,  307,  290,  441,  347,  346,  345,  443,
        32767,  442,  478,  478,  481,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,  312,  469,  468,  313,  439,
          317,  440,  319,  444,  318,  335,  336,  333,  334,  337,
          446,  445,  462,  463,  460,  461,  289,  338,  339,  340,
          341,  464,  465,  466,  467,  271,  271,  271,  271,32767,
        32767,  524,  524,32767,32767,  326,  327,  453,  454,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
          272,32767,  228,  228,  228,  228,  228,32767,32767,32767,
        32767,32767,32767,32767,  321,  322,  320,  448,  449,  447,
        32767,  415,32767,32767,32767,32767,32767,  417,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,  486,32767,32767,
        32767,32767,32767,32767,32767,  499,  404,32767,32767,32767,
          397,  212,  214,  161,  472,32767,32767,32767,32767,  504,
          331,32767,32767,32767,32767,32767,32767,  539,32767,  499,
        32767,32767,32767,32767,32767,32767,32767,32767,  344,  323,
          324,  325,32767,32767,32767,32767,  503,  497,  456,  457,
          458,  459,32767,32767,  450,  451,  452,  455,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,  165,32767,  412,32767,  418,  418,32767,32767,  165,
        32767,32767,32767,32767,  165,32767,  502,  501,  165,32767,
          398,  480,  165,  178,32767,  176,  176,32767,  198,  198,
        32767,32767,  180,  473,  492,32767,  180,32767,  165,32767,
          386,  167,  480,32767,32767,  230,  230,  386,  165,  230,
        32767,  230,32767,   82,  422,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,  399,
        32767,32767,32767,32767,  365,  366,  475,  488,32767,  489,
        32767,  397,32767,  329,  330,  332,  309,32767,  311,  355,
          356,  357,  358,  359,  360,  361,  363,32767,  402,32767,
          405,32767,32767,32767,   84,  108,  247,32767,  537,   84,
          400,32767,32767,  294,  537,32767,32767,32767,32767,  532,
        32767,32767,  288,32767,32767,32767,   84,32767,   84,  243,
        32767,  163,32767,  522,32767,  497,32767,  401,32767,  328,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,  498,
        32767,32767,32767,32767,  219,32767,  435,32767,   84,32767,
          179,32767,32767,  292,  238,32767,32767,  531,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,  164,32767,32767,
          181,32767,32767,  497,32767,32767,32767,32767,32767,32767,
        32767,32767,  283,32767,32767,32767,32767,32767,  497,32767,
        32767,32767,  223,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,   82,   60,32767,  265,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,  121,  121,
            3,  121,  121,    3,  121,  121,  121,  121,  121,  121,
          121,  121,  121,  121,  121,  121,  121,  206,  250,  209,
          198,  198,  158,  250,  250,  250,  257
    );

    protected $goto = array(
          160,  160,  134,  134,  139,  134,  135,  136,  137,  142,
          144,  181,  162,  158,  158,  158,  158,  139,  139,  159,
          159,  159,  159,  159,  159,  159,  159,  159,  159,  159,
          154,  155,  156,  157,  178,  133,  179,  493,  494,  360,
          495,  499,  500,  501,  502,  503,  504,  505,  506,  962,
          138,  140,  141,  143,  165,  170,  180,  196,  245,  248,
          250,  252,  254,  255,  256,  257,  258,  259,  267,  268,
          269,  270,  285,  286,  314,  315,  316,  379,  380,  381,
          549,  182,  183,  184,  185,  186,  187,  188,  189,  190,
          191,  192,  193,  194,  145,  146,  147,  161,  148,  163,
          149,  197,  164,  150,  151,  152,  198,  153,  131,  625,
          567,  754,  567,  567,  567,  567,  567,  567,  567,  567,
          567,  567,  567,  567,  567,  567,  567,  567,  567,  567,
          567,  567,  567,  567,  567,  567,  567,  567,  567,  567,
          567,  567,  567,  567,  567,  567,  567,  567,  567,  567,
          567,  567,  567,  567,  567, 1100,  753, 1100, 1100, 1100,
         1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100,
         1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100,
         1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100,
         1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100,
          523,  784,  497,  497,  497,  497,  497,  497,    6,  508,
          634,  508,  497,  497,  497,  497,  497,  497,  497,  497,
          497,  497,  509,  550,  509,  580,  606,  522,  885,  885,
         1190, 1190,  815,  849,  849,  849,  849,  168,  844,  850,
          522,  522,  171,  172,  173,  388,  389,  390,  391,  167,
          195,  199,  201,  249,  251,  253,  260,  261,  262,  263,
          264,  265,  271,  272,  273,  274,  287,  288,  317,  318,
          319,  394,  395,  396,  397,  169,  174,  246,  247,  175,
          176,  177,  387,  608,  543,  543,  573,  539,  583,  586,
          631,  855,  541,  541,  496,  498,  529,  545,  574,  577,
          587,  593,  341, 1169,  566, 1169,  566,  566,  566,  566,
          566,  566,  566,  566,  566,  566,  566,  566,  566,  566,
          566,  566,  566,  566,  566,  566,  566,  566,  566,  566,
          566,  566,  566,  566,  566,  566,  566,  566,  566,  566,
          566,  566,  566,  566,  566,  566,  566,  566,  566,  514,
          443,  445,  933,  636,  327,  309, 1101,  618,  931,  519,
          519,  519,  519,  777,  551,  552,  553,  554,  555,  556,
          557,  558,  560,  589,  903,  611,  538,  519,  617,  548,
          358,  544,  572,  430,  430,  430,  430,  430,  430, 1194,
          777,  777,  361,  430,  430,  430,  430,  430,  430,  430,
          430,  430,  430, 1065, 1161, 1065,  892,  892,  892,  892,
          892, 1168,  598, 1168,  590,  344,  404,  892,  369,  369,
          369, 1058, 1184, 1184, 1184, 1076, 1075, 1065, 1065, 1065,
         1065, 1149, 1065, 1065,  519,  519,  536,  568,  519,  519,
          615,  519,  369,  510,  960,  510, 1167,  386,  770,  770,
          778,  778,  778,  780,  520,  769,  276,  277,  278,  535,
          607,  659,  562,  547,  594,  868,  882,  613,  867,  616,
          878,  620,  621,  628,  630,  635,  637, 1081,  375, 1201,
         1201, 1187, 1009,  889, 1019,   17,   13,  355,  790,  752,
         1200, 1200,  898, 1061, 1062,  362,  941, 1058, 1201,  527,
          871,  561,  851,  540,  657,  347,  511,  880,  875, 1200,
         1059, 1160, 1059,   21,  398,  373,  773, 1203,  604,  451,
         1060,  771,  907,  342,  343,  368,  645,  402,  446,   10,
         1056, 1051,  912,  781,  578, 1146,  859,  459,  949,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
          528
    );

    protected $gotoCheck = array(
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   53,
           63,   12,   63,   63,   63,   63,   63,   63,   63,   63,
           63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
           63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
           63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
           63,   63,   63,   63,   63,  119,   11,  119,  119,  119,
          119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
          119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
          119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
          119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
           94,   25,  110,  110,  110,  110,  110,  110,   91,   63,
            5,   63,  110,  110,  110,  110,  110,  110,  110,  110,
          110,  110,  110,   40,  110,   36,   36,   40,   71,   71,
           71,   71,   46,   63,   63,   63,   63,   23,   63,   63,
           40,   40,   23,   23,   23,   23,   23,   23,   23,   23,
           23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
           23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
           23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
           23,   23,   47,   47,   47,   47,   47,   47,   56,   56,
           56,   29,   47,   47,   47,   47,   47,   47,   47,   47,
           47,   47,   66,  111,   53,  111,   53,   53,   53,   53,
           53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
           53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
           53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
           53,   53,   53,   53,   53,   53,   53,   53,   53,    8,
            7,    7,    7,    7,  118,  118,    7,    7,    7,    8,
            8,    8,    8,   19,  103,  103,  103,  103,  103,  103,
          103,  103,  103,  103,   78,   57,    8,    8,   57,    2,
           57,  102,    2,   53,   53,   53,   53,   53,   53,  132,
           19,   19,   43,   53,   53,   53,   53,   53,   53,   53,
           53,   53,   53,   53,   76,   53,   53,   53,   53,   53,
           53,  112,  120,  112,   64,   64,   64,   53,  116,  116,
          116,   76,  112,  112,  112,  117,  117,   53,   53,   53,
           53,  124,   53,   53,    8,    8,    8,    8,    8,    8,
           53,    8,  116,  115,   94,  115,  112,  116,   19,   19,
           19,   19,   19,   19,    8,   19,   61,   61,   61,   28,
           45,   28,   28,    8,   28,   28,   28,   28,   28,   28,
           28,   28,   28,   28,   28,   28,   28,   30,   44,  134,
          134,  130,   95,   73,   30,   30,   30,   30,   10,   10,
          133,  133,   75,   76,   76,   54,   91,   76,  134,   54,
           10,   30,   10,   54,   10,   14,   10,   10,   10,  133,
           76,   76,   76,   30,   18,   13,   21,  133,   30,   54,
           76,   20,   79,   66,   66,    9,   68,   17,   59,   54,
          108,  106,   80,   22,   60,  123,   65,  101,   93,   -1,
           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
           94
    );

    protected $gotoBase = array(
            0,    0, -261,    0,    0,  198,    0,  347,   29,  192,
          487,  154,  109,  168,  185,    0,    0,  121,  183,   43,
          173,  184,   93,   37,    0,  193,    0,    0, -180,  273,
           64,    0,    0,    0,    0,    0,  189,    0,    0,  -22,
          201,    0,    0,  354,  188,  180,  216,    3,    0,    0,
            0,    0,    0,  104,   71,    0,  -15,  -81,    0,   92,
           88, -207,    0,  -90,   90,   89, -137,    0,  169,    0,
            0,  -51,    0,  177,    0,  179,   67,    0,  351,  166,
           91,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,  196,    0,   78,  161,  181,    0,    0,    0,    0,
            0,   80,  356,  322,    0,    0,  115,    0,  111,    0,
          -77,    4,  112,    0,    0,  144,  108,  114,   33,  -45,
          209,    0,    0,   83,  227,    0,    0,    0,    0,    0,
          199,    0,  362,  182,  171,    0,    0
    );

    protected $gotoDefault = array(
        -32768,  462,  668,    2,  669,  740,  748,  601,  479,  515,
          853,  791,  792,  364,  410,  480,  363,  399,  392,  779,
          772,  774,  782,  166,  400,  785,    1,  787,  521,  823,
         1010,  351,  795,  352,  592,  797,  531,  799,  800,  132,
          481,  365,  366,  532,  374,  581,  814,  266,  371,  816,
          353,  817,  826,  354,  614,  597,  563,  610,  482,  442,
          575,  275,  542, 1073,  570,  858,  340,  866,  648,  874,
          877,  483,  564,  888,  448,  896, 1086,  382,  902,  908,
          913,  916,  418,  401,  588,  920,  921,    5,  925,  626,
          627,  940,  300,  948,  961,  416, 1029, 1031,  484,  485,
          525,  456,  507,  530,  486, 1052,  436,  403, 1055,  487,
          488,  426,  427, 1070,  346, 1154,  345,  444,  308, 1141,
          584, 1105,  452, 1193, 1150,  337,  489,  490,  359,  376,
         1188,  431, 1195, 1202,  335,  367,  571
    );

    protected $ruleToNonTerminal = array(
            0,    1,    3,    3,    2,    5,    5,    5,    5,    5,
            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
            5,    5,    5,    6,    6,    6,    6,    6,    6,    6,
            7,    7,    8,    8,    9,    4,    4,    4,    4,    4,
            4,    4,    4,    4,    4,    4,   14,   14,   15,   15,
           15,   15,   17,   17,   13,   13,   18,   18,   19,   19,
           20,   20,   21,   21,   16,   16,   22,   24,   24,   25,
           26,   26,   28,   27,   27,   27,   27,   29,   29,   29,
           29,   29,   29,   29,   29,   29,   29,   29,   29,   29,
           29,   29,   29,   29,   29,   29,   29,   29,   29,   29,
           29,   29,   29,   29,   29,   29,   10,   10,   50,   50,
           52,   51,   51,   44,   44,   54,   54,   55,   55,   11,
           12,   12,   12,   58,   58,   58,   59,   59,   62,   62,
           60,   60,   64,   64,   37,   37,   46,   46,   49,   49,
           49,   48,   48,   65,   38,   38,   38,   38,   66,   66,
           67,   67,   68,   68,   35,   35,   31,   31,   69,   33,
           33,   70,   32,   32,   34,   34,   45,   45,   45,   56,
           56,   72,   72,   73,   73,   75,   75,   75,   74,   74,
           57,   57,   76,   76,   76,   77,   77,   78,   78,   78,
           41,   41,   79,   79,   79,   42,   42,   80,   80,   61,
           61,   81,   81,   81,   81,   86,   86,   87,   87,   88,
           88,   88,   88,   88,   89,   90,   90,   85,   85,   82,
           82,   84,   84,   92,   92,   91,   91,   91,   91,   91,
           91,   83,   83,   93,   93,   43,   43,   36,   36,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
           39,   39,   39,   30,   30,   40,   40,   98,   98,   99,
           99,   99,   99,  105,   94,   94,  101,  101,  107,  107,
          108,  109,  109,  109,  109,  109,  109,   63,   63,   53,
           53,   53,   95,   95,  113,  113,  110,  110,  114,  114,
          114,  114,   96,   96,   96,  100,  100,  100,  106,  106,
          119,  119,  119,  119,  119,  119,  119,  119,  119,  119,
          119,  119,  119,   23,   23,   23,   23,   23,   23,  121,
          121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
          121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
          121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
          121,  121,  104,  104,   97,   97,   97,   97,  120,  120,
          123,  123,  122,  122,  124,  124,   47,   47,   47,   47,
          126,  126,  125,  125,  125,  125,  125,  127,  127,  112,
          112,  115,  115,  111,  111,  128,  128,  128,  128,  116,
          116,  116,  116,  103,  103,  117,  117,  117,  117,   71,
          129,  129,  130,  130,  130,  102,  102,  131,  131,  132,
          132,  132,  132,  118,  118,  118,  118,  134,  135,  133,
          133,  133,  133,  133,  133,  133,  136,  136,  136
    );

    protected $ruleToLength = array(
            1,    1,    2,    0,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    3,    1,    1,    1,    1,    1,    3,
            5,    4,    3,    4,    2,    3,    1,    1,    7,    8,
            6,    7,    3,    1,    3,    1,    3,    1,    1,    3,
            1,    2,    1,    2,    3,    1,    3,    3,    1,    3,
            2,    0,    1,    1,    1,    1,    1,    3,    5,    8,
            3,    5,    9,    3,    2,    3,    2,    3,    2,    3,
            2,    3,    3,    3,    1,    2,    5,    7,    9,    5,
            6,    3,    3,    2,    2,    1,    1,    1,    0,    2,
            8,    0,    4,    1,    3,    0,    1,    0,    1,   10,
            7,    6,    5,    1,    2,    2,    0,    2,    0,    2,
            0,    2,    1,    3,    1,    4,    1,    4,    1,    1,
            4,    1,    3,    3,    3,    4,    4,    5,    0,    2,
            4,    3,    1,    1,    1,    4,    0,    2,    3,    0,
            2,    4,    0,    2,    0,    3,    1,    2,    1,    1,
            0,    1,    3,    4,    6,    1,    1,    1,    0,    1,
            0,    2,    2,    3,    3,    1,    3,    1,    2,    2,
            3,    1,    1,    2,    4,    3,    1,    1,    3,    2,
            0,    3,    3,    9,    3,    1,    3,    0,    2,    4,
            5,    4,    4,    4,    3,    1,    1,    1,    3,    1,
            1,    0,    1,    1,    2,    1,    1,    1,    1,    1,
            1,    1,    3,    1,    3,    3,    1,    0,    1,    1,
            3,    3,    4,    4,    1,    2,    3,    3,    3,    3,
            3,    3,    3,    3,    3,    3,    3,    3,    2,    2,
            2,    2,    3,    3,    3,    3,    3,    3,    3,    3,
            3,    3,    3,    3,    3,    3,    3,    3,    3,    2,
            2,    2,    2,    3,    3,    3,    3,    3,    3,    3,
            3,    3,    3,    1,    3,    5,    4,    3,    4,    4,
            2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
            2,    2,    2,    2,    1,    1,    1,    3,    2,    1,
            2,   10,   11,    3,    3,    2,    4,    4,    3,    4,
            4,    4,    4,    7,    3,    2,    0,    4,    1,    3,
            2,    2,    4,    6,    2,    2,    4,    1,    1,    1,
            2,    3,    1,    1,    1,    1,    1,    1,    3,    3,
            4,    4,    0,    2,    1,    0,    1,    1,    0,    1,
            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
            1,    3,    2,    1,    3,    1,    4,    3,    1,    3,
            3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
            3,    3,    3,    3,    3,    3,    2,    2,    2,    2,
            3,    3,    3,    3,    3,    3,    3,    3,    5,    4,
            4,    3,    1,    3,    1,    1,    3,    3,    0,    2,
            0,    1,    3,    1,    3,    1,    1,    1,    1,    1,
            6,    4,    3,    4,    2,    4,    4,    1,    3,    1,
            2,    1,    1,    4,    1,    3,    6,    4,    4,    4,
            4,    1,    4,    0,    1,    1,    3,    1,    1,    4,
            3,    1,    1,    1,    0,    0,    2,    3,    1,    3,
            1,    4,    2,    2,    2,    1,    2,    1,    1,    1,
            4,    3,    3,    3,    6,    3,    1,    1,    1
    );

    protected function reduceRule0() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule1() {
         $this->semValue = $this->handleNamespaces($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule2() {
         if (is_array($this->semStack[$this->stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)]); } else { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; };
    }

    protected function reduceRule3() {
         $this->semValue = array();
    }

    protected function reduceRule4() {
         $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop(['comments' => $startAttributes['comments']]); } else { $nop = null; };
            if ($nop !== null) { $this->semStack[$this->stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule5() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule6() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule7() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule8() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule9() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule10() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule11() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule12() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule13() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule14() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule15() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule16() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule17() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule18() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule19() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule20() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule21() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule22() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule23() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule24() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule25() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule26() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule27() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule28() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule29() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule30() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule31() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule32() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule33() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule34() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule35() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule36() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule37() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule38() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule39() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule40() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule41() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule42() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule43() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule44() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule45() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule46() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule47() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule48() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule49() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule50() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule51() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule52() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule53() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule54() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule55() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule56() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule57() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule58() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule59() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule60() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule61() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule62() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule63() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule64() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule65() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule66() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule67() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule68() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule69() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule70() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule71() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule72() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule73() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule74() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule75() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule76() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule77() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule78() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule79() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule80() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule81() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule82() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule83() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule84() {
         $this->semValue = new Name($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule85() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule86() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule87() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule88() {
         $this->semValue = new Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule89() {
         $this->semValue = new Stmt\Namespace_($this->semStack[$this->stackPos-(3-2)], null, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON);
            $this->checkNamespace($this->semValue);
    }

    protected function reduceRule90() {
         $this->semValue = new Stmt\Namespace_($this->semStack[$this->stackPos-(5-2)], $this->semStack[$this->stackPos-(5-4)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
            $this->checkNamespace($this->semValue);
    }

    protected function reduceRule91() {
         $this->semValue = new Stmt\Namespace_(null, $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
            $this->checkNamespace($this->semValue);
    }

    protected function reduceRule92() {
         $this->semValue = new Stmt\Use_($this->semStack[$this->stackPos-(3-2)], Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule93() {
         $this->semValue = new Stmt\Use_($this->semStack[$this->stackPos-(4-3)], $this->semStack[$this->stackPos-(4-2)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule94() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule95() {
         $this->semValue = new Stmt\Const_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule96() {
         $this->semValue = Stmt\Use_::TYPE_FUNCTION;
    }

    protected function reduceRule97() {
         $this->semValue = Stmt\Use_::TYPE_CONSTANT;
    }

    protected function reduceRule98() {
         $this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(7-3)], $this->startAttributeStack[$this->stackPos-(7-3)] + $this->endAttributeStack[$this->stackPos-(7-3)]), $this->semStack[$this->stackPos-(7-6)], $this->semStack[$this->stackPos-(7-2)], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
    }

    protected function reduceRule99() {
         $this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(8-4)], $this->startAttributeStack[$this->stackPos-(8-4)] + $this->endAttributeStack[$this->stackPos-(8-4)]), $this->semStack[$this->stackPos-(8-7)], $this->semStack[$this->stackPos-(8-2)], $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes);
    }

    protected function reduceRule100() {
         $this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(6-2)], $this->startAttributeStack[$this->stackPos-(6-2)] + $this->endAttributeStack[$this->stackPos-(6-2)]), $this->semStack[$this->stackPos-(6-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes);
    }

    protected function reduceRule101() {
         $this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(7-3)], $this->startAttributeStack[$this->stackPos-(7-3)] + $this->endAttributeStack[$this->stackPos-(7-3)]), $this->semStack[$this->stackPos-(7-6)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
    }

    protected function reduceRule102() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule103() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule104() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule105() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule106() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule107() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule108() {
         $this->semValue = new Stmt\UseUse($this->semStack[$this->stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $this->stackPos-(1-1));
    }

    protected function reduceRule109() {
         $this->semValue = new Stmt\UseUse($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $this->stackPos-(3-3));
    }

    protected function reduceRule110() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule111() {
         $this->semValue = $this->semStack[$this->stackPos-(2-2)];
    }

    protected function reduceRule112() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)]; $this->semValue->type = Stmt\Use_::TYPE_NORMAL;
    }

    protected function reduceRule113() {
         $this->semValue = $this->semStack[$this->stackPos-(2-2)]; $this->semValue->type = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule114() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule115() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule116() {
         $this->semValue = new Node\Const_($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule117() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule118() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule119() {
         $this->semValue = new Node\Const_($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule120() {
         if (is_array($this->semStack[$this->stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)]); } else { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; };
    }

    protected function reduceRule121() {
         $this->semValue = array();
    }

    protected function reduceRule122() {
         $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop(['comments' => $startAttributes['comments']]); } else { $nop = null; };
            if ($nop !== null) { $this->semStack[$this->stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule123() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule124() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule125() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule126() {
         throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule127() {

        if ($this->semStack[$this->stackPos-(3-2)]) {
            $this->semValue = $this->semStack[$this->stackPos-(3-2)]; $attrs = $this->startAttributeStack[$this->stackPos-(3-1)]; $stmts = $this->semValue; if (!empty($attrs['comments'])) {$stmts[0]->setAttribute('comments', array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); };
        } else {
            $startAttributes = $this->startAttributeStack[$this->stackPos-(3-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop(['comments' => $startAttributes['comments']]); } else { $this->semValue = null; };
            if (null === $this->semValue) { $this->semValue = array(); }
        }

    }

    protected function reduceRule128() {
         $this->semValue = new Stmt\If_($this->semStack[$this->stackPos-(5-2)], ['stmts' => is_array($this->semStack[$this->stackPos-(5-3)]) ? $this->semStack[$this->stackPos-(5-3)] : array($this->semStack[$this->stackPos-(5-3)]), 'elseifs' => $this->semStack[$this->stackPos-(5-4)], 'else' => $this->semStack[$this->stackPos-(5-5)]], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
    }

    protected function reduceRule129() {
         $this->semValue = new Stmt\If_($this->semStack[$this->stackPos-(8-2)], ['stmts' => $this->semStack[$this->stackPos-(8-4)], 'elseifs' => $this->semStack[$this->stackPos-(8-5)], 'else' => $this->semStack[$this->stackPos-(8-6)]], $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes);
    }

    protected function reduceRule130() {
         $this->semValue = new Stmt\While_($this->semStack[$this->stackPos-(3-2)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule131() {
         $this->semValue = new Stmt\Do_($this->semStack[$this->stackPos-(5-4)], is_array($this->semStack[$this->stackPos-(5-2)]) ? $this->semStack[$this->stackPos-(5-2)] : array($this->semStack[$this->stackPos-(5-2)]), $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
    }

    protected function reduceRule132() {
         $this->semValue = new Stmt\For_(['init' => $this->semStack[$this->stackPos-(9-3)], 'cond' => $this->semStack[$this->stackPos-(9-5)], 'loop' => $this->semStack[$this->stackPos-(9-7)], 'stmts' => $this->semStack[$this->stackPos-(9-9)]], $this->startAttributeStack[$this->stackPos-(9-1)] + $this->endAttributes);
    }

    protected function reduceRule133() {
         $this->semValue = new Stmt\Switch_($this->semStack[$this->stackPos-(3-2)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule134() {
         $this->semValue = new Stmt\Break_(null, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule135() {
         $this->semValue = new Stmt\Break_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule136() {
         $this->semValue = new Stmt\Continue_(null, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule137() {
         $this->semValue = new Stmt\Continue_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule138() {
         $this->semValue = new Stmt\Return_(null, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule139() {
         $this->semValue = new Stmt\Return_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule140() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule141() {
         $this->semValue = new Stmt\Global_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule142() {
         $this->semValue = new Stmt\Static_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule143() {
         $this->semValue = new Stmt\Echo_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule144() {
         $this->semValue = new Stmt\InlineHTML($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule145() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule146() {
         $this->semValue = new Stmt\Unset_($this->semStack[$this->stackPos-(5-3)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
    }

    protected function reduceRule147() {
         $this->semValue = new Stmt\Foreach_($this->semStack[$this->stackPos-(7-3)], $this->semStack[$this->stackPos-(7-5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$this->stackPos-(7-5)][1], 'stmts' => $this->semStack[$this->stackPos-(7-7)]], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
    }

    protected function reduceRule148() {
         $this->semValue = new Stmt\Foreach_($this->semStack[$this->stackPos-(9-3)], $this->semStack[$this->stackPos-(9-7)][0], ['keyVar' => $this->semStack[$this->stackPos-(9-5)], 'byRef' => $this->semStack[$this->stackPos-(9-7)][1], 'stmts' => $this->semStack[$this->stackPos-(9-9)]], $this->startAttributeStack[$this->stackPos-(9-1)] + $this->endAttributes);
    }

    protected function reduceRule149() {
         $this->semValue = new Stmt\Declare_($this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-5)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
    }

    protected function reduceRule150() {
         $this->semValue = new Stmt\TryCatch($this->semStack[$this->stackPos-(6-3)], $this->semStack[$this->stackPos-(6-5)], $this->semStack[$this->stackPos-(6-6)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); $this->checkTryCatch($this->semValue);
    }

    protected function reduceRule151() {
         $this->semValue = new Stmt\Throw_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule152() {
         $this->semValue = new Stmt\Goto_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule153() {
         $this->semValue = new Stmt\Label($this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule154() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule155() {
         $this->semValue = array(); /* means: no statement */
    }

    protected function reduceRule156() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule157() {
         $startAttributes = $this->startAttributeStack[$this->stackPos-(1-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop(['comments' => $startAttributes['comments']]); } else { $this->semValue = null; };
            if ($this->semValue === null) $this->semValue = array(); /* means: no statement */
    }

    protected function reduceRule158() {
         $this->semValue = array();
    }

    protected function reduceRule159() {
         $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule160() {
         $this->semValue = new Stmt\Catch_(array($this->semStack[$this->stackPos-(8-3)]), substr($this->semStack[$this->stackPos-(8-4)], 1), $this->semStack[$this->stackPos-(8-7)], $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes);
    }

    protected function reduceRule161() {
         $this->semValue = null;
    }

    protected function reduceRule162() {
         $this->semValue = new Stmt\Finally_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule163() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule164() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule165() {
         $this->semValue = false;
    }

    protected function reduceRule166() {
         $this->semValue = true;
    }

    protected function reduceRule167() {
         $this->semValue = false;
    }

    protected function reduceRule168() {
         $this->semValue = true;
    }

    protected function reduceRule169() {
         $this->semValue = new Stmt\Function_($this->semStack[$this->stackPos-(10-3)], ['byRef' => $this->semStack[$this->stackPos-(10-2)], 'params' => $this->semStack[$this->stackPos-(10-5)], 'returnType' => $this->semStack[$this->stackPos-(10-7)], 'stmts' => $this->semStack[$this->stackPos-(10-9)]], $this->startAttributeStack[$this->stackPos-(10-1)] + $this->endAttributes);
    }

    protected function reduceRule170() {
         $this->semValue = new Stmt\Class_($this->semStack[$this->stackPos-(7-2)], ['type' => $this->semStack[$this->stackPos-(7-1)], 'extends' => $this->semStack[$this->stackPos-(7-3)], 'implements' => $this->semStack[$this->stackPos-(7-4)], 'stmts' => $this->semStack[$this->stackPos-(7-6)]], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
            $this->checkClass($this->semValue, $this->stackPos-(7-2));
    }

    protected function reduceRule171() {
         $this->semValue = new Stmt\Interface_($this->semStack[$this->stackPos-(6-2)], ['extends' => $this->semStack[$this->stackPos-(6-3)], 'stmts' => $this->semStack[$this->stackPos-(6-5)]], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes);
            $this->checkInterface($this->semValue, $this->stackPos-(6-2));
    }

    protected function reduceRule172() {
         $this->semValue = new Stmt\Trait_($this->semStack[$this->stackPos-(5-2)], ['stmts' => $this->semStack[$this->stackPos-(5-4)]], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
    }

    protected function reduceRule173() {
         $this->semValue = 0;
    }

    protected function reduceRule174() {
         $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT;
    }

    protected function reduceRule175() {
         $this->semValue = Stmt\Class_::MODIFIER_FINAL;
    }

    protected function reduceRule176() {
         $this->semValue = null;
    }

    protected function reduceRule177() {
         $this->semValue = $this->semStack[$this->stackPos-(2-2)];
    }

    protected function reduceRule178() {
         $this->semValue = array();
    }

    protected function reduceRule179() {
         $this->semValue = $this->semStack[$this->stackPos-(2-2)];
    }

    protected function reduceRule180() {
         $this->semValue = array();
    }

    protected function reduceRule181() {
         $this->semValue = $this->semStack[$this->stackPos-(2-2)];
    }

    protected function reduceRule182() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule183() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule184() {
         $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule185() {
         $this->semValue = $this->semStack[$this->stackPos-(4-2)];
    }

    protected function reduceRule186() {
         $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule187() {
         $this->semValue = $this->semStack[$this->stackPos-(4-2)];
    }

    protected function reduceRule188() {
         $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule189() {
         $this->semValue = null;
    }

    protected function reduceRule190() {
         $this->semValue = $this->semStack[$this->stackPos-(4-2)];
    }

    protected function reduceRule191() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule192() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule193() {
         $this->semValue = new Stmt\DeclareDeclare($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule194() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule195() {
         $this->semValue = $this->semStack[$this->stackPos-(4-3)];
    }

    protected function reduceRule196() {
         $this->semValue = $this->semStack[$this->stackPos-(4-2)];
    }

    protected function reduceRule197() {
         $this->semValue = $this->semStack[$this->stackPos-(5-3)];
    }

    protected function reduceRule198() {
         $this->semValue = array();
    }

    protected function reduceRule199() {
         $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule200() {
         $this->semValue = new Stmt\Case_($this->semStack[$this->stackPos-(4-2)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule201() {
         $this->semValue = new Stmt\Case_(null, $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule202() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule203() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule204() {
         $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule205() {
         $this->semValue = $this->semStack[$this->stackPos-(4-2)];
    }

    protected function reduceRule206() {
         $this->semValue = array();
    }

    protected function reduceRule207() {
         $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule208() {
         $this->semValue = new Stmt\ElseIf_($this->semStack[$this->stackPos-(3-2)], is_array($this->semStack[$this->stackPos-(3-3)]) ? $this->semStack[$this->stackPos-(3-3)] : array($this->semStack[$this->stackPos-(3-3)]), $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule209() {
         $this->semValue = array();
    }

    protected function reduceRule210() {
         $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule211() {
         $this->semValue = new Stmt\ElseIf_($this->semStack[$this->stackPos-(4-2)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule212() {
         $this->semValue = null;
    }

    protected function reduceRule213() {
         $this->semValue = new Stmt\Else_(is_array($this->semStack[$this->stackPos-(2-2)]) ? $this->semStack[$this->stackPos-(2-2)] : array($this->semStack[$this->stackPos-(2-2)]), $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule214() {
         $this->semValue = null;
    }

    protected function reduceRule215() {
         $this->semValue = new Stmt\Else_($this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule216() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)], false);
    }

    protected function reduceRule217() {
         $this->semValue = array($this->semStack[$this->stackPos-(2-2)], true);
    }

    protected function reduceRule218() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)], false);
    }

    protected function reduceRule219() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule220() {
         $this->semValue = array();
    }

    protected function reduceRule221() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule222() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule223() {
         $this->semValue = new Node\Param(substr($this->semStack[$this->stackPos-(4-4)], 1), null, $this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-2)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); $this->checkParam($this->semValue);
    }

    protected function reduceRule224() {
         $this->semValue = new Node\Param(substr($this->semStack[$this->stackPos-(6-4)], 1), $this->semStack[$this->stackPos-(6-6)], $this->semStack[$this->stackPos-(6-1)], $this->semStack[$this->stackPos-(6-2)], $this->semStack[$this->stackPos-(6-3)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); $this->checkParam($this->semValue);
    }

    protected function reduceRule225() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule226() {
         $this->semValue = 'array';
    }

    protected function reduceRule227() {
         $this->semValue = 'callable';
    }

    protected function reduceRule228() {
         $this->semValue = null;
    }

    protected function reduceRule229() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule230() {
         $this->semValue = null;
    }

    protected function reduceRule231() {
         $this->semValue = $this->semStack[$this->stackPos-(2-2)];
    }

    protected function reduceRule232() {
         $this->semValue = array();
    }

    protected function reduceRule233() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule234() {
         $this->semValue = array(new Node\Arg($this->semStack[$this->stackPos-(3-2)], false, false, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes));
    }

    protected function reduceRule235() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule236() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule237() {
         $this->semValue = new Node\Arg($this->semStack[$this->stackPos-(1-1)], false, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule238() {
         $this->semValue = new Node\Arg($this->semStack[$this->stackPos-(2-2)], true, false, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule239() {
         $this->semValue = new Node\Arg($this->semStack[$this->stackPos-(2-2)], false, true, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule240() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule241() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule242() {
         $this->semValue = new Expr\Variable(substr($this->semStack[$this->stackPos-(1-1)], 1), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule243() {
         $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule244() {
         $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule245() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule246() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule247() {
         $this->semValue = new Stmt\StaticVar(substr($this->semStack[$this->stackPos-(1-1)], 1), null, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule248() {
         $this->semValue = new Stmt\StaticVar(substr($this->semStack[$this->stackPos-(3-1)], 1), $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule249() {
         $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule250() {
         $this->semValue = array();
    }

    protected function reduceRule251() {
         $this->semValue = new Stmt\Property($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); $this->checkProperty($this->semValue, $this->stackPos-(3-1));
    }

    protected function reduceRule252() {
         $this->semValue = new Stmt\ClassConst($this->semStack[$this->stackPos-(3-2)], 0, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule253() {
         $this->semValue = new Stmt\ClassMethod($this->semStack[$this->stackPos-(9-4)], ['type' => $this->semStack[$this->stackPos-(9-1)], 'byRef' => $this->semStack[$this->stackPos-(9-3)], 'params' => $this->semStack[$this->stackPos-(9-6)], 'returnType' => $this->semStack[$this->stackPos-(9-8)], 'stmts' => $this->semStack[$this->stackPos-(9-9)]], $this->startAttributeStack[$this->stackPos-(9-1)] + $this->endAttributes);
            $this->checkClassMethod($this->semValue, $this->stackPos-(9-1));
    }

    protected function reduceRule254() {
         $this->semValue = new Stmt\TraitUse($this->semStack[$this->stackPos-(3-2)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule255() {
         $this->semValue = array();
    }

    protected function reduceRule256() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule257() {
         $this->semValue = array();
    }

    protected function reduceRule258() {
         $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule259() {
         $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule260() {
         $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(5-1)][0], $this->semStack[$this->stackPos-(5-1)][1], $this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-4)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
    }

    protected function reduceRule261() {
         $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], $this->semStack[$this->stackPos-(4-3)], null, $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule262() {
         $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], null, $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule263() {
         $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], null, $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule264() {
         $this->semValue = array($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)]);
    }

    protected function reduceRule265() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule266() {
         $this->semValue = array(null, $this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule267() {
         $this->semValue = null;
    }

    protected function reduceRule268() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule269() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule270() {
         $this->semValue = 0;
    }

    protected function reduceRule271() {
         $this->semValue = 0;
    }

    protected function reduceRule272() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule273() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule274() {
         $this->checkModifier($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->stackPos-(2-2)); $this->semValue = $this->semStack[$this->stackPos-(2-1)] | $this->semStack[$this->stackPos-(2-2)];
    }

    protected function reduceRule275() {
         $this->semValue = Stmt\Class_::MODIFIER_PUBLIC;
    }

    protected function reduceRule276() {
         $this->semValue = Stmt\Class_::MODIFIER_PROTECTED;
    }

    protected function reduceRule277() {
         $this->semValue = Stmt\Class_::MODIFIER_PRIVATE;
    }

    protected function reduceRule278() {
         $this->semValue = Stmt\Class_::MODIFIER_STATIC;
    }

    protected function reduceRule279() {
         $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT;
    }

    protected function reduceRule280() {
         $this->semValue = Stmt\Class_::MODIFIER_FINAL;
    }

    protected function reduceRule281() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule282() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule283() {
         $this->semValue = new Stmt\PropertyProperty(substr($this->semStack[$this->stackPos-(1-1)], 1), null, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule284() {
         $this->semValue = new Stmt\PropertyProperty(substr($this->semStack[$this->stackPos-(3-1)], 1), $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule285() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule286() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule287() {
         $this->semValue = array();
    }

    protected function reduceRule288() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule289() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule290() {
         $this->semValue = new Expr\Assign($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule291() {
         $this->semValue = new Expr\Assign($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule292() {
         $this->semValue = new Expr\AssignRef($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule293() {
         $this->semValue = new Expr\AssignRef($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule294() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule295() {
         $this->semValue = new Expr\Clone_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule296() {
         $this->semValue = new Expr\AssignOp\Plus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule297() {
         $this->semValue = new Expr\AssignOp\Minus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule298() {
         $this->semValue = new Expr\AssignOp\Mul($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule299() {
         $this->semValue = new Expr\AssignOp\Div($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule300() {
         $this->semValue = new Expr\AssignOp\Concat($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule301() {
         $this->semValue = new Expr\AssignOp\Mod($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule302() {
         $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule303() {
         $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule304() {
         $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule305() {
         $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule306() {
         $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule307() {
         $this->semValue = new Expr\AssignOp\Pow($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule308() {
         $this->semValue = new Expr\PostInc($this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule309() {
         $this->semValue = new Expr\PreInc($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule310() {
         $this->semValue = new Expr\PostDec($this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule311() {
         $this->semValue = new Expr\PreDec($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule312() {
         $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule313() {
         $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule314() {
         $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule315() {
         $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule316() {
         $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule317() {
         $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule318() {
         $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule319() {
         $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule320() {
         $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule321() {
         $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule322() {
         $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule323() {
         $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule324() {
         $this->semValue = new Expr\BinaryOp\Div($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule325() {
         $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule326() {
         $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule327() {
         $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule328() {
         $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule329() {
         $this->semValue = new Expr\UnaryPlus($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule330() {
         $this->semValue = new Expr\UnaryMinus($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule331() {
         $this->semValue = new Expr\BooleanNot($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule332() {
         $this->semValue = new Expr\BitwiseNot($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule333() {
         $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule334() {
         $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule335() {
         $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule336() {
         $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule337() {
         $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule338() {
         $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule339() {
         $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule340() {
         $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule341() {
         $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule342() {
         $this->semValue = new Expr\Instanceof_($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule343() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule344() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule345() {
         $this->semValue = new Expr\Ternary($this->semStack[$this->stackPos-(5-1)], $this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-5)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
    }

    protected function reduceRule346() {
         $this->semValue = new Expr\Ternary($this->semStack[$this->stackPos-(4-1)], null, $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule347() {
         $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule348() {
         $this->semValue = new Expr\Isset_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule349() {
         $this->semValue = new Expr\Empty_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule350() {
         $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule351() {
         $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule352() {
         $this->semValue = new Expr\Eval_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule353() {
         $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule354() {
         $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule355() {
         $this->semValue = new Expr\Cast\Int_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule356() {
         $this->semValue = new Expr\Cast\Double($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule357() {
         $this->semValue = new Expr\Cast\String_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule358() {
         $this->semValue = new Expr\Cast\Array_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule359() {
         $this->semValue = new Expr\Cast\Object_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule360() {
         $this->semValue = new Expr\Cast\Bool_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule361() {
         $this->semValue = new Expr\Cast\Unset_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule362() {
         $attrs = $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes;
            $attrs['kind'] = strtolower($this->semStack[$this->stackPos-(2-1)]) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE;
            $this->semValue = new Expr\Exit_($this->semStack[$this->stackPos-(2-2)], $attrs);
    }

    protected function reduceRule363() {
         $this->semValue = new Expr\ErrorSuppress($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule364() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule365() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule366() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule367() {
         $this->semValue = new Expr\ShellExec($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule368() {
         $this->semValue = new Expr\Print_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule369() {
         $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule370() {
         $this->semValue = new Expr\YieldFrom($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule371() {
         $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$this->stackPos-(10-2)], 'params' => $this->semStack[$this->stackPos-(10-4)], 'uses' => $this->semStack[$this->stackPos-(10-6)], 'returnType' => $this->semStack[$this->stackPos-(10-7)], 'stmts' => $this->semStack[$this->stackPos-(10-9)]], $this->startAttributeStack[$this->stackPos-(10-1)] + $this->endAttributes);
    }

    protected function reduceRule372() {
         $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$this->stackPos-(11-3)], 'params' => $this->semStack[$this->stackPos-(11-5)], 'uses' => $this->semStack[$this->stackPos-(11-7)], 'returnType' => $this->semStack[$this->stackPos-(11-8)], 'stmts' => $this->semStack[$this->stackPos-(11-10)]], $this->startAttributeStack[$this->stackPos-(11-1)] + $this->endAttributes);
    }

    protected function reduceRule373() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule374() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule375() {
         $this->semValue = new Expr\Yield_($this->semStack[$this->stackPos-(2-2)], null, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule376() {
         $this->semValue = new Expr\Yield_($this->semStack[$this->stackPos-(4-4)], $this->semStack[$this->stackPos-(4-2)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule377() {
         $attrs = $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_LONG;
            $this->semValue = new Expr\Array_($this->semStack[$this->stackPos-(4-3)], $attrs);
    }

    protected function reduceRule378() {
         $attrs = $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_SHORT;
            $this->semValue = new Expr\Array_($this->semStack[$this->stackPos-(3-2)], $attrs);
    }

    protected function reduceRule379() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule380() {
         $attrs = $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = ($this->semStack[$this->stackPos-(4-1)][0] === "'" || ($this->semStack[$this->stackPos-(4-1)][1] === "'" && ($this->semStack[$this->stackPos-(4-1)][0] === 'b' || $this->semStack[$this->stackPos-(4-1)][0] === 'B')) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED);
            $this->semValue = new Expr\ArrayDimFetch(new Scalar\String_(Scalar\String_::parse($this->semStack[$this->stackPos-(4-1)]), $attrs), $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule381() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule382() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule383() {
         $this->semValue = array(new Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$this->stackPos-(7-3)], 'implements' => $this->semStack[$this->stackPos-(7-4)], 'stmts' => $this->semStack[$this->stackPos-(7-6)]], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(7-2)]);
            $this->checkClass($this->semValue[0], -1);
    }

    protected function reduceRule384() {
         $this->semValue = new Expr\New_($this->semStack[$this->stackPos-(3-2)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule385() {
         list($class, $ctorArgs) = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule386() {
         $this->semValue = array();
    }

    protected function reduceRule387() {
         $this->semValue = $this->semStack[$this->stackPos-(4-3)];
    }

    protected function reduceRule388() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule389() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule390() {
         $this->semValue = new Expr\ClosureUse(substr($this->semStack[$this->stackPos-(2-2)], 1), $this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule391() {
         $this->semValue = new Expr\FuncCall($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule392() {
         $this->semValue = new Expr\StaticCall($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule393() {
         $this->semValue = new Expr\StaticCall($this->semStack[$this->stackPos-(6-1)], $this->semStack[$this->stackPos-(6-4)], $this->semStack[$this->stackPos-(6-6)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes);
    }

    protected function reduceRule394() {

            if ($this->semStack[$this->stackPos-(2-1)] instanceof Node\Expr\StaticPropertyFetch) {
                $this->semValue = new Expr\StaticCall($this->semStack[$this->stackPos-(2-1)]->class, new Expr\Variable($this->semStack[$this->stackPos-(2-1)]->name, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
            } elseif ($this->semStack[$this->stackPos-(2-1)] instanceof Node\Expr\ArrayDimFetch) {
                $tmp = $this->semStack[$this->stackPos-(2-1)];
                while ($tmp->var instanceof Node\Expr\ArrayDimFetch) {
                    $tmp = $tmp->var;
                }

                $this->semValue = new Expr\StaticCall($tmp->var->class, $this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
                $tmp->var = new Expr\Variable($tmp->var->name, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
            } else {
                throw new \Exception;
            }

    }

    protected function reduceRule395() {
         $this->semValue = new Expr\FuncCall($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule396() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule397() {
         $this->semValue = new Name($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule398() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule399() {
         $this->semValue = new Name($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule400() {
         $this->semValue = new Name\FullyQualified($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule401() {
         $this->semValue = new Name\Relative($this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule402() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule403() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule404() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule405() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule406() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule407() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule408() {
         $this->semValue = new Expr\PropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule409() {
         $this->semValue = new Expr\PropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule410() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule411() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule412() {
         $this->semValue = null;
    }

    protected function reduceRule413() {
         $this->semValue = null;
    }

    protected function reduceRule414() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule415() {
         $this->semValue = array();
    }

    protected function reduceRule416() {
         $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$this->stackPos-(1-1)], '`', false), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes));
    }

    protected function reduceRule417() {
         foreach ($this->semStack[$this->stackPos-(1-1)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', false); } }; $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule418() {
         $this->semValue = array();
    }

    protected function reduceRule419() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule420() {
         $this->semValue = $this->parseLNumber($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes, true);
    }

    protected function reduceRule421() {
         $this->semValue = new Scalar\DNumber(Scalar\DNumber::parse($this->semStack[$this->stackPos-(1-1)]), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule422() {
         $attrs = $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes; $attrs['kind'] = ($this->semStack[$this->stackPos-(1-1)][0] === "'" || ($this->semStack[$this->stackPos-(1-1)][1] === "'" && ($this->semStack[$this->stackPos-(1-1)][0] === 'b' || $this->semStack[$this->stackPos-(1-1)][0] === 'B')) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED);
            $this->semValue = new Scalar\String_(Scalar\String_::parse($this->semStack[$this->stackPos-(1-1)], false), $attrs);
    }

    protected function reduceRule423() {
         $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule424() {
         $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule425() {
         $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule426() {
         $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule427() {
         $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule428() {
         $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule429() {
         $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule430() {
         $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule431() {
         $attrs = $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = strpos($this->semStack[$this->stackPos-(3-1)], "'") === false ? Scalar\String_::KIND_HEREDOC : Scalar\String_::KIND_NOWDOC; preg_match('/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/', $this->semStack[$this->stackPos-(3-1)], $matches); $attrs['docLabel'] = $matches[1];;
            $this->semValue = new Scalar\String_(Scalar\String_::parseDocString($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-2)], false), $attrs);
    }

    protected function reduceRule432() {
         $attrs = $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes; $attrs['kind'] = strpos($this->semStack[$this->stackPos-(2-1)], "'") === false ? Scalar\String_::KIND_HEREDOC : Scalar\String_::KIND_NOWDOC; preg_match('/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/', $this->semStack[$this->stackPos-(2-1)], $matches); $attrs['docLabel'] = $matches[1];;
            $this->semValue = new Scalar\String_('', $attrs);
    }

    protected function reduceRule433() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule434() {
         $this->semValue = new Expr\ClassConstFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule435() {
         $this->semValue = new Expr\ConstFetch($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule436() {
         $this->semValue = new Expr\Array_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule437() {
         $this->semValue = new Expr\Array_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule438() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule439() {
         $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule440() {
         $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule441() {
         $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule442() {
         $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule443() {
         $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule444() {
         $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule445() {
         $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule446() {
         $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule447() {
         $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule448() {
         $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule449() {
         $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule450() {
         $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule451() {
         $this->semValue = new Expr\BinaryOp\Div($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule452() {
         $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule453() {
         $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule454() {
         $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule455() {
         $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule456() {
         $this->semValue = new Expr\UnaryPlus($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule457() {
         $this->semValue = new Expr\UnaryMinus($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule458() {
         $this->semValue = new Expr\BooleanNot($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule459() {
         $this->semValue = new Expr\BitwiseNot($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule460() {
         $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule461() {
         $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule462() {
         $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule463() {
         $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule464() {
         $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule465() {
         $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule466() {
         $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule467() {
         $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule468() {
         $this->semValue = new Expr\Ternary($this->semStack[$this->stackPos-(5-1)], $this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-5)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
    }

    protected function reduceRule469() {
         $this->semValue = new Expr\Ternary($this->semStack[$this->stackPos-(4-1)], null, $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule470() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule471() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule472() {
         $this->semValue = new Expr\ConstFetch($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule473() {
         $this->semValue = new Expr\ClassConstFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule474() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule475() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule476() {
         $attrs = $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED;
            foreach ($this->semStack[$this->stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', true); } }; $this->semValue = new Scalar\Encapsed($this->semStack[$this->stackPos-(3-2)], $attrs);
    }

    protected function reduceRule477() {
         $attrs = $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = strpos($this->semStack[$this->stackPos-(3-1)], "'") === false ? Scalar\String_::KIND_HEREDOC : Scalar\String_::KIND_NOWDOC; preg_match('/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/', $this->semStack[$this->stackPos-(3-1)], $matches); $attrs['docLabel'] = $matches[1];;
            foreach ($this->semStack[$this->stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, null, true); } } $s->value = preg_replace('~(\r\n|\n|\r)\z~', '', $s->value); if ('' === $s->value) array_pop($this->semStack[$this->stackPos-(3-2)]);; $this->semValue = new Scalar\Encapsed($this->semStack[$this->stackPos-(3-2)], $attrs);
    }

    protected function reduceRule478() {
         $this->semValue = array();
    }

    protected function reduceRule479() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule480() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule481() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule482() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule483() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule484() {
         $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(3-3)], $this->semStack[$this->stackPos-(3-1)], false, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule485() {
         $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(1-1)], null, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule486() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule487() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule488() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule489() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule490() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(6-2)], $this->semStack[$this->stackPos-(6-5)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes);
    }

    protected function reduceRule491() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule492() {
         $this->semValue = new Expr\PropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule493() {
         $this->semValue = new Expr\MethodCall($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule494() {
         $this->semValue = new Expr\FuncCall($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule495() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule496() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule497() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule498() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule499() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule500() {
         $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule501() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule502() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule503() {
         $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule504() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule505() {
         $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$this->stackPos-(3-1)], substr($this->semStack[$this->stackPos-(3-3)], 1), $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule506() {
         $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$this->stackPos-(6-1)], $this->semStack[$this->stackPos-(6-5)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes);
    }

    protected function reduceRule507() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule508() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule509() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule510() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule511() {
         $this->semValue = new Expr\Variable(substr($this->semStack[$this->stackPos-(1-1)], 1), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule512() {
         $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule513() {
         $this->semValue = null;
    }

    protected function reduceRule514() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule515() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule516() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule517() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule518() {
         $this->semValue = new Expr\Error($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2;
    }

    protected function reduceRule519() {
         $this->semValue = new Expr\List_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule520() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule521() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule522() {
         $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(1-1)], null, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule523() {
         $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(1-1)], null, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule524() {
         $this->semValue = null;
    }

    protected function reduceRule525() {
         $this->semValue = array();
    }

    protected function reduceRule526() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule527() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule528() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule529() {
         $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(3-3)], $this->semStack[$this->stackPos-(3-1)], false, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule530() {
         $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(1-1)], null, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule531() {
         $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(4-4)], $this->semStack[$this->stackPos-(4-1)], true, $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule532() {
         $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(2-2)], null, true, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule533() {
         $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule534() {
         $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule535() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule536() {
         $this->semValue = array($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)]);
    }

    protected function reduceRule537() {
         $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule538() {
         $this->semValue = new Expr\Variable(substr($this->semStack[$this->stackPos-(1-1)], 1), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule539() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule540() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule541() {
         $this->semValue = new Expr\PropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule542() {
         $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule543() {
         $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule544() {
         $this->semValue = new Expr\ArrayDimFetch(new Expr\Variable($this->semStack[$this->stackPos-(6-2)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(6-4)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes);
    }

    protected function reduceRule545() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule546() {
         $this->semValue = new Scalar\String_($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule547() {
         $this->semValue = $this->parseNumString($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule548() {
         $this->semValue = new Expr\Variable(substr($this->semStack[$this->stackPos-(1-1)], 1), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }
}
<?php

namespace PhpParser\Parser;

use PhpParser\Error;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar;
use PhpParser\Node\Stmt;

/* This is an automatically GENERATED file, which should not be manually edited.
 * Instead edit one of the following:
 *  * the grammar files grammar/php5.y or grammar/php7.y
 *  * the skeleton file grammar/parser.template
 *  * the preprocessing script grammar/rebuildParsers.php
 */
class Php7 extends \PhpParser\ParserAbstract
{
    protected $tokenToSymbolMapSize = 392;
    protected $actionTableSize = 891;
    protected $gotoTableSize = 429;

    protected $invalidSymbol = 157;
    protected $errorSymbol = 1;
    protected $defaultAction = -32766;
    protected $unexpectedTokenRule = 32767;

    protected $YY2TBLSTATE  = 328;
    protected $YYNLSTATES   = 576;

    protected $symbolToName = array(
        "EOF",
        "error",
        "T_INCLUDE",
        "T_INCLUDE_ONCE",
        "T_EVAL",
        "T_REQUIRE",
        "T_REQUIRE_ONCE",
        "','",
        "T_LOGICAL_OR",
        "T_LOGICAL_XOR",
        "T_LOGICAL_AND",
        "T_PRINT",
        "T_YIELD",
        "T_DOUBLE_ARROW",
        "T_YIELD_FROM",
        "'='",
        "T_PLUS_EQUAL",
        "T_MINUS_EQUAL",
        "T_MUL_EQUAL",
        "T_DIV_EQUAL",
        "T_CONCAT_EQUAL",
        "T_MOD_EQUAL",
        "T_AND_EQUAL",
        "T_OR_EQUAL",
        "T_XOR_EQUAL",
        "T_SL_EQUAL",
        "T_SR_EQUAL",
        "T_POW_EQUAL",
        "'?'",
        "':'",
        "T_COALESCE",
        "T_BOOLEAN_OR",
        "T_BOOLEAN_AND",
        "'|'",
        "'^'",
        "'&'",
        "T_IS_EQUAL",
        "T_IS_NOT_EQUAL",
        "T_IS_IDENTICAL",
        "T_IS_NOT_IDENTICAL",
        "T_SPACESHIP",
        "'<'",
        "T_IS_SMALLER_OR_EQUAL",
        "'>'",
        "T_IS_GREATER_OR_EQUAL",
        "T_SL",
        "T_SR",
        "'+'",
        "'-'",
        "'.'",
        "'*'",
        "'/'",
        "'%'",
        "'!'",
        "T_INSTANCEOF",
        "'~'",
        "T_INC",
        "T_DEC",
        "T_INT_CAST",
        "T_DOUBLE_CAST",
        "T_STRING_CAST",
        "T_ARRAY_CAST",
        "T_OBJECT_CAST",
        "T_BOOL_CAST",
        "T_UNSET_CAST",
        "'@'",
        "T_POW",
        "'['",
        "T_NEW",
        "T_CLONE",
        "T_EXIT",
        "T_IF",
        "T_ELSEIF",
        "T_ELSE",
        "T_ENDIF",
        "T_LNUMBER",
        "T_DNUMBER",
        "T_STRING",
        "T_STRING_VARNAME",
        "T_VARIABLE",
        "T_NUM_STRING",
        "T_INLINE_HTML",
        "T_ENCAPSED_AND_WHITESPACE",
        "T_CONSTANT_ENCAPSED_STRING",
        "T_ECHO",
        "T_DO",
        "T_WHILE",
        "T_ENDWHILE",
        "T_FOR",
        "T_ENDFOR",
        "T_FOREACH",
        "T_ENDFOREACH",
        "T_DECLARE",
        "T_ENDDECLARE",
        "T_AS",
        "T_SWITCH",
        "T_ENDSWITCH",
        "T_CASE",
        "T_DEFAULT",
        "T_BREAK",
        "T_CONTINUE",
        "T_GOTO",
        "T_FUNCTION",
        "T_CONST",
        "T_RETURN",
        "T_TRY",
        "T_CATCH",
        "T_FINALLY",
        "T_THROW",
        "T_USE",
        "T_INSTEADOF",
        "T_GLOBAL",
        "T_STATIC",
        "T_ABSTRACT",
        "T_FINAL",
        "T_PRIVATE",
        "T_PROTECTED",
        "T_PUBLIC",
        "T_VAR",
        "T_UNSET",
        "T_ISSET",
        "T_EMPTY",
        "T_HALT_COMPILER",
        "T_CLASS",
        "T_TRAIT",
        "T_INTERFACE",
        "T_EXTENDS",
        "T_IMPLEMENTS",
        "T_OBJECT_OPERATOR",
        "T_LIST",
        "T_ARRAY",
        "T_CALLABLE",
        "T_CLASS_C",
        "T_TRAIT_C",
        "T_METHOD_C",
        "T_FUNC_C",
        "T_LINE",
        "T_FILE",
        "T_START_HEREDOC",
        "T_END_HEREDOC",
        "T_DOLLAR_OPEN_CURLY_BRACES",
        "T_CURLY_OPEN",
        "T_PAAMAYIM_NEKUDOTAYIM",
        "T_NAMESPACE",
        "T_NS_C",
        "T_DIR",
        "T_NS_SEPARATOR",
        "T_ELLIPSIS",
        "';'",
        "'{'",
        "'}'",
        "'('",
        "')'",
        "'`'",
        "']'",
        "'\"'",
        "'$'"
    );

    protected $tokenToSymbol = array(
            0,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,   53,  155,  157,  156,   52,   35,  157,
          151,  152,   50,   47,    7,   48,   49,   51,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,   29,  148,
           41,   15,   43,   28,   65,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,   67,  157,  154,   34,  157,  153,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  149,   33,  150,   55,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,  157,  157,  157,  157,
          157,  157,  157,  157,  157,  157,    1,    2,    3,    4,
            5,    6,    8,    9,   10,   11,   12,   13,   14,   16,
           17,   18,   19,   20,   21,   22,   23,   24,   25,   26,
           27,   30,   31,   32,   36,   37,   38,   39,   40,   42,
           44,   45,   46,   54,   56,   57,   58,   59,   60,   61,
           62,   63,   64,   66,   68,   69,   70,   71,   72,   73,
           74,   75,   76,   77,   78,   79,   80,   81,  157,  157,
           82,   83,   84,   85,   86,   87,   88,   89,   90,   91,
           92,   93,   94,   95,   96,   97,   98,   99,  100,  101,
          102,  103,  104,  105,  106,  107,  108,  109,  110,  111,
          112,  113,  114,  115,  116,  117,  118,  119,  120,  121,
          122,  123,  124,  125,  126,  127,  128,  129,  130,  131,
          132,  133,  134,  135,  136,  137,  157,  157,  157,  157,
          157,  157,  138,  139,  140,  141,  142,  143,  144,  145,
          146,  147
    );

    protected $action = array(
          581,  582,  583,  584,  585,    0,  586,  587,  588,  624,
          625,  477,   27,   99,  100,  101,  102,  103,  104,  105,
          106,  107,  108,  109,  110,-32766,-32766,-32766,   95,   96,
           97,  361,  239,  263, -282,-32766,-32766,-32766, -488, -487,
         1079,  542, 1082, 1080,   98,-32766,  272,-32766,-32766,-32766,
        -32766,-32766,  589,  899,  901,-32766,-32766,-32766,-32766,-32766,
        -32766,-32766,-32766,  240,-32766,  662,  590,  591,  592,  593,
          594,  595,  596,-32766,  289,  656,  867,  868,  869,  866,
          865,  864,  597,  598,  599,  600,  601,  602,  603,  604,
          605,  606,  607,  627,  628,  629,  630,  631,  619,  620,
          621,  622,  623,  608,  609,  610,  611,  612,  613,  614,
          650,  651,  652,  653,  654,  655,  615,  616,  617,  618,
          648,  639,  637,  638,  634,  635,  215,  626,  632,  633,
          640,  641,  643,  642,  644,  645,   42,   43,  390,   44,
           45,  636,  647,  646,  224,   46,   47,  982,   48,-32767,
        -32767,-32767,-32767,   90,   91,   92,   93,   94,  258,  440,
           22,  867,  868,  869,  866,  865,  864,  859,-32766,-32766,
        -32766, 1071, 1032, 1032, 1070, 1049,  998,  293, -443,  246,
          287,   49,   50, -488, -487, -488, -487,   51,-32766,   52,
          219,  220,   53,   54,   55,   56,   57,   58,   59,   60,
          125,   22,  232,   61,  345,  975,-32766,-32766,-32766,  999,
         1000,  658,  661, 1032,   28, -477, 1012,  998,-32766,-32766,
        -32766,  737,  407,  408,  246, 1032,-32766,  246,-32766,-32766,
        -32766,-32766,   25,  222,  373,  385,  349,  226,-32766, -443,
        -32766,-32766,-32766, 1035,   65,  342,  416,  216,   41,  264,
          264, 1046,    7, -443,  403,  404,  120,   21,  975,   24,
         -443,  822, -446,  407,  408, -227, 1004, 1005, 1006, 1007,
         1001, 1002,  243,  116, -442, -441,  265,  417, 1008, 1003,
          347,  816,  817, 1076,  994,   63,  369,  255,  362,  260,
          264,  391, -133, -133, -133,   -4,  737,  392,  658,  224,
         -441,  727,  264,  -88,   32,   17,  393, -133,  394, -133,
          395, -133,  396, -133,  128,  397, -133, -133, -133,   34,
           35,  398,  346,  122,   36,  399,  816,  817,   62,  816,
          817,  286,  288,  400,  401, -442, -441,  465, -251,  402,
           38,   40,  713,  758,  405,  406, -172,   22, -232, -442,
         -441,-32766,-32766,-32766,  374, -173, -442, -441, -445, 1032,
         -477, -441, 1032,  998,  417, -479,  391,  347,  739,  547,
         -133,-32766,  392,-32766,-32766, -441,  727,  678,  679,   32,
           17,  393, -441,  394,  276,  395,  357,  396,  789,  549,
          397,   71,  975, 1050,   34,   35,  398,  346,  335,   36,
          399,  247,  248,   62,  254,  737,  286,  288,  400,  401,
          408,  120,  131,  530,  402,  982,  306,  670,  758,  405,
          406,  337,  113,  115,-32766,-32766,   72,   73,   74,  242,
          529,   65,  121,  553,  502,   18,  264,  126,  274,  264,
        -32766,-32766,-32766,  739,  547,   -4,   26,  751,   75,   76,
           77,   78,   79,   80,   81,   82,   83,   84,   85,   86,
           87,   88,   89,   90,   91,   92,   93,   94,   95,   96,
           97,  111,  239,  118,  737,  391,   92,   93,   94,  531,
          112,  392,  347, -251,   98,  727,  845,  124,   32,   17,
          393, -172,  394, 1032,  395,  130,  396,  515,  516,  397,
         -173,  117,  554,   34,   35,  398,  737,  790,   36,  399,
         -479,  736,   62,  383,    6,  286,  288,-32766,-32766,-32766,
          127,  311,  114,  402,  678,  679,  975,  495,  496,  816,
          817,  856,  565,  119,  552,  844,  575,  343,  223,  564,
          559,  221,  225,  239,  391,   98,  658,  439,   39,  525,
          392,  659,  775,  547,  727,  435,  971,   32,   17,  393,
          358,  394,  356,  395,  299,  396,  319,  694,  397, 1074,
          264,  451,   34,   35,  398,  737,  391,   36,  399,  453,
          511,   62,  392,  449,  286,  288,  727,  499,  540,   32,
           17,  393,  402,  394,  438,  395, 1081,  396,  354,  444,
          397,-32766,  493,  551,   34,   35,  398,  737,  503,   36,
          399,  526,  -80,   62,  759,  507,  286,  288,  214,  456,
           10,  739,  547,  519,  402,  508,  975,  257,   15,    0,
          338,    0,    0,  259, 1011,  560,  760, 1014,  262,    0,
            0,    0,    0,    0,    0,  391,    0,    0,    0,    0,
            0,  392,    0,  739,  547,  727,  227,  256,   32,   17,
          393,    0,  394,    0,  395,    0,  396,    0,    0,  397,
            3,    0,    9,   34,   35,  398,  737,  391,   36,  399,
          305, -400,   62,  392,  753,  286,  288,  727,   22,  339,
           32,   17,  393,  402,  394,  327,  395,  324,  396,  316,
         1032,  397,  323,  357,  998,   34,   35,  398,  446,  773,
           36,  399,   31,  573,   62,  574,  718,  286,  288,  840,
          850,  792,  739,  547,   30,  402,  849,  852,  851,  848,
          771,  776,  716,  975,  784,  841,  783,   19,  548,  333,
          550,  555,  557,  558,  270,  271,  391,  332,  571,  570,
          407,  408,  392,  568,  739,  547,  727,  566,  563,   32,
           17,  393,  562,  394,  757,  395,  756,  396,  755,  963,
          397, -444,   65,  857,   34,   35,  398,  264,  744,   36,
          399,  962,  961,   62,  754,  746,  286,  288,-32766,-32766,
        -32766,  681, 1077,  680,  402,  683,  682,  672,  673,  782,
          567,  714, 1078,  781, 1047, 1044, 1039, 1026,-32766, 1033,
        -32766,-32766,-32766,-32766,-32766,-32766,-32767,-32767,-32767,-32767,
        -32767, 1075,  250,  739,  547, -467,  955, -446, -445,   20,
           23,   29,   33,   37,   64,  336,  334,  273,  238,  237,
          236,  235,  218,  217,  132,  129,  123,   70,   69,   68,
           67,   66, -469,    0,  308,  473,  939,  489,  539, -230,
          942,   11,  967,  823,  996,  938,  986,  536,  388,  -88,
          381,  378,  375,  309,   16,   14,   13,   12, -227, -228,
            0, -412,    0,  995,  501, 1073, 1038, 1025, 1024,    0,
         1013
    );

    protected $actionCheck = array(
            2,    3,    4,    5,    6,    0,    8,    9,   10,   11,
           12,   48,   15,   16,   17,   18,   19,   20,   21,   22,
           23,   24,   25,   26,   27,    8,    9,   10,   50,   51,
           52,    7,   54,    7,   79,    8,    9,   10,    7,    7,
           77,   77,   79,   80,   66,   28,    7,   30,   31,   32,
           33,   34,   54,   56,   57,   28,    8,   30,   31,   32,
           33,   34,   35,    7,  109,    1,   68,   69,   70,   71,
           72,   73,   74,  118,    7,   77,  112,  113,  114,  115,
          116,  117,   84,   85,   86,   87,   88,   89,   90,   91,
           92,   93,   94,   95,   96,   97,   98,   99,  100,  101,
          102,  103,  104,  105,  106,  107,  108,  109,  110,  111,
          112,  113,  114,  115,  116,  117,  118,  119,  120,  121,
          122,  123,  124,  125,  126,  127,   13,  129,  130,  131,
          132,  133,  134,  135,  136,  137,    2,    3,    4,    5,
            6,  143,  144,  145,   35,   11,   12,    1,   14,   41,
           42,   43,   44,   45,   46,   47,   48,   49,  109,   82,
           67,  112,  113,  114,  115,  116,  117,  118,    8,    9,
           10,   79,   79,   79,   82,    1,   83,    7,   67,   28,
            7,   47,   48,  152,  152,  154,  154,   53,   28,   55,
           56,   57,   58,   59,   60,   61,   62,   63,   64,   65,
           67,   67,   68,   69,   70,  112,    8,    9,   10,   75,
           76,   77,  148,   79,   13,    7,  139,   83,    8,    9,
           10,    1,  129,  130,   28,   79,   28,   28,   30,   31,
           32,   33,  140,  141,   29,    7,  102,    7,   28,  128,
           30,   31,   32,    1,  151,    7,  112,   13,    7,  156,
          156,   77,    7,  142,  120,  121,  147,    7,  112,    7,
          149,  152,  151,  129,  130,  152,  132,  133,  134,  135,
          136,  137,  138,    7,   67,   67,   67,  143,  144,  145,
          146,  130,  131,  150,    1,  151,    7,  153,    7,  155,
          156,   71,   72,   73,   74,    0,    1,   77,   77,   35,
           67,   81,  156,  152,   84,   85,   86,   87,   88,   89,
           90,   91,   92,   93,   15,   95,   96,   97,   98,   99,
          100,  101,  102,  149,  104,  105,  130,  131,  108,  130,
          131,  111,  112,  113,  114,  128,  128,  128,    7,  119,
           67,   67,  122,  123,  124,  125,    7,   67,  152,  142,
          142,    8,    9,   10,  149,    7,  149,  149,  151,   79,
          152,  128,   79,   83,  143,    7,   71,  146,  148,  149,
          150,   28,   77,   30,   31,  142,   81,  102,  103,   84,
           85,   86,  149,   88,   33,   90,  146,   92,   29,  149,
           95,  149,  112,  152,   99,  100,  101,  102,  103,  104,
          105,  128,  128,  108,  109,    1,  111,  112,  113,  114,
          130,  147,   15,   77,  119,    1,  142,  122,  123,  124,
          125,  146,  149,  149,    8,    9,    8,    9,   10,   29,
           79,  151,  149,   29,   72,   73,  156,   29,  143,  156,
            8,    9,   10,  148,  149,  150,   28,   35,   30,   31,
           32,   33,   34,   35,   36,   37,   38,   39,   40,   41,
           42,   43,   44,   45,   46,   47,   48,   49,   50,   51,
           52,   15,   54,   15,    1,   71,   47,   48,   49,  143,
           15,   77,  146,  152,   66,   81,  150,   15,   84,   85,
           86,  152,   88,   79,   90,   15,   92,   72,   73,   95,
          152,   15,   29,   99,  100,  101,    1,  148,  104,  105,
          152,   29,  108,  102,  103,  111,  112,    8,    9,   10,
           97,   98,   13,  119,  102,  103,  112,  106,  107,  130,
          131,  148,  149,   29,   29,  148,  149,  123,   35,   29,
           29,   35,   35,   54,   71,   66,   77,   77,   67,   74,
           77,   77,  148,  149,   81,   77,   79,   84,   85,   86,
           77,   88,   77,   90,   77,   92,   78,   77,   95,   77,
          156,   77,   99,  100,  101,    1,   71,  104,  105,   77,
           79,  108,   77,   86,  111,  112,   81,   79,   89,   84,
           85,   86,  119,   88,   79,   90,   80,   92,  102,   82,
           95,   82,  109,   29,   99,  100,  101,    1,   87,  104,
          105,   91,   94,  108,  123,   93,  111,  112,   94,   94,
           94,  148,  149,   96,  119,   96,  112,  127,  152,   -1,
          146,   -1,   -1,  110,  139,   29,  123,  139,  126,   -1,
           -1,   -1,   -1,   -1,   -1,   71,   -1,   -1,   -1,   -1,
           -1,   77,   -1,  148,  149,   81,   35,  126,   84,   85,
           86,   -1,   88,   -1,   90,   -1,   92,   -1,   -1,   95,
          142,   -1,  142,   99,  100,  101,    1,   71,  104,  105,
          142,  142,  108,   77,  147,  111,  112,   81,   67,  146,
           84,   85,   86,  119,   88,  146,   90,  146,   92,  146,
           79,   95,  146,  146,   83,   99,  100,  101,  146,  148,
          104,  105,  148,  148,  108,  148,  148,  111,  112,  148,
          148,  148,  148,  149,  148,  119,  148,  148,  148,  148,
          148,  148,  148,  112,  148,  148,  148,  152,  149,  149,
          149,  149,  149,  149,  149,  149,   71,  149,  149,  149,
          129,  130,   77,  149,  148,  149,   81,  149,  149,   84,
           85,   86,  149,   88,  150,   90,  150,   92,  150,  150,
           95,  151,  151,  150,   99,  100,  101,  156,  150,  104,
          105,  150,  150,  108,  150,  150,  111,  112,    8,    9,
           10,  150,  150,  150,  119,  150,  150,  150,  150,  150,
          150,  150,  150,  150,  150,  150,  150,  150,   28,  150,
           30,   31,   32,   33,   34,   35,   36,   37,   38,   39,
           40,  150,  152,  148,  149,  151,  153,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,   -1,  152,  152,  152,  152,  152,  152,
          152,  152,  152,  152,  152,  152,  152,  152,  152,  152,
          152,  152,  152,  152,  152,  152,  152,  152,  152,  152,
           -1,  153,   -1,  154,  154,  154,  154,  154,  154,   -1,
          155
    );

    protected $actionBase = array(
            0,  220,  295,  283,  336,  572,   -2,   -2,   -2,   -2,
          -36,  505,  473,  606,  473,  574,  404,  675,  675,  675,
          109,  264,  506,  506,  506,  488,  504,  503,  507,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,   64,   64,  359,  201,  670,  708,  703,
          476,  709,  524,  702,  704,  234,  671,  659,  408,  657,
          656,  655,  654,  705,  730,  585,  706,  418,  418,  418,
          418,  418,  418,  418,  418,  418,  418,  418,  418,  418,
          418,  418,  418,   48,  509,  416,  432,  432,  432,  432,
          432,  432,  432,  432,  432,  432,  432,  432,  432,  432,
          432,  432,  432,  432,  432,  160,  160,  160,  343,  210,
          208,  198,   17,  233,   27,  780,  780,  780,  780,  780,
          108,  108,  108,  108,  621,  621,   93,  280,  280,  280,
          280,  280,  280,  280,  280,  280,  280,  280,  614,  616,
          618,  619,  414,  429,  429,  196,  196,  196,  196,  146,
          151,  -45,  199,   77,  498,  735,  399,  174,  174,  111,
          207,  -22,  -22,  -22,  275,  517,  514,  514,  514,  514,
           92,   92,  514,  514,  242,  -37,  233,  233,  274,  233,
          422,  422,  422,  221,  240,  519,  221,  591,  529,  653,
          527,  649,  273,   31,   32,  484,   94,  543,  496,   94,
          421,  362,  425,  717,   64,  539,   64,   64,   64,   64,
           64,   64,   64,   64,   64,   94,   94,   64,  205,   64,
          387,  359,  383,  489,  502,  209,  595,  339,  241,  133,
          489,  489,  489,  596,  598,  331,  113,  590,  348,  411,
          358,  351,  469,  469,  412,  478,  494,  469,  469,  469,
          469,  508,  469,  678,  678,  682,  412,  469,  678,  412,
          266,   24,  173,   67,  412,  281,  531,  469,  512,  512,
          279,  478,  515,  230,  250,  500,  678,  678,  500,  494,
           56,  412,   26,  565,  567,  493,  537,   39,  400,  400,
          238,  493,  228,  412,  400,  508,  245,  170,  400,    5,
          683,  700,  482,  699,  680,  698,  684,  697,  487,  589,
          491,  513,  692,  691,  696,  470,  485,  681,  679,  562,
          483,  456,  465,  528,  481,  620,  496,  557,  479,  479,
          479,  481,  676,  479,  479,  479,  479,  479,  479,  479,
          479,  729,  252,  538,  497,  486,  553,  525,  458,  608,
          495,  562,  562,  651,  728,  673,  474,  690,  714,  695,
          576,  472,  722,  689,  650,  556,  490,  551,  688,  721,
          713,  604,  456,  712,  652,  492,  562,  648,  479,  674,
          701,  734,  733,  677,  732,  720,  549,  516,  731,  647,
          711,  600,  599,  564,  725,  707,  719,  646,  718,  568,
          521,  727,  522,  685,  501,  686,  592,  645,  643,  299,
          571,  642,  694,  573,  724,  723,  726,  583,  588,  593,
          594,  480,  641,  397,  587,  693,  511,  475,  520,  586,
          477,  710,  635,  613,  687,  584,  561,  634,  632,  715,
          518,  557,  530,  523,  526,  499,  609,  631,  716,  510,
          582,  581,  580,  579,  628,  578,  623,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,  134,  134,   -2,
           -2,   -2,    0,    0,    0,    0,   -2,  134,  134,  134,
          134,  134,  134,  134,  134,  134,  134,  134,  134,  134,
          134,  134,  134,  134,  134,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,  418,
          418,  418,  418,  418,  418,  418,  418,  418,  418,  418,
          418,  418,  418,  418,  418,  418,  418,  418,  418,  418,
          418,  418,  418,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,  418,
          418,  418,  418,  418,  418,  418,  418,  418,  418,  418,
          418,  418,  418,  418,  418,  418,  418,  418,  418,  418,
          418,  418,  418,  418,  418,  418,   -3,  418,  418,   -3,
          418,  418,  418,  418,  418,  418,  -22,  -22,  -22,  -22,
          221,  221,  221,  221,  221,  221,  221,  221,  221,  221,
          221,  221,  221,  221,   49,   49,   49,   49,  221,  -22,
          -22,  221,  221,  221,  221,  221,  221,   49,  221,   92,
           92,   92,  221,   94,   94,    0,    0,    0,    0,    0,
          469,   92,  221,  221,  221,  221,    0,    0,  221,  221,
           94,    0,    0,    0,    0,    0,  469,  469,  469,    0,
          469,   92,    0,   64,  423,  423,  423,  423,    0,    0,
            0,  469,    0,  469,  515,    0,    0,    0,    0,  412,
            0,  678,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,  479,
          690,    0,  474,    0,    0,    0,  479,  479,  479,  474,
          474,    0,    0,  474
    );

    protected $actionDefault = array(
            3,32767,32767,32767,32767,32767,32767,   88,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,   88,  489,  489,  489,32767,32767,32767,32767,  302,
          302,  302,32767,  481,  439,  439,  439,  439,  439,  439,
          439,  481,32767,32767,32767,32767,32767,  381,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,   88,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,  486,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,  364,  365,  367,
          368,  301,  440,  250,  485,  300,  126,  261,  252,  204,
          298,  236,  130,  329,  382,  331,  380,  384,  330,  307,
          311,  312,  313,  314,  315,  316,  317,  318,  319,  320,
          321,  322,  305,  306,  383,  361,  360,  359,  327,  328,
          304,  332,  334,  304,  333,  350,  351,  348,  349,  352,
          353,  354,  355,  356,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,   88,32767,  284,  284,
          284,  284,32767,  341,  342,  242,  242,  242,  242,32767,
          242,  285,32767,32767,32767,32767,32767,32767,32767,  433,
          358,  336,  337,  335,32767,  411,32767,32767,32767,32767,
        32767,  413,32767,   88,32767,32767,  324,  326,  405,  308,
        32767,32767,   90,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,  408,  441,  441,32767,32767,   88,  399,   88,
          169,  223,  225,  174,32767,  416,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,  346,32767,  496,32767,  441,32767,32767,
          338,  339,  340,32767,32767,  441,  441,32767,  441,32767,
          441,32767,32767,32767,  174,32767,32767,32767,32767,32767,
        32767,32767,   90,  414,  414,  409,  174,32767,32767,  174,
           87,   87,   87,   87,  174,   87,  187,32767,  185,  185,
           87,   88,   88,   87,   87,  189,32767,  455,  189,   88,
           87,  174,   87,  209,  209,  390,  176,   89,  244,  244,
           89,  390,   87,  174,  244,   88,   87,   87,  244,32767,
        32767,32767,   82,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,  401,
        32767,32767,  421,32767,  434,  453,  399,32767,  344,  345,
          347,32767,  443,  369,  370,  371,  372,  373,  374,  375,
          377,32767,  482,  404,32767,32767,   84,  117,  260,32767,
          494,   84,  402,32767,  494,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,   84,32767,   84,32767,32767,
        32767,32767,  478,32767,  441,32767,  403,32767,  343,  417,
          460,32767,32767,  442,32767,32767,   84,32767,32767,32767,
        32767,32767,32767,32767,32767,  421,32767,32767,32767,32767,
        32767,  441,32767,32767,32767,32767,32767,32767,32767,  297,
        32767,32767,32767,32767,32767,32767,  441,32767,32767,32767,
        32767,  235,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
           82,   60,32767,  278,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,  132,  132,    3,
            3,  132,  132,  132,  132,  132,  132,  132,  132,  132,
          132,  132,  132,  132,  132,  132,  263,  164,  263,  217,
          263,  263,  220,  209,  209,  270
    );

    protected $goto = array(
          163,  163,  136,  136,  136,  146,  148,  179,  164,  161,
          161,  161,  161,  145,  162,  162,  162,  162,  162,  162,
          162,  145,  157,  158,  159,  160,  176,  174,  177,  418,
          419,  313,  420,  423,  424,  425,  426,  427,  428,  429,
          430,  886,  134,  137,  138,  139,  140,  141,  142,  143,
          144,  147,  173,  175,  178,  195,  198,  199,  201,  202,
          204,  205,  206,  207,  208,  209,  210,  211,  212,  213,
          233,  234,  251,  252,  253,  320,  321,  322,  468,  180,
          181,  182,  183,  184,  185,  186,  187,  188,  189,  190,
          191,  192,  193,  149,  194,  150,  165,  166,  167,  196,
          168,  151,  152,  153,  169,  154,  197,  135,  170,  155,
          171,  172,  156,  532,  200,  436,  734,  704,  469,  855,
          545,  279,  200,  524,  853,  470,  710,  667,    5,  462,
          669,  441,  441,  441,  261,  441,  791,  462,  770,  245,
          569,  668,  434,  800,  795,  543,  457,  454,  441,  774,
          572,  490,  492,  518,  522,  788,  527,  528,  802,  535,
          787,  537,  544,  798,  546,  422,  422,  422,  422,  422,
          422,  422,  422,  422,  422,  422,  422,  422,  422,  421,
          421,  421,  421,  421,  421,  421,  421,  421,  421,  421,
          421,  421,  421,  441,  441,  486,  488,  538,  455,  476,
          441,  441,  972,  441,  229,  731,  230,  231,  442,  298,
          301,  448,  471,  472,  474,  766,  310,  541,  466,  485,
          485,  997,  997,  997,  997,  997,  997,  997,  997,  997,
          997,  997,  997,  699,  687,  829,  433,  833,  463,  695,
         1066, 1066,  777,  433,  825,  747,  480,  483,  504, 1059,
          314,  296,  807,  447,  767,  973,  505, 1066,  458,  671,
          768,  768,  768,  768,  870, 1051,  762,  769,  703,  968,
          695, 1069,  695,  974, 1028,  376,  676,  460,  726,  721,
          722,  735,  677,  723,  674,  724,  725,    8,  933,  675,
          810,  729, 1067, 1067,  821,  326,  506,  330,  317,  317,
          266,  267,  283,  464,  269,  325,  284,  328,  491, 1067,
          805,  805, 1056,  467,  479,  814, 1040,  686,  686,  285,
          280,  281,  696,  696,  696,  698,  510,  685,  497,  277,
          691,  523,  307,  688,  830,  312,  556,  969,  964,  512,
          368,  976,  482,  684,  815,  815,  815,  815,  976,  815,
          700,  815,  834,  779, 1037,  815,  384,  872,    0,  863,
            0, 1037,    0,    0,    0,  976,  976,  976,  976, 1048,
         1048,  976,  976,    0,    0,    0,    0,    0,    0,    0,
            0,    0,  742,    0,    0,  743, 1034,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,  832,    0,
            0,  832,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0, 1041, 1042
    );

    protected $gotoCheck = array(
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   60,   53,    8,   10,   33,    7,    7,
            7,   76,   53,    7,    7,   93,   13,   13,  106,   81,
           15,    8,    8,    8,  128,    8,   13,   81,   13,  128,
           13,   14,   13,   13,   13,    5,    8,   36,    8,   37,
           36,   36,   36,   36,   36,   36,   36,   36,   36,   36,
           36,   36,   36,   36,   36,  131,  131,  131,  131,  131,
          131,  131,  131,  131,  131,  131,  131,  131,  131,  129,
          129,  129,  129,  129,  129,  129,  129,  129,  129,  129,
          129,  129,  129,    8,    8,   64,   64,   64,    8,    8,
            8,    8,   88,    8,   69,   52,   69,   69,    8,   46,
           46,   46,   46,   46,   46,   72,   72,   72,    8,   82,
           82,   82,   82,   82,   82,   82,   82,   82,   82,   82,
           82,   82,   82,   11,   11,   11,   71,   11,  130,   23,
          139,  139,   11,   71,   90,   11,   11,   43,   43,  138,
           62,   49,   11,   62,   11,   88,   51,  139,   62,   10,
           71,   71,   71,   71,   11,  136,   71,   71,   11,   11,
           23,  139,   23,   88,   88,   62,   10,   50,   10,   10,
           10,   10,   10,   10,   10,   10,   10,   62,  112,   10,
           84,   10,  140,  140,   86,   53,   53,   53,   53,   53,
           53,   53,   53,   53,   53,   53,   53,   53,   53,  140,
           81,   81,   81,    2,    2,   87,  133,   23,   23,   17,
           76,   76,   23,   23,   23,   23,   65,   23,   21,    9,
           27,   65,   16,   25,   92,   65,   78,  121,  118,   20,
           67,   60,   68,   12,   60,   60,   60,   60,   60,   60,
           29,   60,   95,   75,   93,   60,  116,  109,   -1,  106,
           -1,   93,   -1,   -1,   -1,   60,   60,   60,   60,   93,
           93,   60,   60,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
           -1,   -1,   60,   -1,   -1,   60,   93,   -1,   -1,   -1,
           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   93,   -1,
           -1,   93,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
           -1,   -1,   -1,   -1,   -1,   -1,   -1,   93,   93
    );

    protected $gotoBase = array(
            0,    0, -236,    0,    0,  135,    0,  115, -139,   55,
          -18, -118,  -37,  125,  139,  128,   47,   65,    0,    0,
            6,   57,    0,  -15,    0,   46,    0,   58,    0,  -11,
          -20,    0,    0,  110,    0,    0, -401,  133,    0,    0,
            0,    0,    0,  217,    0,    0,  174,    0,    0,  219,
           59,   41,  191,   81,    0,    0,    0,    0,    0,    0,
          109,    0,  -96,    0,  -41,  -53,    0,  -19,  -26, -364,
            0,    4,  -42,    0,    0,  -16, -253,    0,   25,    0,
            0,   96,    5,    0,   50,    0,   52,   69,  -93,    0,
          223,    0,   45,  122,    0,  -10,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,  118,    0,    0,  -28,
            0,    0,   49,    0,    0,    0,  -25,    0,   -6,    0,
            0,    3,    0,    0,    0,    0,    0,    0, -121,  -35,
          215,  -49,    0,   68,    0,    0,  224,    0,  225,   -4,
           48,    0,    0
    );

    protected $gotoDefault = array(
        -32768,  389,  577,    2,  578,  649,  657,  513,  409,  437,
          728,  875,  690,  772,  711,  712,  302,  340,  294,  300,
          498,  487,  380,  697,  352,  689,  377,  692,  351,  701,
          133,  514,  386,  705,    1,  707,  443,  738,  291,  715,
          292,  517,  717,  450,  719,  720,  297,  303,  304,  879,
          459,  484,  730,  203,  452,  732,  290,  733,  741,  331,
          295,  363,  520,  494,  475,  509,  410,  365,  481,  228,
          461,  983,  764,  372,  360,  778,  278,  786,  561,  794,
          797,  411,  412,  370,  809,  371,  819,  813,  991,  364,
          824,  353,  831, 1023,  355,  835,  838,  341,  500,  329,
          842,  843,    4,  847,  533,  534,  862,  241,  382,  871,
          350,  885,  344,  952,  954,  445,  379,  965,  359,  521,
          387,  970, 1027,  348,  413,  366,  268,  282,  244,  414,
          431,  249,  415,  367, 1030,  318, 1052,  432, 1060, 1068,
          275,  315,  478
    );

    protected $ruleToNonTerminal = array(
            0,    1,    3,    3,    2,    5,    5,    5,    5,    5,
            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
            5,    5,    5,    6,    6,    6,    6,    6,    6,    6,
            7,    7,    8,    8,    9,   10,   10,   11,   11,   12,
           12,    4,    4,    4,    4,    4,    4,    4,    4,    4,
            4,    4,   17,   17,   18,   18,   18,   18,   20,   22,
           22,   16,   24,   24,   21,   26,   26,   23,   23,   25,
           25,   27,   27,   19,   28,   28,   29,   31,   32,   32,
           33,   34,   34,   36,   35,   35,   35,   35,   37,   37,
           37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
           37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
           37,   37,   13,   13,   56,   56,   59,   59,   58,   57,
           57,   50,   61,   61,   62,   62,   63,   63,   14,   15,
           15,   15,   66,   66,   66,   67,   67,   70,   70,   68,
           68,   72,   73,   73,   44,   44,   52,   52,   55,   55,
           55,   54,   74,   74,   75,   45,   45,   45,   45,   76,
           76,   77,   77,   78,   78,   42,   42,   38,   38,   79,
           40,   40,   80,   39,   39,   41,   41,   51,   51,   51,
           51,   64,   64,   83,   83,   84,   84,   86,   86,   87,
           87,   87,   85,   85,   65,   65,   88,   88,   89,   89,
           90,   90,   90,   47,   91,   91,   92,   48,   94,   94,
           95,   95,   69,   69,   96,   96,   96,   96,  101,  101,
          102,  102,  103,  103,  103,  103,  103,  104,  105,  105,
          100,  100,   97,   97,   99,   99,  107,  107,  106,  106,
          106,  106,  106,  106,   98,  108,  108,  109,  109,   49,
          110,  110,   43,   43,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
           30,   30,   30,   30,   30,   30,   30,  117,  111,  111,
          116,  116,  119,  120,  120,  121,  122,  122,  122,   71,
           71,   60,   60,   60,  112,  112,  112,  124,  124,  113,
          113,  115,  115,  115,  118,  118,  129,  129,  129,   82,
          131,  131,  131,  114,  114,  114,  114,  114,  114,  114,
          114,  114,  114,  114,  114,  114,  114,  114,  114,   46,
           46,  127,  127,  127,  123,  123,  123,  132,  132,  132,
          132,  132,  132,   53,   53,   53,   93,   93,   93,   93,
          134,  126,  126,  126,  126,  126,  126,  125,  125,  125,
          133,  133,  133,  133,   81,  135,  135,  136,  136,  136,
          136,  136,  130,  137,  137,  138,  138,  138,  138,  138,
          128,  128,  128,  128,  140,  141,  139,  139,  139,  139,
          139,  139,  139,  142,  142,  142,  142
    );

    protected $ruleToLength = array(
            1,    1,    2,    0,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    3,    1,    1,    1,    0,    1,    0,
            1,    1,    1,    1,    1,    3,    5,    4,    3,    4,
            2,    3,    1,    1,    7,    8,    6,    7,    2,    3,
            1,    2,    3,    1,    2,    3,    1,    1,    3,    1,
            2,    1,    2,    2,    3,    1,    3,    2,    3,    1,
            3,    2,    0,    1,    1,    1,    1,    1,    3,    7,
           10,    5,    7,    9,    5,    3,    3,    3,    3,    3,
            3,    1,    2,    5,    7,    9,    5,    6,    3,    3,
            2,    1,    1,    1,    0,    2,    1,    3,    8,    0,
            4,    2,    1,    3,    0,    1,    0,    1,   10,    7,
            6,    5,    1,    2,    2,    0,    2,    0,    2,    0,
            2,    2,    1,    3,    1,    4,    1,    4,    1,    1,
            4,    2,    1,    3,    3,    3,    4,    4,    5,    0,
            2,    4,    3,    1,    1,    1,    4,    0,    2,    5,
            0,    2,    6,    0,    2,    0,    3,    1,    2,    1,
            1,    2,    0,    1,    3,    4,    6,    1,    2,    1,
            1,    1,    0,    1,    0,    2,    2,    4,    1,    3,
            1,    2,    2,    2,    3,    1,    1,    2,    3,    1,
            1,    3,    2,    0,    3,    4,    9,    3,    1,    3,
            0,    2,    4,    5,    4,    4,    4,    3,    1,    1,
            1,    3,    1,    1,    0,    1,    1,    2,    1,    1,
            1,    1,    1,    1,    2,    1,    3,    1,    3,    2,
            3,    1,    0,    1,    1,    3,    3,    3,    4,    1,
            2,    3,    3,    3,    3,    3,    3,    3,    3,    3,
            3,    3,    3,    2,    2,    2,    2,    3,    3,    3,
            3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
            3,    3,    3,    3,    2,    2,    2,    2,    3,    3,
            3,    3,    3,    3,    3,    3,    3,    3,    3,    5,
            4,    3,    4,    4,    2,    2,    4,    2,    2,    2,
            2,    2,    2,    2,    2,    2,    2,    2,    1,    3,
            2,    1,    2,    4,    2,   10,   11,    7,    3,    2,
            0,    4,    2,    1,    3,    2,    2,    2,    4,    1,
            1,    1,    2,    3,    1,    1,    1,    1,    1,    0,
            3,    0,    1,    1,    0,    1,    1,    3,    3,    3,
            4,    1,    1,    1,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    1,    1,    3,    2,    3,    3,    0,
            1,    1,    3,    1,    1,    3,    1,    1,    4,    4,
            4,    1,    4,    1,    1,    3,    1,    4,    2,    2,
            3,    1,    4,    4,    3,    3,    3,    1,    3,    1,
            1,    3,    1,    1,    4,    3,    1,    1,    1,    3,
            3,    0,    1,    3,    1,    3,    1,    4,    2,    0,
            2,    2,    1,    2,    1,    1,    1,    4,    3,    3,
            3,    6,    3,    1,    1,    2,    1
    );

    protected function reduceRule0() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule1() {
         $this->semValue = $this->handleNamespaces($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule2() {
         if (is_array($this->semStack[$this->stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)]); } else { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; };
    }

    protected function reduceRule3() {
         $this->semValue = array();
    }

    protected function reduceRule4() {
         $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop(['comments' => $startAttributes['comments']]); } else { $nop = null; };
            if ($nop !== null) { $this->semStack[$this->stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule5() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule6() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule7() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule8() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule9() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule10() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule11() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule12() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule13() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule14() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule15() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule16() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule17() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule18() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule19() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule20() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule21() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule22() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule23() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule24() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule25() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule26() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule27() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule28() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule29() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule30() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule31() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule32() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule33() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule34() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule35() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule36() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule37() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule38() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule39() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule40() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule41() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule42() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule43() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule44() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule45() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule46() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule47() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule48() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule49() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule50() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule51() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule52() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule53() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule54() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule55() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule56() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule57() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule58() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule59() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule60() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule61() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule62() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule63() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule64() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule65() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule66() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule67() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule68() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule69() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule70() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule71() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule72() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule73() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule74() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule75() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule76() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule77() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule78() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule79() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule80() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule81() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule82() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule83() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule84() {
         $this->semValue = new Name($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule85() {
         /* nothing */
    }

    protected function reduceRule86() {
         /* nothing */
    }

    protected function reduceRule87() {
         /* nothing */
    }

    protected function reduceRule88() {
         $this->emitError(new Error('A trailing comma is not allowed here', $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes));
    }

    protected function reduceRule89() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule90() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule91() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule92() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule93() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule94() {
         $this->semValue = new Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule95() {
         $this->semValue = new Stmt\Namespace_($this->semStack[$this->stackPos-(3-2)], null, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON);
            $this->checkNamespace($this->semValue);
    }

    protected function reduceRule96() {
         $this->semValue = new Stmt\Namespace_($this->semStack[$this->stackPos-(5-2)], $this->semStack[$this->stackPos-(5-4)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
            $this->checkNamespace($this->semValue);
    }

    protected function reduceRule97() {
         $this->semValue = new Stmt\Namespace_(null, $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
            $this->checkNamespace($this->semValue);
    }

    protected function reduceRule98() {
         $this->semValue = new Stmt\Use_($this->semStack[$this->stackPos-(3-2)], Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule99() {
         $this->semValue = new Stmt\Use_($this->semStack[$this->stackPos-(4-3)], $this->semStack[$this->stackPos-(4-2)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule100() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule101() {
         $this->semValue = new Stmt\Const_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule102() {
         $this->semValue = Stmt\Use_::TYPE_FUNCTION;
    }

    protected function reduceRule103() {
         $this->semValue = Stmt\Use_::TYPE_CONSTANT;
    }

    protected function reduceRule104() {
         $this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(7-3)], $this->startAttributeStack[$this->stackPos-(7-3)] + $this->endAttributeStack[$this->stackPos-(7-3)]), $this->semStack[$this->stackPos-(7-6)], $this->semStack[$this->stackPos-(7-2)], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
    }

    protected function reduceRule105() {
         $this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(8-4)], $this->startAttributeStack[$this->stackPos-(8-4)] + $this->endAttributeStack[$this->stackPos-(8-4)]), $this->semStack[$this->stackPos-(8-7)], $this->semStack[$this->stackPos-(8-2)], $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes);
    }

    protected function reduceRule106() {
         $this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(6-2)], $this->startAttributeStack[$this->stackPos-(6-2)] + $this->endAttributeStack[$this->stackPos-(6-2)]), $this->semStack[$this->stackPos-(6-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes);
    }

    protected function reduceRule107() {
         $this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(7-3)], $this->startAttributeStack[$this->stackPos-(7-3)] + $this->endAttributeStack[$this->stackPos-(7-3)]), $this->semStack[$this->stackPos-(7-6)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
    }

    protected function reduceRule108() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule109() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule110() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule111() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule112() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule113() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule114() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule115() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule116() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule117() {
         $this->semValue = new Stmt\UseUse($this->semStack[$this->stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $this->stackPos-(1-1));
    }

    protected function reduceRule118() {
         $this->semValue = new Stmt\UseUse($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $this->stackPos-(3-3));
    }

    protected function reduceRule119() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule120() {
         $this->semValue = $this->semStack[$this->stackPos-(2-2)];
    }

    protected function reduceRule121() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)]; $this->semValue->type = Stmt\Use_::TYPE_NORMAL;
    }

    protected function reduceRule122() {
         $this->semValue = $this->semStack[$this->stackPos-(2-2)]; $this->semValue->type = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule123() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule124() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule125() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule126() {
         $this->semValue = new Node\Const_($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule127() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule128() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule129() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule130() {
         $this->semValue = new Node\Const_($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule131() {
         if (is_array($this->semStack[$this->stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)]); } else { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; };
    }

    protected function reduceRule132() {
         $this->semValue = array();
    }

    protected function reduceRule133() {
         $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop(['comments' => $startAttributes['comments']]); } else { $nop = null; };
            if ($nop !== null) { $this->semStack[$this->stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule134() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule135() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule136() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule137() {
         throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule138() {

        if ($this->semStack[$this->stackPos-(3-2)]) {
            $this->semValue = $this->semStack[$this->stackPos-(3-2)]; $attrs = $this->startAttributeStack[$this->stackPos-(3-1)]; $stmts = $this->semValue; if (!empty($attrs['comments'])) {$stmts[0]->setAttribute('comments', array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); };
        } else {
            $startAttributes = $this->startAttributeStack[$this->stackPos-(3-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop(['comments' => $startAttributes['comments']]); } else { $this->semValue = null; };
            if (null === $this->semValue) { $this->semValue = array(); }
        }

    }

    protected function reduceRule139() {
         $this->semValue = new Stmt\If_($this->semStack[$this->stackPos-(7-3)], ['stmts' => is_array($this->semStack[$this->stackPos-(7-5)]) ? $this->semStack[$this->stackPos-(7-5)] : array($this->semStack[$this->stackPos-(7-5)]), 'elseifs' => $this->semStack[$this->stackPos-(7-6)], 'else' => $this->semStack[$this->stackPos-(7-7)]], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
    }

    protected function reduceRule140() {
         $this->semValue = new Stmt\If_($this->semStack[$this->stackPos-(10-3)], ['stmts' => $this->semStack[$this->stackPos-(10-6)], 'elseifs' => $this->semStack[$this->stackPos-(10-7)], 'else' => $this->semStack[$this->stackPos-(10-8)]], $this->startAttributeStack[$this->stackPos-(10-1)] + $this->endAttributes);
    }

    protected function reduceRule141() {
         $this->semValue = new Stmt\While_($this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-5)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
    }

    protected function reduceRule142() {
         $this->semValue = new Stmt\Do_($this->semStack[$this->stackPos-(7-5)], is_array($this->semStack[$this->stackPos-(7-2)]) ? $this->semStack[$this->stackPos-(7-2)] : array($this->semStack[$this->stackPos-(7-2)]), $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
    }

    protected function reduceRule143() {
         $this->semValue = new Stmt\For_(['init' => $this->semStack[$this->stackPos-(9-3)], 'cond' => $this->semStack[$this->stackPos-(9-5)], 'loop' => $this->semStack[$this->stackPos-(9-7)], 'stmts' => $this->semStack[$this->stackPos-(9-9)]], $this->startAttributeStack[$this->stackPos-(9-1)] + $this->endAttributes);
    }

    protected function reduceRule144() {
         $this->semValue = new Stmt\Switch_($this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-5)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
    }

    protected function reduceRule145() {
         $this->semValue = new Stmt\Break_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule146() {
         $this->semValue = new Stmt\Continue_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule147() {
         $this->semValue = new Stmt\Return_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule148() {
         $this->semValue = new Stmt\Global_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule149() {
         $this->semValue = new Stmt\Static_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule150() {
         $this->semValue = new Stmt\Echo_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule151() {
         $this->semValue = new Stmt\InlineHTML($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule152() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule153() {
         $this->semValue = new Stmt\Unset_($this->semStack[$this->stackPos-(5-3)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
    }

    protected function reduceRule154() {
         $this->semValue = new Stmt\Foreach_($this->semStack[$this->stackPos-(7-3)], $this->semStack[$this->stackPos-(7-5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$this->stackPos-(7-5)][1], 'stmts' => $this->semStack[$this->stackPos-(7-7)]], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
    }

    protected function reduceRule155() {
         $this->semValue = new Stmt\Foreach_($this->semStack[$this->stackPos-(9-3)], $this->semStack[$this->stackPos-(9-7)][0], ['keyVar' => $this->semStack[$this->stackPos-(9-5)], 'byRef' => $this->semStack[$this->stackPos-(9-7)][1], 'stmts' => $this->semStack[$this->stackPos-(9-9)]], $this->startAttributeStack[$this->stackPos-(9-1)] + $this->endAttributes);
    }

    protected function reduceRule156() {
         $this->semValue = new Stmt\Declare_($this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-5)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
    }

    protected function reduceRule157() {
         $this->semValue = new Stmt\TryCatch($this->semStack[$this->stackPos-(6-3)], $this->semStack[$this->stackPos-(6-5)], $this->semStack[$this->stackPos-(6-6)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); $this->checkTryCatch($this->semValue);
    }

    protected function reduceRule158() {
         $this->semValue = new Stmt\Throw_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule159() {
         $this->semValue = new Stmt\Goto_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule160() {
         $this->semValue = new Stmt\Label($this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule161() {
         $this->semValue = array(); /* means: no statement */
    }

    protected function reduceRule162() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule163() {
         $startAttributes = $this->startAttributeStack[$this->stackPos-(1-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop(['comments' => $startAttributes['comments']]); } else { $this->semValue = null; };
            if ($this->semValue === null) $this->semValue = array(); /* means: no statement */
    }

    protected function reduceRule164() {
         $this->semValue = array();
    }

    protected function reduceRule165() {
         $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule166() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule167() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule168() {
         $this->semValue = new Stmt\Catch_($this->semStack[$this->stackPos-(8-3)], substr($this->semStack[$this->stackPos-(8-4)], 1), $this->semStack[$this->stackPos-(8-7)], $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes);
    }

    protected function reduceRule169() {
         $this->semValue = null;
    }

    protected function reduceRule170() {
         $this->semValue = new Stmt\Finally_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule171() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule172() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule173() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule174() {
         $this->semValue = false;
    }

    protected function reduceRule175() {
         $this->semValue = true;
    }

    protected function reduceRule176() {
         $this->semValue = false;
    }

    protected function reduceRule177() {
         $this->semValue = true;
    }

    protected function reduceRule178() {
         $this->semValue = new Stmt\Function_($this->semStack[$this->stackPos-(10-3)], ['byRef' => $this->semStack[$this->stackPos-(10-2)], 'params' => $this->semStack[$this->stackPos-(10-5)], 'returnType' => $this->semStack[$this->stackPos-(10-7)], 'stmts' => $this->semStack[$this->stackPos-(10-9)]], $this->startAttributeStack[$this->stackPos-(10-1)] + $this->endAttributes);
    }

    protected function reduceRule179() {
         $this->semValue = new Stmt\Class_($this->semStack[$this->stackPos-(7-2)], ['type' => $this->semStack[$this->stackPos-(7-1)], 'extends' => $this->semStack[$this->stackPos-(7-3)], 'implements' => $this->semStack[$this->stackPos-(7-4)], 'stmts' => $this->semStack[$this->stackPos-(7-6)]], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes);
            $this->checkClass($this->semValue, $this->stackPos-(7-2));
    }

    protected function reduceRule180() {
         $this->semValue = new Stmt\Interface_($this->semStack[$this->stackPos-(6-2)], ['extends' => $this->semStack[$this->stackPos-(6-3)], 'stmts' => $this->semStack[$this->stackPos-(6-5)]], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes);
            $this->checkInterface($this->semValue, $this->stackPos-(6-2));
    }

    protected function reduceRule181() {
         $this->semValue = new Stmt\Trait_($this->semStack[$this->stackPos-(5-2)], ['stmts' => $this->semStack[$this->stackPos-(5-4)]], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
    }

    protected function reduceRule182() {
         $this->semValue = 0;
    }

    protected function reduceRule183() {
         $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT;
    }

    protected function reduceRule184() {
         $this->semValue = Stmt\Class_::MODIFIER_FINAL;
    }

    protected function reduceRule185() {
         $this->semValue = null;
    }

    protected function reduceRule186() {
         $this->semValue = $this->semStack[$this->stackPos-(2-2)];
    }

    protected function reduceRule187() {
         $this->semValue = array();
    }

    protected function reduceRule188() {
         $this->semValue = $this->semStack[$this->stackPos-(2-2)];
    }

    protected function reduceRule189() {
         $this->semValue = array();
    }

    protected function reduceRule190() {
         $this->semValue = $this->semStack[$this->stackPos-(2-2)];
    }

    protected function reduceRule191() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule192() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule193() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule194() {
         $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule195() {
         $this->semValue = $this->semStack[$this->stackPos-(4-2)];
    }

    protected function reduceRule196() {
         $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule197() {
         $this->semValue = $this->semStack[$this->stackPos-(4-2)];
    }

    protected function reduceRule198() {
         $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule199() {
         $this->semValue = null;
    }

    protected function reduceRule200() {
         $this->semValue = $this->semStack[$this->stackPos-(4-2)];
    }

    protected function reduceRule201() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule202() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule203() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule204() {
         $this->semValue = new Stmt\DeclareDeclare($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule205() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule206() {
         $this->semValue = $this->semStack[$this->stackPos-(4-3)];
    }

    protected function reduceRule207() {
         $this->semValue = $this->semStack[$this->stackPos-(4-2)];
    }

    protected function reduceRule208() {
         $this->semValue = $this->semStack[$this->stackPos-(5-3)];
    }

    protected function reduceRule209() {
         $this->semValue = array();
    }

    protected function reduceRule210() {
         $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule211() {
         $this->semValue = new Stmt\Case_($this->semStack[$this->stackPos-(4-2)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule212() {
         $this->semValue = new Stmt\Case_(null, $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule213() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule214() {
        $this->semValue = $this->semStack[$this->stackPos];
    }

    protected function reduceRule215() {
         $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule216() {
         $this->semValue = $this->semStack[$this->stackPos-(4-2)];
    }

    protected function reduceRule217() {
         $this->semValue = array();
    }

    protected function reduceRule218() {
         $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule219() {
         $this->semValue = new Stmt\ElseIf_($this->semStack[$this->stackPos-(5-3)], is_array($this->semStack[$this->stackPos-(5-5)]) ? $this->semStack[$this->stackPos-(5-5)] : array($this->semStack[$this->stackPos-(5-5)]), $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
    }

    protected function reduceRule220() {
         $this->semValue = array();
    }

    protected function reduceRule221() {
         $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule222() {
         $this->semValue = new Stmt\ElseIf_($this->semStack[$this->stackPos-(6-3)], $this->semStack[$this->stackPos-(6-6)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes);
    }

    protected function reduceRule223() {
         $this->semValue = null;
    }

    protected function reduceRule224() {
         $this->semValue = new Stmt\Else_(is_array($this->semStack[$this->stackPos-(2-2)]) ? $this->semStack[$this->stackPos-(2-2)] : array($this->semStack[$this->stackPos-(2-2)]), $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule225() {
         $this->semValue = null;
    }

    protected function reduceRule226() {
         $this->semValue = new Stmt\Else_($this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule227() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)], false);
    }

    protected function reduceRule228() {
         $this->semValue = array($this->semStack[$this->stackPos-(2-2)], true);
    }

    protected function reduceRule229() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)], false);
    }

    protected function reduceRule230() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)], false);
    }

    protected function reduceRule231() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule232() {
         $this->semValue = array();
    }

    protected function reduceRule233() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule234() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule235() {
         $this->semValue = new Node\Param(substr($this->semStack[$this->stackPos-(4-4)], 1), null, $this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-2)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); $this->checkParam($this->semValue);
    }

    protected function reduceRule236() {
         $this->semValue = new Node\Param(substr($this->semStack[$this->stackPos-(6-4)], 1), $this->semStack[$this->stackPos-(6-6)], $this->semStack[$this->stackPos-(6-1)], $this->semStack[$this->stackPos-(6-2)], $this->semStack[$this->stackPos-(6-3)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); $this->checkParam($this->semValue);
    }

    protected function reduceRule237() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule238() {
         $this->semValue = new Node\NullableType($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule239() {
         $this->semValue = $this->handleBuiltinTypes($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule240() {
         $this->semValue = 'array';
    }

    protected function reduceRule241() {
         $this->semValue = 'callable';
    }

    protected function reduceRule242() {
         $this->semValue = null;
    }

    protected function reduceRule243() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule244() {
         $this->semValue = null;
    }

    protected function reduceRule245() {
         $this->semValue = $this->semStack[$this->stackPos-(2-2)];
    }

    protected function reduceRule246() {
         $this->semValue = array();
    }

    protected function reduceRule247() {
         $this->semValue = $this->semStack[$this->stackPos-(4-2)];
    }

    protected function reduceRule248() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule249() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule250() {
         $this->semValue = new Node\Arg($this->semStack[$this->stackPos-(1-1)], false, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule251() {
         $this->semValue = new Node\Arg($this->semStack[$this->stackPos-(2-2)], true, false, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule252() {
         $this->semValue = new Node\Arg($this->semStack[$this->stackPos-(2-2)], false, true, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule253() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule254() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule255() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule256() {
         $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule257() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule258() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule259() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule260() {
         $this->semValue = new Stmt\StaticVar(substr($this->semStack[$this->stackPos-(1-1)], 1), null, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule261() {
         $this->semValue = new Stmt\StaticVar(substr($this->semStack[$this->stackPos-(3-1)], 1), $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule262() {
         $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule263() {
         $this->semValue = array();
    }

    protected function reduceRule264() {
         $this->semValue = new Stmt\Property($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); $this->checkProperty($this->semValue, $this->stackPos-(3-1));
    }

    protected function reduceRule265() {
         $this->semValue = new Stmt\ClassConst($this->semStack[$this->stackPos-(4-3)], $this->semStack[$this->stackPos-(4-1)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); $this->checkClassConst($this->semValue, $this->stackPos-(4-1));
    }

    protected function reduceRule266() {
         $this->semValue = new Stmt\ClassMethod($this->semStack[$this->stackPos-(9-4)], ['type' => $this->semStack[$this->stackPos-(9-1)], 'byRef' => $this->semStack[$this->stackPos-(9-3)], 'params' => $this->semStack[$this->stackPos-(9-6)], 'returnType' => $this->semStack[$this->stackPos-(9-8)], 'stmts' => $this->semStack[$this->stackPos-(9-9)]], $this->startAttributeStack[$this->stackPos-(9-1)] + $this->endAttributes);
            $this->checkClassMethod($this->semValue, $this->stackPos-(9-1));
    }

    protected function reduceRule267() {
         $this->semValue = new Stmt\TraitUse($this->semStack[$this->stackPos-(3-2)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule268() {
         $this->semValue = array();
    }

    protected function reduceRule269() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule270() {
         $this->semValue = array();
    }

    protected function reduceRule271() {
         $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule272() {
         $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule273() {
         $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(5-1)][0], $this->semStack[$this->stackPos-(5-1)][1], $this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-4)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
    }

    protected function reduceRule274() {
         $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], $this->semStack[$this->stackPos-(4-3)], null, $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule275() {
         $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], null, $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule276() {
         $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], null, $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule277() {
         $this->semValue = array($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)]);
    }

    protected function reduceRule278() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule279() {
         $this->semValue = array(null, $this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule280() {
         $this->semValue = null;
    }

    protected function reduceRule281() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule282() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule283() {
         $this->semValue = 0;
    }

    protected function reduceRule284() {
         $this->semValue = 0;
    }

    protected function reduceRule285() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule286() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule287() {
         $this->checkModifier($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->stackPos-(2-2)); $this->semValue = $this->semStack[$this->stackPos-(2-1)] | $this->semStack[$this->stackPos-(2-2)];
    }

    protected function reduceRule288() {
         $this->semValue = Stmt\Class_::MODIFIER_PUBLIC;
    }

    protected function reduceRule289() {
         $this->semValue = Stmt\Class_::MODIFIER_PROTECTED;
    }

    protected function reduceRule290() {
         $this->semValue = Stmt\Class_::MODIFIER_PRIVATE;
    }

    protected function reduceRule291() {
         $this->semValue = Stmt\Class_::MODIFIER_STATIC;
    }

    protected function reduceRule292() {
         $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT;
    }

    protected function reduceRule293() {
         $this->semValue = Stmt\Class_::MODIFIER_FINAL;
    }

    protected function reduceRule294() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule295() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule296() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule297() {
         $this->semValue = new Stmt\PropertyProperty(substr($this->semStack[$this->stackPos-(1-1)], 1), null, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule298() {
         $this->semValue = new Stmt\PropertyProperty(substr($this->semStack[$this->stackPos-(3-1)], 1), $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule299() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule300() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule301() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule302() {
         $this->semValue = array();
    }

    protected function reduceRule303() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule304() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule305() {
         $this->semValue = new Expr\Assign($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule306() {
         $this->semValue = new Expr\Assign($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule307() {
         $this->semValue = new Expr\Assign($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule308() {
         $this->semValue = new Expr\AssignRef($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule309() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule310() {
         $this->semValue = new Expr\Clone_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule311() {
         $this->semValue = new Expr\AssignOp\Plus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule312() {
         $this->semValue = new Expr\AssignOp\Minus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule313() {
         $this->semValue = new Expr\AssignOp\Mul($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule314() {
         $this->semValue = new Expr\AssignOp\Div($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule315() {
         $this->semValue = new Expr\AssignOp\Concat($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule316() {
         $this->semValue = new Expr\AssignOp\Mod($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule317() {
         $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule318() {
         $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule319() {
         $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule320() {
         $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule321() {
         $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule322() {
         $this->semValue = new Expr\AssignOp\Pow($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule323() {
         $this->semValue = new Expr\PostInc($this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule324() {
         $this->semValue = new Expr\PreInc($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule325() {
         $this->semValue = new Expr\PostDec($this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule326() {
         $this->semValue = new Expr\PreDec($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule327() {
         $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule328() {
         $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule329() {
         $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule330() {
         $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule331() {
         $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule332() {
         $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule333() {
         $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule334() {
         $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule335() {
         $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule336() {
         $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule337() {
         $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule338() {
         $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule339() {
         $this->semValue = new Expr\BinaryOp\Div($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule340() {
         $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule341() {
         $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule342() {
         $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule343() {
         $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule344() {
         $this->semValue = new Expr\UnaryPlus($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule345() {
         $this->semValue = new Expr\UnaryMinus($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule346() {
         $this->semValue = new Expr\BooleanNot($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule347() {
         $this->semValue = new Expr\BitwiseNot($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule348() {
         $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule349() {
         $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule350() {
         $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule351() {
         $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule352() {
         $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule353() {
         $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule354() {
         $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule355() {
         $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule356() {
         $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule357() {
         $this->semValue = new Expr\Instanceof_($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule358() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule359() {
         $this->semValue = new Expr\Ternary($this->semStack[$this->stackPos-(5-1)], $this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-5)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes);
    }

    protected function reduceRule360() {
         $this->semValue = new Expr\Ternary($this->semStack[$this->stackPos-(4-1)], null, $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule361() {
         $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule362() {
         $this->semValue = new Expr\Isset_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule363() {
         $this->semValue = new Expr\Empty_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule364() {
         $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule365() {
         $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule366() {
         $this->semValue = new Expr\Eval_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule367() {
         $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule368() {
         $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule369() {
         $this->semValue = new Expr\Cast\Int_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule370() {
         $this->semValue = new Expr\Cast\Double($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule371() {
         $this->semValue = new Expr\Cast\String_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule372() {
         $this->semValue = new Expr\Cast\Array_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule373() {
         $this->semValue = new Expr\Cast\Object_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule374() {
         $this->semValue = new Expr\Cast\Bool_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule375() {
         $this->semValue = new Expr\Cast\Unset_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule376() {
         $attrs = $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes;
            $attrs['kind'] = strtolower($this->semStack[$this->stackPos-(2-1)]) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE;
            $this->semValue = new Expr\Exit_($this->semStack[$this->stackPos-(2-2)], $attrs);
    }

    protected function reduceRule377() {
         $this->semValue = new Expr\ErrorSuppress($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule378() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule379() {
         $this->semValue = new Expr\ShellExec($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule380() {
         $this->semValue = new Expr\Print_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule381() {
         $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule382() {
         $this->semValue = new Expr\Yield_($this->semStack[$this->stackPos-(2-2)], null, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule383() {
         $this->semValue = new Expr\Yield_($this->semStack[$this->stackPos-(4-4)], $this->semStack[$this->stackPos-(4-2)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule384() {
         $this->semValue = new Expr\YieldFrom($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule385() {
         $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$this->stackPos-(10-2)], 'params' => $this->semStack[$this->stackPos-(10-4)], 'uses' => $this->semStack[$this->stackPos-(10-6)], 'returnType' => $this->semStack[$this->stackPos-(10-7)], 'stmts' => $this->semStack[$this->stackPos-(10-9)]], $this->startAttributeStack[$this->stackPos-(10-1)] + $this->endAttributes);
    }

    protected function reduceRule386() {
         $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$this->stackPos-(11-3)], 'params' => $this->semStack[$this->stackPos-(11-5)], 'uses' => $this->semStack[$this->stackPos-(11-7)], 'returnType' => $this->semStack[$this->stackPos-(11-8)], 'stmts' => $this->semStack[$this->stackPos-(11-10)]], $this->startAttributeStack[$this->stackPos-(11-1)] + $this->endAttributes);
    }

    protected function reduceRule387() {
         $this->semValue = array(new Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$this->stackPos-(7-3)], 'implements' => $this->semStack[$this->stackPos-(7-4)], 'stmts' => $this->semStack[$this->stackPos-(7-6)]], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(7-2)]);
            $this->checkClass($this->semValue[0], -1);
    }

    protected function reduceRule388() {
         $this->semValue = new Expr\New_($this->semStack[$this->stackPos-(3-2)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule389() {
         list($class, $ctorArgs) = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule390() {
         $this->semValue = array();
    }

    protected function reduceRule391() {
         $this->semValue = $this->semStack[$this->stackPos-(4-3)];
    }

    protected function reduceRule392() {
         $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule393() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule394() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule395() {
         $this->semValue = new Expr\ClosureUse(substr($this->semStack[$this->stackPos-(2-2)], 1), $this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule396() {
         $this->semValue = new Expr\FuncCall($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule397() {
         $this->semValue = new Expr\FuncCall($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule398() {
         $this->semValue = new Expr\StaticCall($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule399() {
         $this->semValue = new Name($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule400() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule401() {
         $this->semValue = new Name($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule402() {
         $this->semValue = new Name\FullyQualified($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule403() {
         $this->semValue = new Name\Relative($this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule404() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule405() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule406() {
         $this->semValue = new Expr\Error($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2;
    }

    protected function reduceRule407() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule408() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule409() {
         $this->semValue = null;
    }

    protected function reduceRule410() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule411() {
         $this->semValue = array();
    }

    protected function reduceRule412() {
         $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$this->stackPos-(1-1)], '`'), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes));
    }

    protected function reduceRule413() {
         foreach ($this->semStack[$this->stackPos-(1-1)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', true); } }; $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule414() {
         $this->semValue = array();
    }

    protected function reduceRule415() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule416() {
         $this->semValue = new Expr\ConstFetch($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule417() {
         $this->semValue = new Expr\ClassConstFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule418() {
         $this->semValue = new Expr\ClassConstFetch($this->semStack[$this->stackPos-(3-1)], new Expr\Error($this->startAttributeStack[$this->stackPos-(3-3)] + $this->endAttributeStack[$this->stackPos-(3-3)]), $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); $this->errorState = 2;
    }

    protected function reduceRule419() {
         $attrs = $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_SHORT;
            $this->semValue = new Expr\Array_($this->semStack[$this->stackPos-(3-2)], $attrs);
    }

    protected function reduceRule420() {
         $attrs = $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_LONG;
            $this->semValue = new Expr\Array_($this->semStack[$this->stackPos-(4-3)], $attrs);
    }

    protected function reduceRule421() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule422() {
         $attrs = $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes; $attrs['kind'] = ($this->semStack[$this->stackPos-(1-1)][0] === "'" || ($this->semStack[$this->stackPos-(1-1)][1] === "'" && ($this->semStack[$this->stackPos-(1-1)][0] === 'b' || $this->semStack[$this->stackPos-(1-1)][0] === 'B')) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED);
            $this->semValue = new Scalar\String_(Scalar\String_::parse($this->semStack[$this->stackPos-(1-1)]), $attrs);
    }

    protected function reduceRule423() {
         $this->semValue = $this->parseLNumber($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule424() {
         $this->semValue = new Scalar\DNumber(Scalar\DNumber::parse($this->semStack[$this->stackPos-(1-1)]), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule425() {
         $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule426() {
         $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule427() {
         $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule428() {
         $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule429() {
         $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule430() {
         $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule431() {
         $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule432() {
         $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule433() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule434() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule435() {
         $attrs = $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = strpos($this->semStack[$this->stackPos-(3-1)], "'") === false ? Scalar\String_::KIND_HEREDOC : Scalar\String_::KIND_NOWDOC; preg_match('/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/', $this->semStack[$this->stackPos-(3-1)], $matches); $attrs['docLabel'] = $matches[1];;
            $this->semValue = new Scalar\String_(Scalar\String_::parseDocString($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-2)]), $attrs);
    }

    protected function reduceRule436() {
         $attrs = $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes; $attrs['kind'] = strpos($this->semStack[$this->stackPos-(2-1)], "'") === false ? Scalar\String_::KIND_HEREDOC : Scalar\String_::KIND_NOWDOC; preg_match('/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/', $this->semStack[$this->stackPos-(2-1)], $matches); $attrs['docLabel'] = $matches[1];;
            $this->semValue = new Scalar\String_('', $attrs);
    }

    protected function reduceRule437() {
         $attrs = $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED;
            foreach ($this->semStack[$this->stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', true); } }; $this->semValue = new Scalar\Encapsed($this->semStack[$this->stackPos-(3-2)], $attrs);
    }

    protected function reduceRule438() {
         $attrs = $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = strpos($this->semStack[$this->stackPos-(3-1)], "'") === false ? Scalar\String_::KIND_HEREDOC : Scalar\String_::KIND_NOWDOC; preg_match('/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/', $this->semStack[$this->stackPos-(3-1)], $matches); $attrs['docLabel'] = $matches[1];;
            foreach ($this->semStack[$this->stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, null, true); } } $s->value = preg_replace('~(\r\n|\n|\r)\z~', '', $s->value); if ('' === $s->value) array_pop($this->semStack[$this->stackPos-(3-2)]);; $this->semValue = new Scalar\Encapsed($this->semStack[$this->stackPos-(3-2)], $attrs);
    }

    protected function reduceRule439() {
         $this->semValue = null;
    }

    protected function reduceRule440() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule441() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule442() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule443() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule444() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule445() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule446() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule447() {
         $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule448() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule449() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule450() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule451() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule452() {
         $this->semValue = new Expr\MethodCall($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule453() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule454() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule455() {
         $this->semValue = new Expr\PropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule456() {
         $this->semValue = substr($this->semStack[$this->stackPos-(1-1)], 1);
    }

    protected function reduceRule457() {
         $this->semValue = $this->semStack[$this->stackPos-(4-3)];
    }

    protected function reduceRule458() {
         $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule459() {
         $this->semValue = new Expr\Error($this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); $this->errorState = 2;
    }

    protected function reduceRule460() {
         $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule461() {
         $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule462() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule463() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule464() {
         $this->semValue = new Expr\PropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule465() {
         $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule466() {
         $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule467() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule468() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule469() {
         $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule470() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule471() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule472() {
         $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule473() {
         $this->semValue = new Expr\Error($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2;
    }

    protected function reduceRule474() {
         $this->semValue = new Expr\List_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule475() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule476() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule477() {
         $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(1-1)], null, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule478() {
         $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(1-1)], null, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule479() {
         $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(3-3)], $this->semStack[$this->stackPos-(3-1)], false, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule480() {
         $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(3-3)], $this->semStack[$this->stackPos-(3-1)], false, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule481() {
         $this->semValue = null;
    }

    protected function reduceRule482() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)]; $end = count($this->semValue)-1; if ($this->semValue[$end] === null) unset($this->semValue[$end]);
    }

    protected function reduceRule483() {
         $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)];
    }

    protected function reduceRule484() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule485() {
         $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(3-3)], $this->semStack[$this->stackPos-(3-1)], false, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule486() {
         $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(1-1)], null, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule487() {
         $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(4-4)], $this->semStack[$this->stackPos-(4-1)], true, $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule488() {
         $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(2-2)], null, true, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule489() {
         $this->semValue = null;
    }

    protected function reduceRule490() {
         $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule491() {
         $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)];
    }

    protected function reduceRule492() {
         $this->semValue = array($this->semStack[$this->stackPos-(1-1)]);
    }

    protected function reduceRule493() {
         $this->semValue = array($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)]);
    }

    protected function reduceRule494() {
         $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule495() {
         $this->semValue = new Expr\Variable(substr($this->semStack[$this->stackPos-(1-1)], 1), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule496() {
         $this->semValue = $this->semStack[$this->stackPos-(1-1)];
    }

    protected function reduceRule497() {
         $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes);
    }

    protected function reduceRule498() {
         $this->semValue = new Expr\PropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule499() {
         $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule500() {
         $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes);
    }

    protected function reduceRule501() {
         $this->semValue = new Expr\ArrayDimFetch(new Expr\Variable($this->semStack[$this->stackPos-(6-2)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(6-4)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes);
    }

    protected function reduceRule502() {
         $this->semValue = $this->semStack[$this->stackPos-(3-2)];
    }

    protected function reduceRule503() {
         $this->semValue = new Scalar\String_($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule504() {
         $this->semValue = $this->parseNumString($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }

    protected function reduceRule505() {
         $this->semValue = $this->parseNumString('-' . $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes);
    }

    protected function reduceRule506() {
         $this->semValue = new Expr\Variable(substr($this->semStack[$this->stackPos-(1-1)], 1), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
    }
}
<?php

namespace PhpParser\Parser;

/* GENERATED file based on grammar/tokens.y */
final class Tokens
{
    const YYERRTOK = 256;
    const T_INCLUDE = 257;
    const T_INCLUDE_ONCE = 258;
    const T_EVAL = 259;
    const T_REQUIRE = 260;
    const T_REQUIRE_ONCE = 261;
    const T_LOGICAL_OR = 262;
    const T_LOGICAL_XOR = 263;
    const T_LOGICAL_AND = 264;
    const T_PRINT = 265;
    const T_YIELD = 266;
    const T_DOUBLE_ARROW = 267;
    const T_YIELD_FROM = 268;
    const T_PLUS_EQUAL = 269;
    const T_MINUS_EQUAL = 270;
    const T_MUL_EQUAL = 271;
    const T_DIV_EQUAL = 272;
    const T_CONCAT_EQUAL = 273;
    const T_MOD_EQUAL = 274;
    const T_AND_EQUAL = 275;
    const T_OR_EQUAL = 276;
    const T_XOR_EQUAL = 277;
    const T_SL_EQUAL = 278;
    const T_SR_EQUAL = 279;
    const T_POW_EQUAL = 280;
    const T_COALESCE = 281;
    const T_BOOLEAN_OR = 282;
    const T_BOOLEAN_AND = 283;
    const T_IS_EQUAL = 284;
    const T_IS_NOT_EQUAL = 285;
    const T_IS_IDENTICAL = 286;
    const T_IS_NOT_IDENTICAL = 287;
    const T_SPACESHIP = 288;
    const T_IS_SMALLER_OR_EQUAL = 289;
    const T_IS_GREATER_OR_EQUAL = 290;
    const T_SL = 291;
    const T_SR = 292;
    const T_INSTANCEOF = 293;
    const T_INC = 294;
    const T_DEC = 295;
    const T_INT_CAST = 296;
    const T_DOUBLE_CAST = 297;
    const T_STRING_CAST = 298;
    const T_ARRAY_CAST = 299;
    const T_OBJECT_CAST = 300;
    const T_BOOL_CAST = 301;
    const T_UNSET_CAST = 302;
    const T_POW = 303;
    const T_NEW = 304;
    const T_CLONE = 305;
    const T_EXIT = 306;
    const T_IF = 307;
    const T_ELSEIF = 308;
    const T_ELSE = 309;
    const T_ENDIF = 310;
    const T_LNUMBER = 311;
    const T_DNUMBER = 312;
    const T_STRING = 313;
    const T_STRING_VARNAME = 314;
    const T_VARIABLE = 315;
    const T_NUM_STRING = 316;
    const T_INLINE_HTML = 317;
    const T_CHARACTER = 318;
    const T_BAD_CHARACTER = 319;
    const T_ENCAPSED_AND_WHITESPACE = 320;
    const T_CONSTANT_ENCAPSED_STRING = 321;
    const T_ECHO = 322;
    const T_DO = 323;
    const T_WHILE = 324;
    const T_ENDWHILE = 325;
    const T_FOR = 326;
    const T_ENDFOR = 327;
    const T_FOREACH = 328;
    const T_ENDFOREACH = 329;
    const T_DECLARE = 330;
    const T_ENDDECLARE = 331;
    const T_AS = 332;
    const T_SWITCH = 333;
    const T_ENDSWITCH = 334;
    const T_CASE = 335;
    const T_DEFAULT = 336;
    const T_BREAK = 337;
    const T_CONTINUE = 338;
    const T_GOTO = 339;
    const T_FUNCTION = 340;
    const T_CONST = 341;
    const T_RETURN = 342;
    const T_TRY = 343;
    const T_CATCH = 344;
    const T_FINALLY = 345;
    const T_THROW = 346;
    const T_USE = 347;
    const T_INSTEADOF = 348;
    const T_GLOBAL = 349;
    const T_STATIC = 350;
    const T_ABSTRACT = 351;
    const T_FINAL = 352;
    const T_PRIVATE = 353;
    const T_PROTECTED = 354;
    const T_PUBLIC = 355;
    const T_VAR = 356;
    const T_UNSET = 357;
    const T_ISSET = 358;
    const T_EMPTY = 359;
    const T_HALT_COMPILER = 360;
    const T_CLASS = 361;
    const T_TRAIT = 362;
    const T_INTERFACE = 363;
    const T_EXTENDS = 364;
    const T_IMPLEMENTS = 365;
    const T_OBJECT_OPERATOR = 366;
    const T_LIST = 367;
    const T_ARRAY = 368;
    const T_CALLABLE = 369;
    const T_CLASS_C = 370;
    const T_TRAIT_C = 371;
    const T_METHOD_C = 372;
    const T_FUNC_C = 373;
    const T_LINE = 374;
    const T_FILE = 375;
    const T_COMMENT = 376;
    const T_DOC_COMMENT = 377;
    const T_OPEN_TAG = 378;
    const T_OPEN_TAG_WITH_ECHO = 379;
    const T_CLOSE_TAG = 380;
    const T_WHITESPACE = 381;
    const T_START_HEREDOC = 382;
    const T_END_HEREDOC = 383;
    const T_DOLLAR_OPEN_CURLY_BRACES = 384;
    const T_CURLY_OPEN = 385;
    const T_PAAMAYIM_NEKUDOTAYIM = 386;
    const T_NAMESPACE = 387;
    const T_NS_C = 388;
    const T_DIR = 389;
    const T_NS_SEPARATOR = 390;
    const T_ELLIPSIS = 391;
}
<?php

namespace PhpParser;

/*
 * This parser is based on a skeleton written by Moriyoshi Koizumi, which in
 * turn is based on work by Masato Bito.
 */
use PhpParser\Node\Name;
use PhpParser\Node\Param;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassConst;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Interface_;
use PhpParser\Node\Stmt\Namespace_;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\TryCatch;
use PhpParser\Node\Stmt\UseUse;

abstract class ParserAbstract implements Parser
{
    const SYMBOL_NONE = -1;

    /*
     * The following members will be filled with generated parsing data:
     */

    /** @var int Size of $tokenToSymbol map */
    protected $tokenToSymbolMapSize;
    /** @var int Size of $action table */
    protected $actionTableSize;
    /** @var int Size of $goto table */
    protected $gotoTableSize;

    /** @var int Symbol number signifying an invalid token */
    protected $invalidSymbol;
    /** @var int Symbol number of error recovery token */
    protected $errorSymbol;
    /** @var int Action number signifying default action */
    protected $defaultAction;
    /** @var int Rule number signifying that an unexpected token was encountered */
    protected $unexpectedTokenRule;

    protected $YY2TBLSTATE;
    protected $YYNLSTATES;

    /** @var array Map of lexer tokens to internal symbols */
    protected $tokenToSymbol;
    /** @var array Map of symbols to their names */
    protected $symbolToName;
    /** @var array Names of the production rules (only necessary for debugging) */
    protected $productions;

    /** @var array Map of states to a displacement into the $action table. The corresponding action for this
     *             state/symbol pair is $action[$actionBase[$state] + $symbol]. If $actionBase[$state] is 0, the
                   action is defaulted, i.e. $actionDefault[$state] should be used instead. */
    protected $actionBase;
    /** @var array Table of actions. Indexed according to $actionBase comment. */
    protected $action;
    /** @var array Table indexed analogously to $action. If $actionCheck[$actionBase[$state] + $symbol] != $symbol
     *             then the action is defaulted, i.e. $actionDefault[$state] should be used instead. */
    protected $actionCheck;
    /** @var array Map of states to their default action */
    protected $actionDefault;

    /** @var array Map of non-terminals to a displacement into the $goto table. The corresponding goto state for this
     *             non-terminal/state pair is $goto[$gotoBase[$nonTerminal] + $state] (unless defaulted) */
    protected $gotoBase;
    /** @var array Table of states to goto after reduction. Indexed according to $gotoBase comment. */
    protected $goto;
    /** @var array Table indexed analogously to $goto. If $gotoCheck[$gotoBase[$nonTerminal] + $state] != $nonTerminal
     *             then the goto state is defaulted, i.e. $gotoDefault[$nonTerminal] should be used. */
    protected $gotoCheck;
    /** @var array Map of non-terminals to the default state to goto after their reduction */
    protected $gotoDefault;

    /** @var array Map of rules to the non-terminal on their left-hand side, i.e. the non-terminal to use for
     *             determining the state to goto after reduction. */
    protected $ruleToNonTerminal;
    /** @var array Map of rules to the length of their right-hand side, which is the number of elements that have to
     *             be popped from the stack(s) on reduction. */
    protected $ruleToLength;

    /*
     * The following members are part of the parser state:
     */

    /** @var Lexer Lexer that is used when parsing */
    protected $lexer;
    /** @var mixed Temporary value containing the result of last semantic action (reduction) */
    protected $semValue;
    /** @var int Position in stacks (state stack, semantic value stack, attribute stack) */
    protected $stackPos;
    /** @var array Semantic value stack (contains values of tokens and semantic action results) */
    protected $semStack;
    /** @var array[] Start attribute stack */
    protected $startAttributeStack;
    /** @var array[] End attribute stack */
    protected $endAttributeStack;
    /** @var array End attributes of last *shifted* token */
    protected $endAttributes;
    /** @var array Start attributes of last *read* token */
    protected $lookaheadStartAttributes;

    /** @var ErrorHandler Error handler */
    protected $errorHandler;
    /** @var Error[] Errors collected during last parse */
    protected $errors;
    /** @var int Error state, used to avoid error floods */
    protected $errorState;

    /**
     * Creates a parser instance.
     *
     * @param Lexer $lexer A lexer
     * @param array $options Options array. Currently no options are supported.
     */
    public function __construct(Lexer $lexer, array $options = array()) {
        $this->lexer = $lexer;
        $this->errors = array();

        if (isset($options['throwOnError'])) {
            throw new \LogicException(
                '"throwOnError" is no longer supported, use "errorHandler" instead');
        }
    }

    /**
     * Parses PHP code into a node tree.
     *
     * If a non-throwing error handler is used, the parser will continue parsing after an error
     * occurred and attempt to build a partial AST.
     *
     * @param string $code The source code to parse
     * @param ErrorHandler|null $errorHandler Error handler to use for lexer/parser errors, defaults
     *                                        to ErrorHandler\Throwing.
     *
     * @return Node[]|null Array of statements (or null if the 'throwOnError' option is disabled and the parser was
     *                     unable to recover from an error).
     */
    public function parse($code, ErrorHandler $errorHandler = null) {
        $this->errorHandler = $errorHandler ?: new ErrorHandler\Throwing;

        // Initialize the lexer
        $this->lexer->startLexing($code, $this->errorHandler);

        // We start off with no lookahead-token
        $symbol = self::SYMBOL_NONE;

        // The attributes for a node are taken from the first and last token of the node.
        // From the first token only the startAttributes are taken and from the last only
        // the endAttributes. Both are merged using the array union operator (+).
        $startAttributes = '*POISON';
        $endAttributes = '*POISON';
        $this->endAttributes = $endAttributes;

        // Keep stack of start and end attributes
        $this->startAttributeStack = array();
        $this->endAttributeStack = array($endAttributes);

        // Start off in the initial state and keep a stack of previous states
        $state = 0;
        $stateStack = array($state);

        // Semantic value stack (contains values of tokens and semantic action results)
        $this->semStack = array();

        // Current position in the stack(s)
        $this->stackPos = 0;

        $this->errorState = 0;

        for (;;) {
            //$this->traceNewState($state, $symbol);

            if ($this->actionBase[$state] == 0) {
                $rule = $this->actionDefault[$state];
            } else {
                if ($symbol === self::SYMBOL_NONE) {
                    // Fetch the next token id from the lexer and fetch additional info by-ref.
                    // The end attributes are fetched into a temporary variable and only set once the token is really
                    // shifted (not during read). Otherwise you would sometimes get off-by-one errors, when a rule is
                    // reduced after a token was read but not yet shifted.
                    $tokenId = $this->lexer->getNextToken($tokenValue, $startAttributes, $endAttributes);

                    // map the lexer token id to the internally used symbols
                    $symbol = $tokenId >= 0 && $tokenId < $this->tokenToSymbolMapSize
                        ? $this->tokenToSymbol[$tokenId]
                        : $this->invalidSymbol;

                    if ($symbol === $this->invalidSymbol) {
                        throw new \RangeException(sprintf(
                            'The lexer returned an invalid token (id=%d, value=%s)',
                            $tokenId, $tokenValue
                        ));
                    }

                    // This is necessary to assign some meaningful attributes to /* empty */ productions. They'll get
                    // the attributes of the next token, even though they don't contain it themselves.
                    $this->startAttributeStack[$this->stackPos+1] = $startAttributes;
                    $this->endAttributeStack[$this->stackPos+1] = $endAttributes;
                    $this->lookaheadStartAttributes = $startAttributes;

                    //$this->traceRead($symbol);
                }

                $idx = $this->actionBase[$state] + $symbol;
                if ((($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] == $symbol)
                     || ($state < $this->YY2TBLSTATE
                         && ($idx = $this->actionBase[$state + $this->YYNLSTATES] + $symbol) >= 0
                         && $idx < $this->actionTableSize && $this->actionCheck[$idx] == $symbol))
                    && ($action = $this->action[$idx]) != $this->defaultAction) {
                    /*
                     * >= YYNLSTATES: shift and reduce
                     * > 0: shift
                     * = 0: accept
                     * < 0: reduce
                     * = -YYUNEXPECTED: error
                     */
                    if ($action > 0) {
                        /* shift */
                        //$this->traceShift($symbol);

                        ++$this->stackPos;
                        $stateStack[$this->stackPos] = $state = $action;
                        $this->semStack[$this->stackPos] = $tokenValue;
                        $this->startAttributeStack[$this->stackPos] = $startAttributes;
                        $this->endAttributeStack[$this->stackPos] = $endAttributes;
                        $this->endAttributes = $endAttributes;
                        $symbol = self::SYMBOL_NONE;

                        if ($this->errorState) {
                            --$this->errorState;
                        }

                        if ($action < $this->YYNLSTATES) {
                            continue;
                        }

                        /* $yyn >= YYNLSTATES means shift-and-reduce */
                        $rule = $action - $this->YYNLSTATES;
                    } else {
                        $rule = -$action;
                    }
                } else {
                    $rule = $this->actionDefault[$state];
                }
            }

            for (;;) {
                if ($rule === 0) {
                    /* accept */
                    //$this->traceAccept();
                    return $this->semValue;
                } elseif ($rule !== $this->unexpectedTokenRule) {
                    /* reduce */
                    //$this->traceReduce($rule);

                    try {
                        $this->{'reduceRule' . $rule}();
                    } catch (Error $e) {
                        if (-1 === $e->getStartLine() && isset($startAttributes['startLine'])) {
                            $e->setStartLine($startAttributes['startLine']);
                        }

                        $this->emitError($e);
                        // Can't recover from this type of error
                        return null;
                    }

                    /* Goto - shift nonterminal */
                    $lastEndAttributes = $this->endAttributeStack[$this->stackPos];
                    $this->stackPos -= $this->ruleToLength[$rule];
                    $nonTerminal = $this->ruleToNonTerminal[$rule];
                    $idx = $this->gotoBase[$nonTerminal] + $stateStack[$this->stackPos];
                    if ($idx >= 0 && $idx < $this->gotoTableSize && $this->gotoCheck[$idx] == $nonTerminal) {
                        $state = $this->goto[$idx];
                    } else {
                        $state = $this->gotoDefault[$nonTerminal];
                    }

                    ++$this->stackPos;
                    $stateStack[$this->stackPos]     = $state;
                    $this->semStack[$this->stackPos] = $this->semValue;
                    $this->endAttributeStack[$this->stackPos] = $lastEndAttributes;
                } else {
                    /* error */
                    switch ($this->errorState) {
                        case 0:
                            $msg = $this->getErrorMessage($symbol, $state);
                            $this->emitError(new Error($msg, $startAttributes + $endAttributes));
                            // Break missing intentionally
                        case 1:
                        case 2:
                            $this->errorState = 3;

                            // Pop until error-expecting state uncovered
                            while (!(
                                (($idx = $this->actionBase[$state] + $this->errorSymbol) >= 0
                                    && $idx < $this->actionTableSize && $this->actionCheck[$idx] == $this->errorSymbol)
                                || ($state < $this->YY2TBLSTATE
                                    && ($idx = $this->actionBase[$state + $this->YYNLSTATES] + $this->errorSymbol) >= 0
                                    && $idx < $this->actionTableSize && $this->actionCheck[$idx] == $this->errorSymbol)
                            ) || ($action = $this->action[$idx]) == $this->defaultAction) { // Not totally sure about this
                                if ($this->stackPos <= 0) {
                                    // Could not recover from error
                                    return null;
                                }
                                $state = $stateStack[--$this->stackPos];
                                //$this->tracePop($state);
                            }

                            //$this->traceShift($this->errorSymbol);
                            ++$this->stackPos;
                            $stateStack[$this->stackPos] = $state = $action;

                            // We treat the error symbol as being empty, so we reset the end attributes
                            // to the end attributes of the last non-error symbol
                            $this->endAttributeStack[$this->stackPos] = $this->endAttributeStack[$this->stackPos - 1];
                            $this->endAttributes = $this->endAttributeStack[$this->stackPos - 1];
                            break;

                        case 3:
                            if ($symbol === 0) {
                                // Reached EOF without recovering from error
                                return null;
                            }

                            //$this->traceDiscard($symbol);
                            $symbol = self::SYMBOL_NONE;
                            break 2;
                    }
                }

                if ($state < $this->YYNLSTATES) {
                    break;
                }

                /* >= YYNLSTATES means shift-and-reduce */
                $rule = $state - $this->YYNLSTATES;
            }
        }

        throw new \RuntimeException('Reached end of parser loop');
    }

    protected function emitError(Error $error) {
        $this->errorHandler->handleError($error);
    }

    protected function getErrorMessage($symbol, $state) {
        $expectedString = '';
        if ($expected = $this->getExpectedTokens($state)) {
            $expectedString = ', expecting ' . implode(' or ', $expected);
        }

        return 'Syntax error, unexpected ' . $this->symbolToName[$symbol] . $expectedString;
    }

    protected function getExpectedTokens($state) {
        $expected = array();

        $base = $this->actionBase[$state];
        foreach ($this->symbolToName as $symbol => $name) {
            $idx = $base + $symbol;
            if ($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol
                || $state < $this->YY2TBLSTATE
                && ($idx = $this->actionBase[$state + $this->YYNLSTATES] + $symbol) >= 0
                && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol
            ) {
                if ($this->action[$idx] != $this->unexpectedTokenRule
                    && $this->action[$idx] != $this->defaultAction
                    && $symbol != $this->errorSymbol
                ) {
                    if (count($expected) == 4) {
                        /* Too many expected tokens */
                        return array();
                    }

                    $expected[] = $name;
                }
            }
        }

        return $expected;
    }

    /*
     * Tracing functions used for debugging the parser.
     */

    /*
    protected function traceNewState($state, $symbol) {
        echo '% State ' . $state
            . ', Lookahead ' . ($symbol == self::SYMBOL_NONE ? '--none--' : $this->symbolToName[$symbol]) . "\n";
    }

    protected function traceRead($symbol) {
        echo '% Reading ' . $this->symbolToName[$symbol] . "\n";
    }

    protected function traceShift($symbol) {
        echo '% Shift ' . $this->symbolToName[$symbol] . "\n";
    }

    protected function traceAccept() {
        echo "% Accepted.\n";
    }

    protected function traceReduce($n) {
        echo '% Reduce by (' . $n . ') ' . $this->productions[$n] . "\n";
    }

    protected function tracePop($state) {
        echo '% Recovering, uncovered state ' . $state . "\n";
    }

    protected function traceDiscard($symbol) {
        echo '% Discard ' . $this->symbolToName[$symbol] . "\n";
    }
    */

    /*
     * Helper functions invoked by semantic actions
     */

    /**
     * Moves statements of semicolon-style namespaces into $ns->stmts and checks various error conditions.
     *
     * @param Node[] $stmts
     * @return Node[]
     */
    protected function handleNamespaces(array $stmts) {
        $hasErrored = false;
        $style = $this->getNamespacingStyle($stmts);
        if (null === $style) {
            // not namespaced, nothing to do
            return $stmts;
        } elseif ('brace' === $style) {
            // For braced namespaces we only have to check that there are no invalid statements between the namespaces
            $afterFirstNamespace = false;
            foreach ($stmts as $stmt) {
                if ($stmt instanceof Node\Stmt\Namespace_) {
                    $afterFirstNamespace = true;
                } elseif (!$stmt instanceof Node\Stmt\HaltCompiler
                        && !$stmt instanceof Node\Stmt\Nop
                        && $afterFirstNamespace && !$hasErrored) {
                    $this->emitError(new Error(
                        'No code may exist outside of namespace {}', $stmt->getAttributes()));
                    $hasErrored = true; // Avoid one error for every statement
                }
            }
            return $stmts;
        } else {
            // For semicolon namespaces we have to move the statements after a namespace declaration into ->stmts
            $resultStmts = array();
            $targetStmts =& $resultStmts;
            foreach ($stmts as $stmt) {
                if ($stmt instanceof Node\Stmt\Namespace_) {
                    if ($stmt->stmts === null) {
                        $stmt->stmts = array();
                        $targetStmts =& $stmt->stmts;
                        $resultStmts[] = $stmt;
                    } else {
                        // This handles the invalid case of mixed style namespaces
                        $resultStmts[] = $stmt;
                        $targetStmts =& $resultStmts;
                    }
                } elseif ($stmt instanceof Node\Stmt\HaltCompiler) {
                    // __halt_compiler() is not moved into the namespace
                    $resultStmts[] = $stmt;
                } else {
                    $targetStmts[] = $stmt;
                }
            }
            return $resultStmts;
        }
    }

    private function getNamespacingStyle(array $stmts) {
        $style = null;
        $hasNotAllowedStmts = false;
        foreach ($stmts as $i => $stmt) {
            if ($stmt instanceof Node\Stmt\Namespace_) {
                $currentStyle = null === $stmt->stmts ? 'semicolon' : 'brace';
                if (null === $style) {
                    $style = $currentStyle;
                    if ($hasNotAllowedStmts) {
                        $this->emitError(new Error(
                            'Namespace declaration statement has to be the very first statement in the script',
                            $stmt->getLine() // Avoid marking the entire namespace as an error
                        ));
                    }
                } elseif ($style !== $currentStyle) {
                    $this->emitError(new Error(
                        'Cannot mix bracketed namespace declarations with unbracketed namespace declarations',
                        $stmt->getLine() // Avoid marking the entire namespace as an error
                    ));
                    // Treat like semicolon style for namespace normalization
                    return 'semicolon';
                }
                continue;
            }

            /* declare(), __halt_compiler() and nops can be used before a namespace declaration */
            if ($stmt instanceof Node\Stmt\Declare_
                || $stmt instanceof Node\Stmt\HaltCompiler
                || $stmt instanceof Node\Stmt\Nop) {
                continue;
            }

            /* There may be a hashbang line at the very start of the file */
            if ($i == 0 && $stmt instanceof Node\Stmt\InlineHTML && preg_match('/\A#!.*\r?\n\z/', $stmt->value)) {
                continue;
            }

            /* Everything else if forbidden before namespace declarations */
            $hasNotAllowedStmts = true;
        }
        return $style;
    }

    protected function handleBuiltinTypes(Name $name) {
        $scalarTypes = [
            'bool'     => true,
            'int'      => true,
            'float'    => true,
            'string'   => true,
            'iterable' => true,
            'void'     => true,
            'object'   => true,
        ];

        if (!$name->isUnqualified()) {
            return $name;
        }

        $lowerName = strtolower($name->toString());
        return isset($scalarTypes[$lowerName]) ? $lowerName : $name;
    }

    protected static $specialNames = array(
        'self'   => true,
        'parent' => true,
        'static' => true,
    );

    protected function getAttributesAt($pos) {
        return $this->startAttributeStack[$pos] + $this->endAttributeStack[$pos];
    }

    protected function parseLNumber($str, $attributes, $allowInvalidOctal = false) {
        try {
            return LNumber::fromString($str, $attributes, $allowInvalidOctal);
        } catch (Error $error) {
            $this->emitError($error);
            // Use dummy value
            return new LNumber(0, $attributes);
        }
    }

    protected function parseNumString($str, $attributes) {
        if (!preg_match('/^(?:0|-?[1-9][0-9]*)$/', $str)) {
            return new String_($str, $attributes);
        }

        $num = +$str;
        if (!is_int($num)) {
            return new String_($str, $attributes);
        }

        return new LNumber($num, $attributes);
    }

    protected function checkModifier($a, $b, $modifierPos) {
        // Jumping through some hoops here because verifyModifier() is also used elsewhere
        try {
            Class_::verifyModifier($a, $b);
        } catch (Error $error) {
            $error->setAttributes($this->getAttributesAt($modifierPos));
            $this->emitError($error);
        }
    }

    protected function checkParam(Param $node) {
        if ($node->variadic && null !== $node->default) {
            $this->emitError(new Error(
                'Variadic parameter cannot have a default value',
                $node->default->getAttributes()
            ));
        }
    }

    protected function checkTryCatch(TryCatch $node) {
        if (empty($node->catches) && null === $node->finally) {
            $this->emitError(new Error(
                'Cannot use try without catch or finally', $node->getAttributes()
            ));
        }
    }

    protected function checkNamespace(Namespace_ $node) {
        if (isset(self::$specialNames[strtolower($node->name)])) {
            $this->emitError(new Error(
                sprintf('Cannot use \'%s\' as namespace name', $node->name),
                $node->name->getAttributes()
            ));
        }

        if (null !== $node->stmts) {
            foreach ($node->stmts as $stmt) {
                if ($stmt instanceof Namespace_) {
                    $this->emitError(new Error(
                        'Namespace declarations cannot be nested', $stmt->getAttributes()
                    ));
                }
            }
        }
    }

    protected function checkClass(Class_ $node, $namePos) {
        if (null !== $node->name && isset(self::$specialNames[strtolower($node->name)])) {
            $this->emitError(new Error(
                sprintf('Cannot use \'%s\' as class name as it is reserved', $node->name),
                $this->getAttributesAt($namePos)
            ));
        }

        if (isset(self::$specialNames[strtolower($node->extends)])) {
            $this->emitError(new Error(
                sprintf('Cannot use \'%s\' as class name as it is reserved', $node->extends),
                $node->extends->getAttributes()
            ));
        }

        foreach ($node->implements as $interface) {
            if (isset(self::$specialNames[strtolower($interface)])) {
                $this->emitError(new Error(
                    sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface),
                    $interface->getAttributes()
                ));
            }
        }
    }

    protected function checkInterface(Interface_ $node, $namePos) {
        if (null !== $node->name && isset(self::$specialNames[strtolower($node->name)])) {
            $this->emitError(new Error(
                sprintf('Cannot use \'%s\' as class name as it is reserved', $node->name),
                $this->getAttributesAt($namePos)
            ));
        }

        foreach ($node->extends as $interface) {
            if (isset(self::$specialNames[strtolower($interface)])) {
                $this->emitError(new Error(
                    sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface),
                    $interface->getAttributes()
                ));
            }
        }
    }

    protected function checkClassMethod(ClassMethod $node, $modifierPos) {
        if ($node->flags & Class_::MODIFIER_STATIC) {
            switch (strtolower($node->name)) {
                case '__construct':
                    $this->emitError(new Error(
                        sprintf('Constructor %s() cannot be static', $node->name),
                        $this->getAttributesAt($modifierPos)));
                    break;
                case '__destruct':
                    $this->emitError(new Error(
                        sprintf('Destructor %s() cannot be static', $node->name),
                        $this->getAttributesAt($modifierPos)));
                    break;
                case '__clone':
                    $this->emitError(new Error(
                        sprintf('Clone method %s() cannot be static', $node->name),
                        $this->getAttributesAt($modifierPos)));
                    break;
            }
        }
    }

    protected function checkClassConst(ClassConst $node, $modifierPos) {
        if ($node->flags & Class_::MODIFIER_STATIC) {
            $this->emitError(new Error(
                "Cannot use 'static' as constant modifier",
                $this->getAttributesAt($modifierPos)));
        }
        if ($node->flags & Class_::MODIFIER_ABSTRACT) {
            $this->emitError(new Error(
                "Cannot use 'abstract' as constant modifier",
                $this->getAttributesAt($modifierPos)));
        }
        if ($node->flags & Class_::MODIFIER_FINAL) {
            $this->emitError(new Error(
                "Cannot use 'final' as constant modifier",
                $this->getAttributesAt($modifierPos)));
        }
    }

    protected function checkProperty(Property $node, $modifierPos) {
        if ($node->flags & Class_::MODIFIER_ABSTRACT) {
            $this->emitError(new Error('Properties cannot be declared abstract',
                $this->getAttributesAt($modifierPos)));
        }

        if ($node->flags & Class_::MODIFIER_FINAL) {
            $this->emitError(new Error('Properties cannot be declared final',
                $this->getAttributesAt($modifierPos)));
        }
    }

    protected function checkUseUse(UseUse $node, $namePos) {
        if ('self' == strtolower($node->alias) || 'parent' == strtolower($node->alias)) {
            $this->emitError(new Error(
                sprintf(
                    'Cannot use %s as %s because \'%2$s\' is a special class name',
                    $node->name, $node->alias
                ),
                $this->getAttributesAt($namePos)
            ));
        }
    }
}
<?php

namespace PhpParser;

class ParserFactory {
    const PREFER_PHP7 = 1;
    const PREFER_PHP5 = 2;
    const ONLY_PHP7 = 3;
    const ONLY_PHP5 = 4;

    /**
     * Creates a Parser instance, according to the provided kind.
     *
     * @param int        $kind  One of ::PREFER_PHP7, ::PREFER_PHP5, ::ONLY_PHP7 or ::ONLY_PHP5
     * @param Lexer|null $lexer Lexer to use. Defaults to emulative lexer when not specified
     * @param array      $parserOptions Parser options. See ParserAbstract::__construct() argument
     *
     * @return Parser The parser instance
     */
    public function create($kind, Lexer $lexer = null, array $parserOptions = array()) {
        if (null === $lexer) {
            $lexer = new Lexer\Emulative();
        }
        switch ($kind) {
            case self::PREFER_PHP7:
                return new Parser\Multiple([
                    new Parser\Php7($lexer, $parserOptions), new Parser\Php5($lexer, $parserOptions)
                ]);
            case self::PREFER_PHP5:
                return new Parser\Multiple([
                    new Parser\Php5($lexer, $parserOptions), new Parser\Php7($lexer, $parserOptions)
                ]);
            case self::ONLY_PHP7:
                return new Parser\Php7($lexer, $parserOptions);
            case self::ONLY_PHP5:
                return new Parser\Php5($lexer, $parserOptions);
            default:
                throw new \LogicException(
                    'Kind must be one of ::PREFER_PHP7, ::PREFER_PHP5, ::ONLY_PHP7 or ::ONLY_PHP5'
                );
        }
    }
}
<?php

namespace PhpParser\PrettyPrinter;

use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\AssignOp;
use PhpParser\Node\Expr\BinaryOp;
use PhpParser\Node\Expr\Cast;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar;
use PhpParser\Node\Scalar\MagicConst;
use PhpParser\Node\Stmt;
use PhpParser\PrettyPrinterAbstract;

class Standard extends PrettyPrinterAbstract
{
    // Special nodes

    protected function pParam(Node\Param $node) {
        return ($node->type ? $this->pType($node->type) . ' ' : '')
             . ($node->byRef ? '&' : '')
             . ($node->variadic ? '...' : '')
             . '$' . $node->name
             . ($node->default ? ' = ' . $this->p($node->default) : '');
    }

    protected function pArg(Node\Arg $node) {
        return ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '') . $this->p($node->value);
    }

    protected function pConst(Node\Const_ $node) {
        return $node->name . ' = ' . $this->p($node->value);
    }

    protected function pNullableType(Node\NullableType $node) {
        return '?' . $this->pType($node->type);
    }

    // Names

    protected function pName(Name $node) {
        return implode('\\', $node->parts);
    }

    protected function pName_FullyQualified(Name\FullyQualified $node) {
        return '\\' . implode('\\', $node->parts);
    }

    protected function pName_Relative(Name\Relative $node) {
        return 'namespace\\' . implode('\\', $node->parts);
    }

    // Magic Constants

    protected function pScalar_MagicConst_Class(MagicConst\Class_ $node) {
        return '__CLASS__';
    }

    protected function pScalar_MagicConst_Dir(MagicConst\Dir $node) {
        return '__DIR__';
    }

    protected function pScalar_MagicConst_File(MagicConst\File $node) {
        return '__FILE__';
    }

    protected function pScalar_MagicConst_Function(MagicConst\Function_ $node) {
        return '__FUNCTION__';
    }

    protected function pScalar_MagicConst_Line(MagicConst\Line $node) {
        return '__LINE__';
    }

    protected function pScalar_MagicConst_Method(MagicConst\Method $node) {
        return '__METHOD__';
    }

    protected function pScalar_MagicConst_Namespace(MagicConst\Namespace_ $node) {
        return '__NAMESPACE__';
    }

    protected function pScalar_MagicConst_Trait(MagicConst\Trait_ $node) {
        return '__TRAIT__';
    }

    // Scalars

    protected function pScalar_String(Scalar\String_ $node) {
        $kind = $node->getAttribute('kind', Scalar\String_::KIND_SINGLE_QUOTED);
        switch ($kind) {
            case Scalar\String_::KIND_NOWDOC:
                $label = $node->getAttribute('docLabel');
                if ($label && !$this->containsEndLabel($node->value, $label)) {
                    if ($node->value === '') {
                        return $this->pNoIndent("<<<'$label'\n$label") . $this->docStringEndToken;
                    }

                    return $this->pNoIndent("<<<'$label'\n$node->value\n$label")
                         . $this->docStringEndToken;
                }
                /* break missing intentionally */
            case Scalar\String_::KIND_SINGLE_QUOTED:
                return '\'' . $this->pNoIndent(addcslashes($node->value, '\'\\')) . '\'';
            case Scalar\String_::KIND_HEREDOC:
                $label = $node->getAttribute('docLabel');
                if ($label && !$this->containsEndLabel($node->value, $label)) {
                    if ($node->value === '') {
                        return $this->pNoIndent("<<<$label\n$label") . $this->docStringEndToken;
                    }

                    $escaped = $this->escapeString($node->value, null);
                    return $this->pNoIndent("<<<$label\n" . $escaped ."\n$label")
                         . $this->docStringEndToken;
                }
            /* break missing intentionally */
            case Scalar\String_::KIND_DOUBLE_QUOTED:
                return '"' . $this->escapeString($node->value, '"') . '"';
        }
        throw new \Exception('Invalid string kind');
    }

    protected function pScalar_Encapsed(Scalar\Encapsed $node) {
        if ($node->getAttribute('kind') === Scalar\String_::KIND_HEREDOC) {
            $label = $node->getAttribute('docLabel');
            if ($label && !$this->encapsedContainsEndLabel($node->parts, $label)) {
                if (count($node->parts) === 1
                    && $node->parts[0] instanceof Scalar\EncapsedStringPart
                    && $node->parts[0]->value === ''
                ) {
                    return $this->pNoIndent("<<<$label\n$label") . $this->docStringEndToken;
                }

                return $this->pNoIndent(
                    "<<<$label\n" . $this->pEncapsList($node->parts, null) . "\n$label"
                ) . $this->docStringEndToken;
            }
        }
        return '"' . $this->pEncapsList($node->parts, '"') . '"';
    }

    protected function pScalar_LNumber(Scalar\LNumber $node) {
        if ($node->value === -\PHP_INT_MAX-1) {
            // PHP_INT_MIN cannot be represented as a literal,
            // because the sign is not part of the literal
            return '(-' . \PHP_INT_MAX . '-1)';
        }

        $kind = $node->getAttribute('kind', Scalar\LNumber::KIND_DEC);
        if (Scalar\LNumber::KIND_DEC === $kind) {
            return (string) $node->value;
        }

        $sign = $node->value < 0 ? '-' : '';
        $str = (string) $node->value;
        switch ($kind) {
            case Scalar\LNumber::KIND_BIN:
                return $sign . '0b' . base_convert($str, 10, 2);
            case Scalar\LNumber::KIND_OCT:
                return $sign . '0' . base_convert($str, 10, 8);
            case Scalar\LNumber::KIND_HEX:
                return $sign . '0x' . base_convert($str, 10, 16);
        }
        throw new \Exception('Invalid number kind');
    }

    protected function pScalar_DNumber(Scalar\DNumber $node) {
        if (!is_finite($node->value)) {
            if ($node->value === \INF) {
                return '\INF';
            } elseif ($node->value === -\INF) {
                return '-\INF';
            } else {
                return '\NAN';
            }
        }

        // Try to find a short full-precision representation
        $stringValue = sprintf('%.16G', $node->value);
        if ($node->value !== (double) $stringValue) {
            $stringValue = sprintf('%.17G', $node->value);
        }

        // %G is locale dependent and there exists no locale-independent alternative. We don't want
        // mess with switching locales here, so let's assume that a comma is the only non-standard
        // decimal separator we may encounter...
        $stringValue = str_replace(',', '.', $stringValue);

        // ensure that number is really printed as float
        return preg_match('/^-?[0-9]+$/', $stringValue) ? $stringValue . '.0' : $stringValue;
    }

    // Assignments

    protected function pExpr_Assign(Expr\Assign $node) {
        return $this->pInfixOp('Expr_Assign', $node->var, ' = ', $node->expr);
    }

    protected function pExpr_AssignRef(Expr\AssignRef $node) {
        return $this->pInfixOp('Expr_AssignRef', $node->var, ' =& ', $node->expr);
    }

    protected function pExpr_AssignOp_Plus(AssignOp\Plus $node) {
        return $this->pInfixOp('Expr_AssignOp_Plus', $node->var, ' += ', $node->expr);
    }

    protected function pExpr_AssignOp_Minus(AssignOp\Minus $node) {
        return $this->pInfixOp('Expr_AssignOp_Minus', $node->var, ' -= ', $node->expr);
    }

    protected function pExpr_AssignOp_Mul(AssignOp\Mul $node) {
        return $this->pInfixOp('Expr_AssignOp_Mul', $node->var, ' *= ', $node->expr);
    }

    protected function pExpr_AssignOp_Div(AssignOp\Div $node) {
        return $this->pInfixOp('Expr_AssignOp_Div', $node->var, ' /= ', $node->expr);
    }

    protected function pExpr_AssignOp_Concat(AssignOp\Concat $node) {
        return $this->pInfixOp('Expr_AssignOp_Concat', $node->var, ' .= ', $node->expr);
    }

    protected function pExpr_AssignOp_Mod(AssignOp\Mod $node) {
        return $this->pInfixOp('Expr_AssignOp_Mod', $node->var, ' %= ', $node->expr);
    }

    protected function pExpr_AssignOp_BitwiseAnd(AssignOp\BitwiseAnd $node) {
        return $this->pInfixOp('Expr_AssignOp_BitwiseAnd', $node->var, ' &= ', $node->expr);
    }

    protected function pExpr_AssignOp_BitwiseOr(AssignOp\BitwiseOr $node) {
        return $this->pInfixOp('Expr_AssignOp_BitwiseOr', $node->var, ' |= ', $node->expr);
    }

    protected function pExpr_AssignOp_BitwiseXor(AssignOp\BitwiseXor $node) {
        return $this->pInfixOp('Expr_AssignOp_BitwiseXor', $node->var, ' ^= ', $node->expr);
    }

    protected function pExpr_AssignOp_ShiftLeft(AssignOp\ShiftLeft $node) {
        return $this->pInfixOp('Expr_AssignOp_ShiftLeft', $node->var, ' <<= ', $node->expr);
    }

    protected function pExpr_AssignOp_ShiftRight(AssignOp\ShiftRight $node) {
        return $this->pInfixOp('Expr_AssignOp_ShiftRight', $node->var, ' >>= ', $node->expr);
    }

    protected function pExpr_AssignOp_Pow(AssignOp\Pow $node) {
        return $this->pInfixOp('Expr_AssignOp_Pow', $node->var, ' **= ', $node->expr);
    }

    // Binary expressions

    protected function pExpr_BinaryOp_Plus(BinaryOp\Plus $node) {
        return $this->pInfixOp('Expr_BinaryOp_Plus', $node->left, ' + ', $node->right);
    }

    protected function pExpr_BinaryOp_Minus(BinaryOp\Minus $node) {
        return $this->pInfixOp('Expr_BinaryOp_Minus', $node->left, ' - ', $node->right);
    }

    protected function pExpr_BinaryOp_Mul(BinaryOp\Mul $node) {
        return $this->pInfixOp('Expr_BinaryOp_Mul', $node->left, ' * ', $node->right);
    }

    protected function pExpr_BinaryOp_Div(BinaryOp\Div $node) {
        return $this->pInfixOp('Expr_BinaryOp_Div', $node->left, ' / ', $node->right);
    }

    protected function pExpr_BinaryOp_Concat(BinaryOp\Concat $node) {
        return $this->pInfixOp('Expr_BinaryOp_Concat', $node->left, ' . ', $node->right);
    }

    protected function pExpr_BinaryOp_Mod(BinaryOp\Mod $node) {
        return $this->pInfixOp('Expr_BinaryOp_Mod', $node->left, ' % ', $node->right);
    }

    protected function pExpr_BinaryOp_BooleanAnd(BinaryOp\BooleanAnd $node) {
        return $this->pInfixOp('Expr_BinaryOp_BooleanAnd', $node->left, ' && ', $node->right);
    }

    protected function pExpr_BinaryOp_BooleanOr(BinaryOp\BooleanOr $node) {
        return $this->pInfixOp('Expr_BinaryOp_BooleanOr', $node->left, ' || ', $node->right);
    }

    protected function pExpr_BinaryOp_BitwiseAnd(BinaryOp\BitwiseAnd $node) {
        return $this->pInfixOp('Expr_BinaryOp_BitwiseAnd', $node->left, ' & ', $node->right);
    }

    protected function pExpr_BinaryOp_BitwiseOr(BinaryOp\BitwiseOr $node) {
        return $this->pInfixOp('Expr_BinaryOp_BitwiseOr', $node->left, ' | ', $node->right);
    }

    protected function pExpr_BinaryOp_BitwiseXor(BinaryOp\BitwiseXor $node) {
        return $this->pInfixOp('Expr_BinaryOp_BitwiseXor', $node->left, ' ^ ', $node->right);
    }

    protected function pExpr_BinaryOp_ShiftLeft(BinaryOp\ShiftLeft $node) {
        return $this->pInfixOp('Expr_BinaryOp_ShiftLeft', $node->left, ' << ', $node->right);
    }

    protected function pExpr_BinaryOp_ShiftRight(BinaryOp\ShiftRight $node) {
        return $this->pInfixOp('Expr_BinaryOp_ShiftRight', $node->left, ' >> ', $node->right);
    }

    protected function pExpr_BinaryOp_Pow(BinaryOp\Pow $node) {
        return $this->pInfixOp('Expr_BinaryOp_Pow', $node->left, ' ** ', $node->right);
    }

    protected function pExpr_BinaryOp_LogicalAnd(BinaryOp\LogicalAnd $node) {
        return $this->pInfixOp('Expr_BinaryOp_LogicalAnd', $node->left, ' and ', $node->right);
    }

    protected function pExpr_BinaryOp_LogicalOr(BinaryOp\LogicalOr $node) {
        return $this->pInfixOp('Expr_BinaryOp_LogicalOr', $node->left, ' or ', $node->right);
    }

    protected function pExpr_BinaryOp_LogicalXor(BinaryOp\LogicalXor $node) {
        return $this->pInfixOp('Expr_BinaryOp_LogicalXor', $node->left, ' xor ', $node->right);
    }

    protected function pExpr_BinaryOp_Equal(BinaryOp\Equal $node) {
        return $this->pInfixOp('Expr_BinaryOp_Equal', $node->left, ' == ', $node->right);
    }

    protected function pExpr_BinaryOp_NotEqual(BinaryOp\NotEqual $node) {
        return $this->pInfixOp('Expr_BinaryOp_NotEqual', $node->left, ' != ', $node->right);
    }

    protected function pExpr_BinaryOp_Identical(BinaryOp\Identical $node) {
        return $this->pInfixOp('Expr_BinaryOp_Identical', $node->left, ' === ', $node->right);
    }

    protected function pExpr_BinaryOp_NotIdentical(BinaryOp\NotIdentical $node) {
        return $this->pInfixOp('Expr_BinaryOp_NotIdentical', $node->left, ' !== ', $node->right);
    }

    protected function pExpr_BinaryOp_Spaceship(BinaryOp\Spaceship $node) {
        return $this->pInfixOp('Expr_BinaryOp_Spaceship', $node->left, ' <=> ', $node->right);
    }

    protected function pExpr_BinaryOp_Greater(BinaryOp\Greater $node) {
        return $this->pInfixOp('Expr_BinaryOp_Greater', $node->left, ' > ', $node->right);
    }

    protected function pExpr_BinaryOp_GreaterOrEqual(BinaryOp\GreaterOrEqual $node) {
        return $this->pInfixOp('Expr_BinaryOp_GreaterOrEqual', $node->left, ' >= ', $node->right);
    }

    protected function pExpr_BinaryOp_Smaller(BinaryOp\Smaller $node) {
        return $this->pInfixOp('Expr_BinaryOp_Smaller', $node->left, ' < ', $node->right);
    }

    protected function pExpr_BinaryOp_SmallerOrEqual(BinaryOp\SmallerOrEqual $node) {
        return $this->pInfixOp('Expr_BinaryOp_SmallerOrEqual', $node->left, ' <= ', $node->right);
    }

    protected function pExpr_BinaryOp_Coalesce(BinaryOp\Coalesce $node) {
        return $this->pInfixOp('Expr_BinaryOp_Coalesce', $node->left, ' ?? ', $node->right);
    }

    protected function pExpr_Instanceof(Expr\Instanceof_ $node) {
        return $this->pInfixOp('Expr_Instanceof', $node->expr, ' instanceof ', $node->class);
    }

    // Unary expressions

    protected function pExpr_BooleanNot(Expr\BooleanNot $node) {
        return $this->pPrefixOp('Expr_BooleanNot', '!', $node->expr);
    }

    protected function pExpr_BitwiseNot(Expr\BitwiseNot $node) {
        return $this->pPrefixOp('Expr_BitwiseNot', '~', $node->expr);
    }

    protected function pExpr_UnaryMinus(Expr\UnaryMinus $node) {
        if ($node->expr instanceof Expr\UnaryMinus || $node->expr instanceof Expr\PreDec) {
            // Enforce -(-$expr) instead of --$expr
            return '-(' . $this->p($node->expr) . ')';
        }
        return $this->pPrefixOp('Expr_UnaryMinus', '-', $node->expr);
    }

    protected function pExpr_UnaryPlus(Expr\UnaryPlus $node) {
        if ($node->expr instanceof Expr\UnaryPlus || $node->expr instanceof Expr\PreInc) {
            // Enforce +(+$expr) instead of ++$expr
            return '+(' . $this->p($node->expr) . ')';
        }
        return $this->pPrefixOp('Expr_UnaryPlus', '+', $node->expr);
    }

    protected function pExpr_PreInc(Expr\PreInc $node) {
        return $this->pPrefixOp('Expr_PreInc', '++', $node->var);
    }

    protected function pExpr_PreDec(Expr\PreDec $node) {
        return $this->pPrefixOp('Expr_PreDec', '--', $node->var);
    }

    protected function pExpr_PostInc(Expr\PostInc $node) {
        return $this->pPostfixOp('Expr_PostInc', $node->var, '++');
    }

    protected function pExpr_PostDec(Expr\PostDec $node) {
        return $this->pPostfixOp('Expr_PostDec', $node->var, '--');
    }

    protected function pExpr_ErrorSuppress(Expr\ErrorSuppress $node) {
        return $this->pPrefixOp('Expr_ErrorSuppress', '@', $node->expr);
    }

    protected function pExpr_YieldFrom(Expr\YieldFrom $node) {
        return $this->pPrefixOp('Expr_YieldFrom', 'yield from ', $node->expr);
    }

    protected function pExpr_Print(Expr\Print_ $node) {
        return $this->pPrefixOp('Expr_Print', 'print ', $node->expr);
    }

    // Casts

    protected function pExpr_Cast_Int(Cast\Int_ $node) {
        return $this->pPrefixOp('Expr_Cast_Int', '(int) ', $node->expr);
    }

    protected function pExpr_Cast_Double(Cast\Double $node) {
        return $this->pPrefixOp('Expr_Cast_Double', '(double) ', $node->expr);
    }

    protected function pExpr_Cast_String(Cast\String_ $node) {
        return $this->pPrefixOp('Expr_Cast_String', '(string) ', $node->expr);
    }

    protected function pExpr_Cast_Array(Cast\Array_ $node) {
        return $this->pPrefixOp('Expr_Cast_Array', '(array) ', $node->expr);
    }

    protected function pExpr_Cast_Object(Cast\Object_ $node) {
        return $this->pPrefixOp('Expr_Cast_Object', '(object) ', $node->expr);
    }

    protected function pExpr_Cast_Bool(Cast\Bool_ $node) {
        return $this->pPrefixOp('Expr_Cast_Bool', '(bool) ', $node->expr);
    }

    protected function pExpr_Cast_Unset(Cast\Unset_ $node) {
        return $this->pPrefixOp('Expr_Cast_Unset', '(unset) ', $node->expr);
    }

    // Function calls and similar constructs

    protected function pExpr_FuncCall(Expr\FuncCall $node) {
        return $this->pCallLhs($node->name)
             . '(' . $this->pMaybeMultiline($node->args) . ')';
    }

    protected function pExpr_MethodCall(Expr\MethodCall $node) {
        return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name)
             . '(' . $this->pMaybeMultiline($node->args) . ')';
    }

    protected function pExpr_StaticCall(Expr\StaticCall $node) {
        return $this->pDereferenceLhs($node->class) . '::'
             . ($node->name instanceof Expr
                ? ($node->name instanceof Expr\Variable
                   ? $this->p($node->name)
                   : '{' . $this->p($node->name) . '}')
                : $node->name)
             . '(' . $this->pMaybeMultiline($node->args) . ')';
    }

    protected function pExpr_Empty(Expr\Empty_ $node) {
        return 'empty(' . $this->p($node->expr) . ')';
    }

    protected function pExpr_Isset(Expr\Isset_ $node) {
        return 'isset(' . $this->pCommaSeparated($node->vars) . ')';
    }

    protected function pExpr_Eval(Expr\Eval_ $node) {
        return 'eval(' . $this->p($node->expr) . ')';
    }

    protected function pExpr_Include(Expr\Include_ $node) {
        static $map = array(
            Expr\Include_::TYPE_INCLUDE      => 'include',
            Expr\Include_::TYPE_INCLUDE_ONCE => 'include_once',
            Expr\Include_::TYPE_REQUIRE      => 'require',
            Expr\Include_::TYPE_REQUIRE_ONCE => 'require_once',
        );

        return $map[$node->type] . ' ' . $this->p($node->expr);
    }

    protected function pExpr_List(Expr\List_ $node) {
        return 'list(' . $this->pCommaSeparated($node->items) . ')';
    }

    // Other

    protected function pExpr_Error(Expr\Error $node) {
        throw new \LogicException('Cannot pretty-print AST with Error nodes');
    }

    protected function pExpr_Variable(Expr\Variable $node) {
        if ($node->name instanceof Expr) {
            return '${' . $this->p($node->name) . '}';
        } else {
            return '$' . $node->name;
        }
    }

    protected function pExpr_Array(Expr\Array_ $node) {
        $syntax = $node->getAttribute('kind',
            $this->options['shortArraySyntax'] ? Expr\Array_::KIND_SHORT : Expr\Array_::KIND_LONG);
        if ($syntax === Expr\Array_::KIND_SHORT) {
            return '[' . $this->pMaybeMultiline($node->items, true) . ']';
        } else {
            return 'array(' . $this->pMaybeMultiline($node->items, true) . ')';
        }
    }

    protected function pExpr_ArrayItem(Expr\ArrayItem $node) {
        return (null !== $node->key ? $this->p($node->key) . ' => ' : '')
             . ($node->byRef ? '&' : '') . $this->p($node->value);
    }

    protected function pExpr_ArrayDimFetch(Expr\ArrayDimFetch $node) {
        return $this->pDereferenceLhs($node->var)
             . '[' . (null !== $node->dim ? $this->p($node->dim) : '') . ']';
    }

    protected function pExpr_ConstFetch(Expr\ConstFetch $node) {
        return $this->p($node->name);
    }

    protected function pExpr_ClassConstFetch(Expr\ClassConstFetch $node) {
        return $this->p($node->class) . '::'
             . (is_string($node->name) ? $node->name : $this->p($node->name));
    }

    protected function pExpr_PropertyFetch(Expr\PropertyFetch $node) {
        return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name);
    }

    protected function pExpr_StaticPropertyFetch(Expr\StaticPropertyFetch $node) {
        return $this->pDereferenceLhs($node->class) . '::$' . $this->pObjectProperty($node->name);
    }

    protected function pExpr_ShellExec(Expr\ShellExec $node) {
        return '`' . $this->pEncapsList($node->parts, '`') . '`';
    }

    protected function pExpr_Closure(Expr\Closure $node) {
        return ($node->static ? 'static ' : '')
             . 'function ' . ($node->byRef ? '&' : '')
             . '(' . $this->pCommaSeparated($node->params) . ')'
             . (!empty($node->uses) ? ' use(' . $this->pCommaSeparated($node->uses) . ')': '')
             . (null !== $node->returnType ? ' : ' . $this->pType($node->returnType) : '')
             . ' {' . $this->pStmts($node->stmts) . "\n" . '}';
    }

    protected function pExpr_ClosureUse(Expr\ClosureUse $node) {
        return ($node->byRef ? '&' : '') . '$' . $node->var;
    }

    protected function pExpr_New(Expr\New_ $node) {
        if ($node->class instanceof Stmt\Class_) {
            $args = $node->args ? '(' . $this->pMaybeMultiline($node->args) . ')' : '';
            return 'new ' . $this->pClassCommon($node->class, $args);
        }
        return 'new ' . $this->p($node->class) . '(' . $this->pMaybeMultiline($node->args) . ')';
    }

    protected function pExpr_Clone(Expr\Clone_ $node) {
        return 'clone ' . $this->p($node->expr);
    }

    protected function pExpr_Ternary(Expr\Ternary $node) {
        // a bit of cheating: we treat the ternary as a binary op where the ?...: part is the operator.
        // this is okay because the part between ? and : never needs parentheses.
        return $this->pInfixOp('Expr_Ternary',
            $node->cond, ' ?' . (null !== $node->if ? ' ' . $this->p($node->if) . ' ' : '') . ': ', $node->else
        );
    }

    protected function pExpr_Exit(Expr\Exit_ $node) {
        $kind = $node->getAttribute('kind', Expr\Exit_::KIND_DIE);
        return ($kind === Expr\Exit_::KIND_EXIT ? 'exit' : 'die')
             . (null !== $node->expr ? '(' . $this->p($node->expr) . ')' : '');
    }

    protected function pExpr_Yield(Expr\Yield_ $node) {
        if ($node->value === null) {
            return 'yield';
        } else {
            // this is a bit ugly, but currently there is no way to detect whether the parentheses are necessary
            return '(yield '
                 . ($node->key !== null ? $this->p($node->key) . ' => ' : '')
                 . $this->p($node->value)
                 . ')';
        }
    }

    // Declarations

    protected function pStmt_Namespace(Stmt\Namespace_ $node) {
        if ($this->canUseSemicolonNamespaces) {
            return 'namespace ' . $this->p($node->name) . ';' . "\n" . $this->pStmts($node->stmts, false);
        } else {
            return 'namespace' . (null !== $node->name ? ' ' . $this->p($node->name) : '')
                 . ' {' . $this->pStmts($node->stmts) . "\n" . '}';
        }
    }

    protected function pStmt_Use(Stmt\Use_ $node) {
        return 'use ' . $this->pUseType($node->type)
             . $this->pCommaSeparated($node->uses) . ';';
    }

    protected function pStmt_GroupUse(Stmt\GroupUse $node) {
        return 'use ' . $this->pUseType($node->type) . $this->pName($node->prefix)
             . '\{' . $this->pCommaSeparated($node->uses) . '};';
    }

    protected function pStmt_UseUse(Stmt\UseUse $node) {
        return $this->pUseType($node->type) . $this->p($node->name)
             . ($node->name->getLast() !== $node->alias ? ' as ' . $node->alias : '');
    }

    protected function pUseType($type) {
        return $type === Stmt\Use_::TYPE_FUNCTION ? 'function '
            : ($type === Stmt\Use_::TYPE_CONSTANT ? 'const ' : '');
    }

    protected function pStmt_Interface(Stmt\Interface_ $node) {
        return 'interface ' . $node->name
             . (!empty($node->extends) ? ' extends ' . $this->pCommaSeparated($node->extends) : '')
             . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}';
    }

    protected function pStmt_Class(Stmt\Class_ $node) {
        return $this->pClassCommon($node, ' ' . $node->name);
    }

    protected function pStmt_Trait(Stmt\Trait_ $node) {
        return 'trait ' . $node->name
             . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}';
    }

    protected function pStmt_TraitUse(Stmt\TraitUse $node) {
        return 'use ' . $this->pCommaSeparated($node->traits)
             . (empty($node->adaptations)
                ? ';'
                : ' {' . $this->pStmts($node->adaptations) . "\n" . '}');
    }

    protected function pStmt_TraitUseAdaptation_Precedence(Stmt\TraitUseAdaptation\Precedence $node) {
        return $this->p($node->trait) . '::' . $node->method
             . ' insteadof ' . $this->pCommaSeparated($node->insteadof) . ';';
    }

    protected function pStmt_TraitUseAdaptation_Alias(Stmt\TraitUseAdaptation\Alias $node) {
        return (null !== $node->trait ? $this->p($node->trait) . '::' : '')
             . $node->method . ' as'
             . (null !== $node->newModifier ? ' ' . rtrim($this->pModifiers($node->newModifier), ' ') : '')
             . (null !== $node->newName     ? ' ' . $node->newName                        : '')
             . ';';
    }

    protected function pStmt_Property(Stmt\Property $node) {
        return (0 === $node->flags ? 'var ' : $this->pModifiers($node->flags)) . $this->pCommaSeparated($node->props) . ';';
    }

    protected function pStmt_PropertyProperty(Stmt\PropertyProperty $node) {
        return '$' . $node->name
             . (null !== $node->default ? ' = ' . $this->p($node->default) : '');
    }

    protected function pStmt_ClassMethod(Stmt\ClassMethod $node) {
        return $this->pModifiers($node->flags)
             . 'function ' . ($node->byRef ? '&' : '') . $node->name
             . '(' . $this->pCommaSeparated($node->params) . ')'
             . (null !== $node->returnType ? ' : ' . $this->pType($node->returnType) : '')
             . (null !== $node->stmts
                ? "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}'
                : ';');
    }

    protected function pStmt_ClassConst(Stmt\ClassConst $node) {
        return $this->pModifiers($node->flags)
             . 'const ' . $this->pCommaSeparated($node->consts) . ';';
    }

    protected function pStmt_Function(Stmt\Function_ $node) {
        return 'function ' . ($node->byRef ? '&' : '') . $node->name
             . '(' . $this->pCommaSeparated($node->params) . ')'
             . (null !== $node->returnType ? ' : ' . $this->pType($node->returnType) : '')
             . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}';
    }

    protected function pStmt_Const(Stmt\Const_ $node) {
        return 'const ' . $this->pCommaSeparated($node->consts) . ';';
    }

    protected function pStmt_Declare(Stmt\Declare_ $node) {
        return 'declare (' . $this->pCommaSeparated($node->declares) . ')'
             . (null !== $node->stmts ? ' {' . $this->pStmts($node->stmts) . "\n" . '}' : ';');
    }

    protected function pStmt_DeclareDeclare(Stmt\DeclareDeclare $node) {
        return $node->key . '=' . $this->p($node->value);
    }

    // Control flow

    protected function pStmt_If(Stmt\If_ $node) {
        return 'if (' . $this->p($node->cond) . ') {'
             . $this->pStmts($node->stmts) . "\n" . '}'
             . $this->pImplode($node->elseifs)
             . (null !== $node->else ? $this->p($node->else) : '');
    }

    protected function pStmt_ElseIf(Stmt\ElseIf_ $node) {
        return ' elseif (' . $this->p($node->cond) . ') {'
             . $this->pStmts($node->stmts) . "\n" . '}';
    }

    protected function pStmt_Else(Stmt\Else_ $node) {
        return ' else {' . $this->pStmts($node->stmts) . "\n" . '}';
    }

    protected function pStmt_For(Stmt\For_ $node) {
        return 'for ('
             . $this->pCommaSeparated($node->init) . ';' . (!empty($node->cond) ? ' ' : '')
             . $this->pCommaSeparated($node->cond) . ';' . (!empty($node->loop) ? ' ' : '')
             . $this->pCommaSeparated($node->loop)
             . ') {' . $this->pStmts($node->stmts) . "\n" . '}';
    }

    protected function pStmt_Foreach(Stmt\Foreach_ $node) {
        return 'foreach (' . $this->p($node->expr) . ' as '
             . (null !== $node->keyVar ? $this->p($node->keyVar) . ' => ' : '')
             . ($node->byRef ? '&' : '') . $this->p($node->valueVar) . ') {'
             . $this->pStmts($node->stmts) . "\n" . '}';
    }

    protected function pStmt_While(Stmt\While_ $node) {
        return 'while (' . $this->p($node->cond) . ') {'
             . $this->pStmts($node->stmts) . "\n" . '}';
    }

    protected function pStmt_Do(Stmt\Do_ $node) {
        return 'do {' . $this->pStmts($node->stmts) . "\n"
             . '} while (' . $this->p($node->cond) . ');';
    }

    protected function pStmt_Switch(Stmt\Switch_ $node) {
        return 'switch (' . $this->p($node->cond) . ') {'
             . $this->pStmts($node->cases) . "\n" . '}';
    }

    protected function pStmt_Case(Stmt\Case_ $node) {
        return (null !== $node->cond ? 'case ' . $this->p($node->cond) : 'default') . ':'
             . $this->pStmts($node->stmts);
    }

    protected function pStmt_TryCatch(Stmt\TryCatch $node) {
        return 'try {' . $this->pStmts($node->stmts) . "\n" . '}'
             . $this->pImplode($node->catches)
             . ($node->finally !== null ? $this->p($node->finally) : '');
    }

    protected function pStmt_Catch(Stmt\Catch_ $node) {
        return ' catch (' . $this->pImplode($node->types, '|') . ' $' . $node->var . ') {'
             . $this->pStmts($node->stmts) . "\n" . '}';
    }

    protected function pStmt_Finally(Stmt\Finally_ $node) {
        return ' finally {' . $this->pStmts($node->stmts) . "\n" . '}';
    }

    protected function pStmt_Break(Stmt\Break_ $node) {
        return 'break' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';';
    }

    protected function pStmt_Continue(Stmt\Continue_ $node) {
        return 'continue' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';';
    }

    protected function pStmt_Return(Stmt\Return_ $node) {
        return 'return' . (null !== $node->expr ? ' ' . $this->p($node->expr) : '') . ';';
    }

    protected function pStmt_Throw(Stmt\Throw_ $node) {
        return 'throw ' . $this->p($node->expr) . ';';
    }

    protected function pStmt_Label(Stmt\Label $node) {
        return $node->name . ':';
    }

    protected function pStmt_Goto(Stmt\Goto_ $node) {
        return 'goto ' . $node->name . ';';
    }

    // Other

    protected function pStmt_Echo(Stmt\Echo_ $node) {
        return 'echo ' . $this->pCommaSeparated($node->exprs) . ';';
    }

    protected function pStmt_Static(Stmt\Static_ $node) {
        return 'static ' . $this->pCommaSeparated($node->vars) . ';';
    }

    protected function pStmt_Global(Stmt\Global_ $node) {
        return 'global ' . $this->pCommaSeparated($node->vars) . ';';
    }

    protected function pStmt_StaticVar(Stmt\StaticVar $node) {
        return '$' . $node->name
             . (null !== $node->default ? ' = ' . $this->p($node->default) : '');
    }

    protected function pStmt_Unset(Stmt\Unset_ $node) {
        return 'unset(' . $this->pCommaSeparated($node->vars) . ');';
    }

    protected function pStmt_InlineHTML(Stmt\InlineHTML $node) {
        $newline = $node->getAttribute('hasLeadingNewline', true) ? "\n" : '';
        return '?>' . $this->pNoIndent($newline . $node->value) . '<?php ';
    }

    protected function pStmt_HaltCompiler(Stmt\HaltCompiler $node) {
        return '__halt_compiler();' . $node->remaining;
    }

    protected function pStmt_Nop(Stmt\Nop $node) {
        return '';
    }

    // Helpers

    protected function pType($node) {
        return is_string($node) ? $node : $this->p($node);
    }

    protected function pClassCommon(Stmt\Class_ $node, $afterClassToken) {
        return $this->pModifiers($node->flags)
        . 'class' . $afterClassToken
        . (null !== $node->extends ? ' extends ' . $this->p($node->extends) : '')
        . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '')
        . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}';
    }

    protected function pObjectProperty($node) {
        if ($node instanceof Expr) {
            return '{' . $this->p($node) . '}';
        } else {
            return $node;
        }
    }

    protected function pModifiers($modifiers) {
        return ($modifiers & Stmt\Class_::MODIFIER_PUBLIC    ? 'public '    : '')
             . ($modifiers & Stmt\Class_::MODIFIER_PROTECTED ? 'protected ' : '')
             . ($modifiers & Stmt\Class_::MODIFIER_PRIVATE   ? 'private '   : '')
             . ($modifiers & Stmt\Class_::MODIFIER_STATIC    ? 'static '    : '')
             . ($modifiers & Stmt\Class_::MODIFIER_ABSTRACT  ? 'abstract '  : '')
             . ($modifiers & Stmt\Class_::MODIFIER_FINAL     ? 'final '     : '');
    }

    protected function pEncapsList(array $encapsList, $quote) {
        $return = '';
        foreach ($encapsList as $element) {
            if ($element instanceof Scalar\EncapsedStringPart) {
                $return .= $this->escapeString($element->value, $quote);
            } else {
                $return .= '{' . $this->p($element) . '}';
            }
        }

        return $return;
    }

    protected function escapeString($string, $quote) {
        if (null === $quote) {
            // For doc strings, don't escape newlines
            $escaped = addcslashes($string, "\t\f\v$\\");
        } else {
            $escaped = addcslashes($string, "\n\r\t\f\v$" . $quote . "\\");
        }

        // Escape other control characters
        return preg_replace_callback('/([\0-\10\16-\37])(?=([0-7]?))/', function ($matches) {
            $oct = decoct(ord($matches[1]));
            if ($matches[2] !== '') {
                // If there is a trailing digit, use the full three character form
                return '\\' . str_pad($oct, 3, '0', STR_PAD_LEFT);
            }
            return '\\' . $oct;
        }, $escaped);
    }

    protected function containsEndLabel($string, $label, $atStart = true, $atEnd = true) {
        $start = $atStart ? '(?:^|[\r\n])' : '[\r\n]';
        $end = $atEnd ? '(?:$|[;\r\n])' : '[;\r\n]';
        return false !== strpos($string, $label)
            && preg_match('/' . $start . $label . $end . '/', $string);
    }

    protected function encapsedContainsEndLabel(array $parts, $label) {
        foreach ($parts as $i => $part) {
            $atStart = $i === 0;
            $atEnd = $i === count($parts) - 1;
            if ($part instanceof Scalar\EncapsedStringPart
                && $this->containsEndLabel($part->value, $label, $atStart, $atEnd)
            ) {
                return true;
            }
        }
        return false;
    }

    protected function pDereferenceLhs(Node $node) {
        if ($node instanceof Expr\Variable
            || $node instanceof Name
            || $node instanceof Expr\ArrayDimFetch
            || $node instanceof Expr\PropertyFetch
            || $node instanceof Expr\StaticPropertyFetch
            || $node instanceof Expr\FuncCall
            || $node instanceof Expr\MethodCall
            || $node instanceof Expr\StaticCall
            || $node instanceof Expr\Array_
            || $node instanceof Scalar\String_
            || $node instanceof Expr\ConstFetch
            || $node instanceof Expr\ClassConstFetch
        ) {
            return $this->p($node);
        } else  {
            return '(' . $this->p($node) . ')';
        }
    }

    protected function pCallLhs(Node $node) {
        if ($node instanceof Name
            || $node instanceof Expr\Variable
            || $node instanceof Expr\ArrayDimFetch
            || $node instanceof Expr\FuncCall
            || $node instanceof Expr\MethodCall
            || $node instanceof Expr\StaticCall
            || $node instanceof Expr\Array_
        ) {
            return $this->p($node);
        } else  {
            return '(' . $this->p($node) . ')';
        }
    }

    private function hasNodeWithComments(array $nodes) {
        foreach ($nodes as $node) {
            if ($node && $node->getAttribute('comments')) {
                return true;
            }
        }
        return false;
    }

    private function pMaybeMultiline(array $nodes, $trailingComma = false) {
        if (!$this->hasNodeWithComments($nodes)) {
            return $this->pCommaSeparated($nodes);
        } else {
            return $this->pCommaSeparatedMultiline($nodes, $trailingComma) . "\n";
        }
    }
}
<?php

namespace PhpParser;

use PhpParser\Node\Expr;
use PhpParser\Node\Stmt;

abstract class PrettyPrinterAbstract
{
    protected $precedenceMap = array(
        // [precedence, associativity] where for the latter -1 is %left, 0 is %nonassoc and 1 is %right
        'Expr_BinaryOp_Pow'            => array(  0,  1),
        'Expr_BitwiseNot'              => array( 10,  1),
        'Expr_PreInc'                  => array( 10,  1),
        'Expr_PreDec'                  => array( 10,  1),
        'Expr_PostInc'                 => array( 10, -1),
        'Expr_PostDec'                 => array( 10, -1),
        'Expr_UnaryPlus'               => array( 10,  1),
        'Expr_UnaryMinus'              => array( 10,  1),
        'Expr_Cast_Int'                => array( 10,  1),
        'Expr_Cast_Double'             => array( 10,  1),
        'Expr_Cast_String'             => array( 10,  1),
        'Expr_Cast_Array'              => array( 10,  1),
        'Expr_Cast_Object'             => array( 10,  1),
        'Expr_Cast_Bool'               => array( 10,  1),
        'Expr_Cast_Unset'              => array( 10,  1),
        'Expr_ErrorSuppress'           => array( 10,  1),
        'Expr_Instanceof'              => array( 20,  0),
        'Expr_BooleanNot'              => array( 30,  1),
        'Expr_BinaryOp_Mul'            => array( 40, -1),
        'Expr_BinaryOp_Div'            => array( 40, -1),
        'Expr_BinaryOp_Mod'            => array( 40, -1),
        'Expr_BinaryOp_Plus'           => array( 50, -1),
        'Expr_BinaryOp_Minus'          => array( 50, -1),
        'Expr_BinaryOp_Concat'         => array( 50, -1),
        'Expr_BinaryOp_ShiftLeft'      => array( 60, -1),
        'Expr_BinaryOp_ShiftRight'     => array( 60, -1),
        'Expr_BinaryOp_Smaller'        => array( 70,  0),
        'Expr_BinaryOp_SmallerOrEqual' => array( 70,  0),
        'Expr_BinaryOp_Greater'        => array( 70,  0),
        'Expr_BinaryOp_GreaterOrEqual' => array( 70,  0),
        'Expr_BinaryOp_Equal'          => array( 80,  0),
        'Expr_BinaryOp_NotEqual'       => array( 80,  0),
        'Expr_BinaryOp_Identical'      => array( 80,  0),
        'Expr_BinaryOp_NotIdentical'   => array( 80,  0),
        'Expr_BinaryOp_Spaceship'      => array( 80,  0),
        'Expr_BinaryOp_BitwiseAnd'     => array( 90, -1),
        'Expr_BinaryOp_BitwiseXor'     => array(100, -1),
        'Expr_BinaryOp_BitwiseOr'      => array(110, -1),
        'Expr_BinaryOp_BooleanAnd'     => array(120, -1),
        'Expr_BinaryOp_BooleanOr'      => array(130, -1),
        'Expr_BinaryOp_Coalesce'       => array(140,  1),
        'Expr_Ternary'                 => array(150, -1),
        // parser uses %left for assignments, but they really behave as %right
        'Expr_Assign'                  => array(160,  1),
        'Expr_AssignRef'               => array(160,  1),
        'Expr_AssignOp_Plus'           => array(160,  1),
        'Expr_AssignOp_Minus'          => array(160,  1),
        'Expr_AssignOp_Mul'            => array(160,  1),
        'Expr_AssignOp_Div'            => array(160,  1),
        'Expr_AssignOp_Concat'         => array(160,  1),
        'Expr_AssignOp_Mod'            => array(160,  1),
        'Expr_AssignOp_BitwiseAnd'     => array(160,  1),
        'Expr_AssignOp_BitwiseOr'      => array(160,  1),
        'Expr_AssignOp_BitwiseXor'     => array(160,  1),
        'Expr_AssignOp_ShiftLeft'      => array(160,  1),
        'Expr_AssignOp_ShiftRight'     => array(160,  1),
        'Expr_AssignOp_Pow'            => array(160,  1),
        'Expr_YieldFrom'               => array(165,  1),
        'Expr_Print'                   => array(168,  1),
        'Expr_BinaryOp_LogicalAnd'     => array(170, -1),
        'Expr_BinaryOp_LogicalXor'     => array(180, -1),
        'Expr_BinaryOp_LogicalOr'      => array(190, -1),
        'Expr_Include'                 => array(200, -1),
    );

    protected $noIndentToken;
    protected $docStringEndToken;
    protected $canUseSemicolonNamespaces;
    protected $options;

    /**
     * Creates a pretty printer instance using the given options.
     *
     * Supported options:
     *  * bool $shortArraySyntax = false: Whether to use [] instead of array() as the default array
     *                                    syntax, if the node does not specify a format.
     *
     * @param array $options Dictionary of formatting options
     */
    public function __construct(array $options = []) {
        $this->noIndentToken = '_NO_INDENT_' . mt_rand();
        $this->docStringEndToken = '_DOC_STRING_END_' . mt_rand();

        $defaultOptions = ['shortArraySyntax' => false];
        $this->options = $options + $defaultOptions;
    }

    /**
     * Pretty prints an array of statements.
     *
     * @param Node[] $stmts Array of statements
     *
     * @return string Pretty printed statements
     */
    public function prettyPrint(array $stmts) {
        $this->preprocessNodes($stmts);

        return ltrim($this->handleMagicTokens($this->pStmts($stmts, false)));
    }

    /**
     * Pretty prints an expression.
     *
     * @param Expr $node Expression node
     *
     * @return string Pretty printed node
     */
    public function prettyPrintExpr(Expr $node) {
        return $this->handleMagicTokens($this->p($node));
    }

    /**
     * Pretty prints a file of statements (includes the opening <?php tag if it is required).
     *
     * @param Node[] $stmts Array of statements
     *
     * @return string Pretty printed statements
     */
    public function prettyPrintFile(array $stmts) {
        if (!$stmts) {
            return "<?php\n\n";
        }

        $p = "<?php\n\n" . $this->prettyPrint($stmts);

        if ($stmts[0] instanceof Stmt\InlineHTML) {
            $p = preg_replace('/^<\?php\s+\?>\n?/', '', $p);
        }
        if ($stmts[count($stmts) - 1] instanceof Stmt\InlineHTML) {
            $p = preg_replace('/<\?php$/', '', rtrim($p));
        }

        return $p;
    }

    /**
     * Preprocesses the top-level nodes to initialize pretty printer state.
     *
     * @param Node[] $nodes Array of nodes
     */
    protected function preprocessNodes(array $nodes) {
        /* We can use semicolon-namespaces unless there is a global namespace declaration */
        $this->canUseSemicolonNamespaces = true;
        foreach ($nodes as $node) {
            if ($node instanceof Stmt\Namespace_ && null === $node->name) {
                $this->canUseSemicolonNamespaces = false;
            }
        }
    }

    protected function handleMagicTokens($str) {
        // Drop no-indent tokens
        $str = str_replace($this->noIndentToken, '', $str);

        // Replace doc-string-end tokens with nothing or a newline
        $str = str_replace($this->docStringEndToken . ";\n", ";\n", $str);
        $str = str_replace($this->docStringEndToken, "\n", $str);

        return $str;
    }

    /**
     * Pretty prints an array of nodes (statements) and indents them optionally.
     *
     * @param Node[] $nodes  Array of nodes
     * @param bool   $indent Whether to indent the printed nodes
     *
     * @return string Pretty printed statements
     */
    protected function pStmts(array $nodes, $indent = true) {
        $result = '';
        foreach ($nodes as $node) {
            $comments = $node->getAttribute('comments', array());
            if ($comments) {
                $result .= "\n" . $this->pComments($comments);
                if ($node instanceof Stmt\Nop) {
                    continue;
                }
            }

            $result .= "\n" . $this->p($node) . ($node instanceof Expr ? ';' : '');
        }

        if ($indent) {
            return preg_replace('~\n(?!$|' . $this->noIndentToken . ')~', "\n    ", $result);
        } else {
            return $result;
        }
    }

    /**
     * Pretty prints a node.
     *
     * @param Node $node Node to be pretty printed
     *
     * @return string Pretty printed node
     */
    protected function p(Node $node) {
        return $this->{'p' . $node->getType()}($node);
    }

    protected function pInfixOp($type, Node $leftNode, $operatorString, Node $rightNode) {
        list($precedence, $associativity) = $this->precedenceMap[$type];

        return $this->pPrec($leftNode, $precedence, $associativity, -1)
             . $operatorString
             . $this->pPrec($rightNode, $precedence, $associativity, 1);
    }

    protected function pPrefixOp($type, $operatorString, Node $node) {
        list($precedence, $associativity) = $this->precedenceMap[$type];
        return $operatorString . $this->pPrec($node, $precedence, $associativity, 1);
    }

    protected function pPostfixOp($type, Node $node, $operatorString) {
        list($precedence, $associativity) = $this->precedenceMap[$type];
        return $this->pPrec($node, $precedence, $associativity, -1) . $operatorString;
    }

    /**
     * Prints an expression node with the least amount of parentheses necessary to preserve the meaning.
     *
     * @param Node $node                Node to pretty print
     * @param int  $parentPrecedence    Precedence of the parent operator
     * @param int  $parentAssociativity Associativity of parent operator
     *                                  (-1 is left, 0 is nonassoc, 1 is right)
     * @param int  $childPosition       Position of the node relative to the operator
     *                                  (-1 is left, 1 is right)
     *
     * @return string The pretty printed node
     */
    protected function pPrec(Node $node, $parentPrecedence, $parentAssociativity, $childPosition) {
        $type = $node->getType();
        if (isset($this->precedenceMap[$type])) {
            $childPrecedence = $this->precedenceMap[$type][0];
            if ($childPrecedence > $parentPrecedence
                || ($parentPrecedence == $childPrecedence && $parentAssociativity != $childPosition)
            ) {
                return '(' . $this->p($node) . ')';
            }
        }

        return $this->p($node);
    }

    /**
     * Pretty prints an array of nodes and implodes the printed values.
     *
     * @param Node[] $nodes Array of Nodes to be printed
     * @param string $glue  Character to implode with
     *
     * @return string Imploded pretty printed nodes
     */
    protected function pImplode(array $nodes, $glue = '') {
        $pNodes = array();
        foreach ($nodes as $node) {
            if (null === $node) {
                $pNodes[] = '';
            } else {
                $pNodes[] = $this->p($node);
            }
        }

        return implode($glue, $pNodes);
    }

    /**
     * Pretty prints an array of nodes and implodes the printed values with commas.
     *
     * @param Node[] $nodes Array of Nodes to be printed
     *
     * @return string Comma separated pretty printed nodes
     */
    protected function pCommaSeparated(array $nodes) {
        return $this->pImplode($nodes, ', ');
    }

    /**
     * Pretty prints a comma-separated list of nodes in multiline style, including comments.
     *
     * The result includes a leading newline and one level of indentation (same as pStmts).
     *
     * @param Node[] $nodes         Array of Nodes to be printed
     * @param bool   $trailingComma Whether to use a trailing comma
     *
     * @return string Comma separated pretty printed nodes in multiline style
     */
    protected function pCommaSeparatedMultiline(array $nodes, $trailingComma) {
        $result = '';
        $lastIdx = count($nodes) - 1;
        foreach ($nodes as $idx => $node) {
            if ($node !== null) {
                $comments = $node->getAttribute('comments', array());
                if ($comments) {
                    $result .= "\n" . $this->pComments($comments);
                }

                $result .= "\n" . $this->p($node);
            } else {
                $result .= "\n";
            }
            if ($trailingComma || $idx !== $lastIdx) {
                $result .= ',';
            }
        }

        return preg_replace('~\n(?!$|' . $this->noIndentToken . ')~', "\n    ", $result);
    }

    /**
     * Signals the pretty printer that a string shall not be indented.
     *
     * @param string $string Not to be indented string
     *
     * @return string String marked with $this->noIndentToken's.
     */
    protected function pNoIndent($string) {
        return str_replace("\n", "\n" . $this->noIndentToken, $string);
    }

    /**
     * Prints reformatted text of the passed comments.
     *
     * @param Comment[] $comments List of comments
     *
     * @return string Reformatted text of comments
     */
    protected function pComments(array $comments) {
        $formattedComments = [];

        foreach ($comments as $comment) {
            $formattedComments[] = $comment->getReformattedText();
        }

        return implode("\n", $formattedComments);
    }
}
<?php

namespace PhpParser;

/**
 * @deprecated
 */
interface Serializer
{
    /**
     * Serializes statements into some string format.
     *
     * @param array $nodes Statements
     *
     * @return string Serialized string
     */
    public function serialize(array $nodes);
}<?php

namespace PhpParser\Serializer;

use PhpParser\Comment;
use PhpParser\Node;
use PhpParser\Serializer;
use XMLWriter;

/**
 * @deprecated
 */
class XML implements Serializer
{
    protected $writer;

    /**
     * Constructs a XML serializer.
     */
    public function __construct() {
        $this->writer = new XMLWriter;
        $this->writer->openMemory();
        $this->writer->setIndent(true);
    }

    public function serialize(array $nodes) {
        $this->writer->flush();
        $this->writer->startDocument('1.0', 'UTF-8');

        $this->writer->startElement('AST');
        $this->writer->writeAttribute('xmlns:node',      'http://nikic.github.com/PHPParser/XML/node');
        $this->writer->writeAttribute('xmlns:subNode',   'http://nikic.github.com/PHPParser/XML/subNode');
        $this->writer->writeAttribute('xmlns:attribute', 'http://nikic.github.com/PHPParser/XML/attribute');
        $this->writer->writeAttribute('xmlns:scalar',    'http://nikic.github.com/PHPParser/XML/scalar');

        $this->_serialize($nodes);

        $this->writer->endElement();

        return $this->writer->outputMemory();
    }

    protected function _serialize($node) {
        if ($node instanceof Node) {
            $this->writer->startElement('node:' . $node->getType());

            foreach ($node->getAttributes() as $name => $value) {
                $this->writer->startElement('attribute:' . $name);
                $this->_serialize($value);
                $this->writer->endElement();
            }

            foreach ($node as $name => $subNode) {
                $this->writer->startElement('subNode:' . $name);
                $this->_serialize($subNode);
                $this->writer->endElement();
            }

            $this->writer->endElement();
        } elseif ($node instanceof Comment) {
            $this->writer->startElement('comment');
            $this->writer->writeAttribute('isDocComment', $node instanceof Comment\Doc ? 'true' : 'false');
            $this->writer->writeAttribute('line', (string) $node->getLine());
            $this->writer->text($node->getText());
            $this->writer->endElement();
        } elseif (is_array($node)) {
            $this->writer->startElement('scalar:array');
            foreach ($node as $subNode) {
                $this->_serialize($subNode);
            }
            $this->writer->endElement();
        } elseif (is_string($node)) {
            $this->writer->writeElement('scalar:string', $node);
        } elseif (is_int($node)) {
            $this->writer->writeElement('scalar:int', (string) $node);
        } elseif (is_float($node)) {
            // TODO Higher precision conversion?
            $this->writer->writeElement('scalar:float', (string) $node);
        } elseif (true === $node) {
            $this->writer->writeElement('scalar:true');
        } elseif (false === $node) {
            $this->writer->writeElement('scalar:false');
        } elseif (null === $node) {
            $this->writer->writeElement('scalar:null');
        } else {
            throw new \InvalidArgumentException('Unexpected node type');
        }
    }
}
<?php

namespace PhpParser;

/**
 * @deprecated
 */
interface Unserializer
{
    /**
     * Unserializes a string in some format into a node tree.
     *
     * @param string $string Serialized string
     *
     * @return mixed Node tree
     */
    public function unserialize($string);
}
<?php

namespace PhpParser\Unserializer;

use DomainException;
use PhpParser\Unserializer;
use XMLReader;

/**
 * @deprecated
 */
class XML implements Unserializer
{
    protected $reader;

    public function __construct() {
        $this->reader = new XMLReader;
    }

    public function unserialize($string) {
        $this->reader->XML($string);

        $this->reader->read();
        if ('AST' !== $this->reader->name) {
            throw new DomainException('AST root element not found');
        }

        return $this->read($this->reader->depth);
    }

    protected function read($depthLimit, $throw = true, &$nodeFound = null) {
        $nodeFound = true;
        while ($this->reader->read() && $depthLimit < $this->reader->depth) {
            if (XMLReader::ELEMENT !== $this->reader->nodeType) {
                continue;
            }

            if ('node' === $this->reader->prefix) {
                return $this->readNode();
            } elseif ('scalar' === $this->reader->prefix) {
                return $this->readScalar();
            } elseif ('comment' === $this->reader->name) {
                return $this->readComment();
            } else {
                throw new DomainException(sprintf('Unexpected node of type "%s"', $this->reader->name));
            }
        }

        $nodeFound = false;
        if ($throw) {
            throw new DomainException('Expected node or scalar');
        }
    }

    protected function readNode() {
        $className = $this->getClassNameFromType($this->reader->localName);

        // create the node without calling it's constructor
        $node = unserialize(
            sprintf(
                "O:%d:\"%s\":1:{s:13:\"\0*\0attributes\";a:0:{}}",
                strlen($className), $className
            )
        );

        $depthLimit = $this->reader->depth;
        while ($this->reader->read() && $depthLimit < $this->reader->depth) {
            if (XMLReader::ELEMENT !== $this->reader->nodeType) {
                continue;
            }

            $type = $this->reader->prefix;
            if ('subNode' !== $type && 'attribute' !== $type) {
                throw new DomainException(
                    sprintf('Expected sub node or attribute, got node of type "%s"', $this->reader->name)
                );
            }

            $name = $this->reader->localName;
            $value = $this->read($this->reader->depth);

            if ('subNode' === $type) {
                $node->$name = $value;
            } else {
                $node->setAttribute($name, $value);
            }
        }

        return $node;
    }

    protected function readScalar() {
        switch ($name = $this->reader->localName) {
            case 'array':
                $depth = $this->reader->depth;
                $array = array();
                while (true) {
                    $node = $this->read($depth, false, $nodeFound);
                    if (!$nodeFound) {
                        break;
                    }
                    $array[] = $node;
                }
                return $array;
            case 'string':
                return $this->reader->readString();
            case 'int':
                return $this->parseInt($this->reader->readString());
            case 'float':
                $text = $this->reader->readString();
                if (false === $float = filter_var($text, FILTER_VALIDATE_FLOAT)) {
                    throw new DomainException(sprintf('"%s" is not a valid float', $text));
                }
                return $float;
            case 'true':
            case 'false':
            case 'null':
                if (!$this->reader->isEmptyElement) {
                    throw new DomainException(sprintf('"%s" scalar must be empty', $name));
                }
                return constant($name);
            default:
                throw new DomainException(sprintf('Unknown scalar type "%s"', $name));
        }
    }

    private function parseInt($text) {
        if (false === $int = filter_var($text, FILTER_VALIDATE_INT)) {
            throw new DomainException(sprintf('"%s" is not a valid integer', $text));
        }
        return $int;
    }

    protected function readComment() {
        $className = $this->reader->getAttribute('isDocComment') === 'true'
            ? 'PhpParser\Comment\Doc'
            : 'PhpParser\Comment'
        ;
        return new $className(
            $this->reader->readString(),
            $this->parseInt($this->reader->getAttribute('line'))
        );
    }

    protected function getClassNameFromType($type) {
        $className = 'PhpParser\\Node\\' . strtr($type, '_', '\\');
        if (!class_exists($className)) {
            $className .= '_';
        }
        if (!class_exists($className)) {
            throw new DomainException(sprintf('Unknown node type "%s"', $type));
        }
        return $className;
    }
}
<?php

if (!class_exists('PhpParser\Autoloader')) {
    require __DIR__ . '/PhpParser/Autoloader.php';
}
PhpParser\Autoloader::register();

Copyright (c) 2016 Marco Pivetta

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

{
    "name": "ocramius/package-versions",
    "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)",
    "type": "composer-plugin",
    "license": "MIT",
    "authors": [
        {
            "name": "Marco Pivetta",
            "email": "ocramius@gmail.com"
        }
    ],
    "require": {
        "php":                 "~7.0",
        "composer-plugin-api": "^1.0"
    },
    "require-dev": {
        "phpunit/phpunit":   "^6.4",
        "humbug/humbug":     "dev-master",
        "composer/composer": "^1.3",
        "ext-zip":           "*"
    },
    "autoload": {
        "psr-4": {
            "PackageVersions\\": "src/PackageVersions"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "PackageVersionsTest\\": "test/PackageVersionsTest"
        }
    },
    "extra": {
        "class": "PackageVersions\\Installer",
        "branch-alias": {
            "dev-master": "2.0.x-dev"
        }
    },
    "scripts": {
        "post-update-cmd":  "PackageVersions\\Installer::dumpVersionsClass",
        "post-install-cmd": "PackageVersions\\Installer::dumpVersionsClass"
    }
}
<?php

namespace PHPStanVendor\PackageVersions;

/**
 * @internal
 *
 * This is a fallback for {@see \PackageVersions\Versions::getVersion()}
 * Do not use this class directly: it is intended to be only used when
 * {@see \PackageVersions\Versions} fails to be generated, which typically
 * happens when running composer with `--no-scripts` flag)
 */
final class FallbackVersions
{
    private function __construct()
    {
    }

    /**
     * @param string $packageName
     *
     * @return string
     *
     * @throws \OutOfBoundsException if a version cannot be located
     * @throws \UnexpectedValueException if the composer.lock file could not be located
     */
    public static function getVersion(string $packageName) : string
    {
        $versions = iterator_to_array(self::getVersions(self::getComposerLockPath()));

        if (! array_key_exists($packageName, $versions)) {
            throw new \OutOfBoundsException(
                'Required package "' . $packageName . '" is not installed: cannot detect its version'
            );
        }

        return $versions[$packageName];
    }

    /**
     * @return string
     *
     * @throws \UnexpectedValueException
     */
    private static function getComposerLockPath() : string
    {
        // bold assumption, but there's not here to fix everyone's problems.
        $checkedPaths = [__DIR__ . '/../../../../../composer.lock', __DIR__ . '/../../composer.lock'];

        foreach ($checkedPaths as $path) {
            if (file_exists($path)) {
                return $path;
            }
        }

        throw new \UnexpectedValueException(sprintf(
            'PackageVersions could not locate your `composer.lock` location. This is assumed to be in %s. '
            . 'If you customized your composer vendor directory and ran composer installation with --no-scripts, '
            . 'then you are on your own, and we can\'t really help you. Fix your shit and cut the tooling some slack.',
            json_encode($checkedPaths)
        ));
    }

    private static function getVersions(string $composerLockFile) : \Generator
    {
        $lockData = json_decode(file_get_contents($composerLockFile), true);

        $lockData['packages-dev'] = $lockData['packages-dev'] ?? [];

        foreach (array_merge($lockData['packages'], $lockData['packages-dev']) as $package) {
            yield $package['name'] => $package['version'] . '@' . (
                $package['source']['reference']?? $package['dist']['reference'] ?? ''
            );
        }

        yield 'unknown/root-package@UNKNOWN';
    }
}
<?php

namespace PHPStanVendor\PackageVersions;

final class Installer implements \Composer\Plugin\PluginInterface, \Composer\EventDispatcher\EventSubscriberInterface
{
    private static $generatedClassTemplate = <<<'PHP'
<?php

namespace PackageVersions;

/**
 * This class is generated by ocramius/package-versions, specifically by
 * @see \PHPStanVendor\PackageVersions\Installer
 *
 * This file is overwritten at every run of `composer install` or `composer update`.
 */
%s
{
    const VERSIONS = %s;

    private function __construct()
    {
    }

    /**
     * @throws \OutOfBoundsException if a version cannot be located
     */
    public static function getVersion(string $packageName) : string
    {
        if (! isset(self::VERSIONS[$packageName])) {
            throw new \OutOfBoundsException(
                'Required package "' . $packageName . '" is not installed: cannot detect its version'
            );
        }

        return self::VERSIONS[$packageName];
    }
}

PHP;

    /**
     * {@inheritDoc}
     */
    public function activate(\Composer\Composer $composer, \Composer\IO\IOInterface $io)
    {
        // Nothing to do here, as all features are provided through event listeners
    }

    /**
     * {@inheritDoc}
     */
    public static function getSubscribedEvents()
    {
        return [
            \Composer\Script\ScriptEvents::POST_INSTALL_CMD => 'dumpVersionsClass',
            \Composer\Script\ScriptEvents::POST_UPDATE_CMD  => 'dumpVersionsClass',
        ];
    }

    /**
     * @param Event $composerEvent
     *
     * @return void
     *
     * @throws \RuntimeException
     */
    public static function dumpVersionsClass(\Composer\Script\Event $composerEvent)
    {
        $composer = $composerEvent->getComposer();
        $versions = iterator_to_array(self::getVersions($composer->getLocker(), $composer->getPackage()));

        if (!array_key_exists('ocramius/package-versions', $versions)) {
            //plugin must be globally installed - we only want to generate versions for projects which specifically
            //require ocramius/package-versions
            return;
        }

        self::writeVersionClassToFile(self::generateVersionsClass($versions), $composer, $composerEvent->getIO());
    }

    private static function generateVersionsClass(array $versions) : string
    {
        return sprintf(
            self::$generatedClassTemplate,
            'fin' . 'al ' . 'cla' . 'ss ' . 'Versions', // note: workaround for regex-based code parsers :-(
            var_export($versions, true)
        );
    }

    /**
     * @param string $versionClassSource
     * @param Composer $composer
     * @param IOInterface $io
     *
     * @return void
     *
     * @throws \RuntimeException
     */
    private static function writeVersionClassToFile(string $versionClassSource, \Composer\Composer $composer, \Composer\IO\IOInterface $io)
    {
        $installPath = self::locateRootPackageInstallPath($composer->getConfig(), $composer->getPackage())
            . '/src/PackageVersions/Versions.php';

        if (! file_exists(dirname($installPath))) {
            $io->write('<info>ocramius/package-versions:</info> Package not found (probably scheduled for removal); generation of version class skipped.');

            return;
        }

        $io->write('<info>ocramius/package-versions:</info>  Generating version class...');

        file_put_contents($installPath, $versionClassSource);
        chmod($installPath, 0664);

        $io->write('<info>ocramius/package-versions:</info> ...done generating version class');
    }

    /**
     * @param Config               $composerConfig
     * @param RootPackageInterface $rootPackage
     *
     * @return string
     *
     * @throws \RuntimeException
     */
    private static function locateRootPackageInstallPath(
        \Composer\Config $composerConfig,
        \Composer\Package\RootPackageInterface $rootPackage
    ) : string {
        if ('ocramius/package-versions' === self::getRootPackageAlias($rootPackage)->getName()) {
            return dirname($composerConfig->get('vendor-dir'));
        }

        return $composerConfig->get('vendor-dir') . '/ocramius/package-versions';
    }

    private static function getRootPackageAlias(\Composer\Package\RootPackageInterface $rootPackage) : \Composer\Package\PackageInterface
    {
        $package = $rootPackage;

        while ($package instanceof \Composer\Package\AliasPackage) {
            $package = $package->getAliasOf();
        }

        return $package;
    }

    /**
     * @param Locker               $locker
     * @param RootPackageInterface $rootPackage
     *
     * @return \Generator|\string[]
     */
    private static function getVersions(\Composer\Package\Locker $locker, \Composer\Package\RootPackageInterface $rootPackage) : \Generator
    {
        $lockData = $locker->getLockData();

        $lockData['packages-dev'] = $lockData['packages-dev'] ?? [];

        foreach (array_merge($lockData['packages'], $lockData['packages-dev']) as $package) {
            yield $package['name'] => $package['version'] . '@' . (
                $package['source']['reference']?? $package['dist']['reference'] ?? ''
            );
        }

        yield $rootPackage->getName() => $rootPackage->getPrettyVersion() . '@' . $rootPackage->getSourceReference();
    }
}
<?php

namespace PHPStanVendor\PackageVersions;

/**
 * This class is generated by ocramius/package-versions, specifically by
 * @see \PackageVersions\Installer
 *
 * This file is overwritten at every run of `composer install` or `composer update`.
 */
final class Versions
{
    const VERSIONS = array (
  'dg/composer-cleaner' => 'v1.1@417979b0169b2fc28fd05e48ceb20f87a3113d4e',
  'jean85/pretty-package-versions' => '1.1@d457344b6a035ef99236bdda4729ad7eeb233f54',
  'netresearch/composer-patches-plugin' => '1.2.1@3a3de792955eb7e6bad2b5e892b63a1f6d9be000',
  'nette/bootstrap' => 'v2.4.5@804925787764d708a7782ea0d9382a310bb21968',
  'nette/di' => 'v2.4.10@a4b3be935b755f23aebea1ce33d7e3c832cdff98',
  'nette/finder' => 'v2.4.1@4d43a66d072c57d585bf08a3ef68d3587f7e9547',
  'nette/neon' => 'v2.4.2@9eacd50553b26b53a3977bfb2fea2166d4331622',
  'nette/php-generator' => 'v3.0.1@eb2dbc9c3409e9db40568109ca4994d51373b60c',
  'nette/robot-loader' => 'v3.0.2@b703b4f5955831b0bcaacbd2f6af76021b056826',
  'nette/utils' => 'v2.4.8@f1584033b5af945b470533b466b81a789d532034',
  'nikic/php-parser' => 'v3.1.4@e57b3a09784f846411aa7ed664eedb73e3399078',
  'ocramius/package-versions' => '1.2.0@ad8a245decad4897cc6b432743913dad0d69753c',
  'phpstan/package-patches' => '1.0.0@',
  'phpstan/phpdoc-parser' => '0.2@02f909f134fe06f0cd4790d8627ee24efbe84d6a',
  'psr/log' => '1.0.2@4ebe3a8bf773a19edfe0a84b6585ba3d401b724d',
  'symfony/console' => 'v3.4.3@8394c8ef121949e8f858f13bc1e34f05169e4e7d',
  'symfony/debug' => 'v4.0.3@9ae4223a661b56a9abdce144de4886cca37f198f',
  'symfony/finder' => 'v3.4.3@613e26310776f49a1773b6737c6bd554b8bc8c6f',
  'symfony/polyfill-mbstring' => 'v1.6.0@2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296',
  'phpstan/phpstan' => '0.9.2.0@e59541bcc7cac9b35ca54db6365bf377baf4a488',
);

    private function __construct()
    {
    }

    /**
     * @throws \OutOfBoundsException if a version cannot be located
     */
    public static function getVersion(string $packageName) : string
    {
        if (! isset(self::VERSIONS[$packageName])) {
            throw new \OutOfBoundsException(
                'Required package "' . $packageName . '" is not installed: cannot detect its version'
            );
        }

        return self::VERSIONS[$packageName];
    }
}
{
	"name": "phpstan/phpdoc-parser",
	"description": "PHPDoc parser with support for nullable, intersection and generic types",
	"license": "MIT",
	"minimum-stability": "dev",
	"prefer-stable": true,
	"require": {
		"php": "~7.0"
	},
	"require-dev": {
		"consistence/coding-standard": "^2.0.0",
		"jakub-onderka/php-parallel-lint": "^0.9.2",
		"phing/phing": "^2.16.0",
		"phpstan/phpstan": "^0.9",
		"phpunit/phpunit": "^6.3",
		"slevomat/coding-standard": "^3.3.0"
	},
	"autoload": {
		"psr-4": {"PHPStan\\PhpDocParser\\": ["src/"]}
	},
	"autoload-dev": {
		"psr-4": {"PHPStan\\PhpDocParser\\": ["tests/PHPStan"]}
	},
	"extra": {
		"branch-alias": {
			"dev-master": "0.1-dev"
		}
	}
}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\ConstExpr;

class ConstExprArrayItemNode implements ConstExprNode
{

	/** @var null|ConstExprNode */
	public $key;

	/** @var ConstExprNode */
	public $value;

	public function __construct(ConstExprNode $key = null, ConstExprNode $value)
	{
		$this->key = $key;
		$this->value = $value;
	}


	public function __toString(): string
	{
		if ($this->key !== null) {
			return "{$this->key} => {$this->value}";

		} else {
			return "{$this->value}";
		}
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\ConstExpr;

class ConstExprArrayNode implements ConstExprNode
{

	/** @var ConstExprArrayItemNode[] */
	public $items;

	/**
	 * @param ConstExprArrayItemNode[] $items
	 */
	public function __construct(array $items)
	{
		$this->items = $items;
	}


	public function __toString(): string
	{
		return '[' . implode(', ', $this->items) . ']';
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\ConstExpr;

class ConstExprFalseNode implements ConstExprNode
{

	public function __toString(): string
	{
		return 'false';
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\ConstExpr;

class ConstExprFloatNode implements ConstExprNode
{

	/** @var string */
	public $value;

	public function __construct(string $value)
	{
		$this->value = $value;
	}


	public function __toString(): string
	{
		return $this->value;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\ConstExpr;

class ConstExprIntegerNode implements ConstExprNode
{

	/** @var string */
	public $value;

	public function __construct(string $value)
	{
		$this->value = $value;
	}


	public function __toString(): string
	{
		return $this->value;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\ConstExpr;

use PHPStan\PhpDocParser\Ast\Node;

interface ConstExprNode extends Node
{

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\ConstExpr;

class ConstExprNullNode implements ConstExprNode
{

	public function __toString(): string
	{
		return 'null';
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\ConstExpr;

class ConstExprStringNode implements ConstExprNode
{

	/** @var string */
	public $value;

	public function __construct(string $value)
	{
		$this->value = $value;
	}


	public function __toString(): string
	{
		return $this->value;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\ConstExpr;

class ConstExprTrueNode implements ConstExprNode
{

	public function __toString(): string
	{
		return 'true';
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\ConstExpr;

class ConstFetchNode implements ConstExprNode
{

	/** @var string class name for class constants or empty string for non-class constants */
	public $className;

	/** @var string */
	public $name;

	public function __construct(string $className, string $name)
	{
		$this->className = $className;
		$this->name = $name;
	}


	public function __toString(): string
	{
		if ($this->className === '') {
			return $this->name;

		} else {
			return "{$this->className}::{$this->name}";
		}
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast;

interface Node
{

	public function __toString(): string;

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\PhpDoc;

class GenericTagValueNode implements PhpDocTagValueNode
{

	/** @var string (may be empty) */
	public $value;

	public function __construct(string $value)
	{
		$this->value = $value;
	}


	public function __toString(): string
	{
		return $this->value;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\PhpDoc;

class InvalidTagValueNode implements PhpDocTagValueNode
{

	/** @var string (may be empty) */
	public $value;

	/** @var \PHPStan\PhpDocParser\Parser\ParserException */
	public $exception;

	public function __construct(string $value, \PHPStan\PhpDocParser\Parser\ParserException $exception)
	{
		$this->value = $value;
		$this->exception = $exception;
	}


	public function __toString(): string
	{
		return $this->value;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\PhpDoc;

use PHPStan\PhpDocParser\Ast\Type\TypeNode;

class MethodTagValueNode implements PhpDocTagValueNode
{

	/** @var bool */
	public $isStatic;

	/** @var null|TypeNode */
	public $returnType;

	/** @var string */
	public $methodName;

	/** @var MethodTagValueParameterNode[] */
	public $parameters;

	/** @var string (may be empty) */
	public $description;

	public function __construct(bool $isStatic, TypeNode $returnType = null, string $methodName, array $parameters, string $description)
	{
		$this->isStatic = $isStatic;
		$this->returnType = $returnType;
		$this->methodName = $methodName;
		$this->parameters = $parameters;
		$this->description = $description;
	}


	public function __toString(): string
	{
		$static = $this->isStatic ? 'static ' : '';
		$returnType = $this->returnType ? "{$this->returnType} " : '';
		$parameters = implode(', ', $this->parameters);
		$description = $this->description !== '' ? " {$this->description}" : '';
		return "{$static}{$returnType}{$this->methodName}({$parameters}){$description}";
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\PhpDoc;

use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprNode;
use PHPStan\PhpDocParser\Ast\Node;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;

class MethodTagValueParameterNode implements Node
{

	/** @var null|TypeNode */
	public $type;

	/** @var bool */
	public $isReference;

	/** @var bool */
	public $isVariadic;

	/** @var string */
	public $parameterName;

	/** @var null|ConstExprNode */
	public $defaultValue;

	public function __construct(TypeNode $type = null, bool $isReference, bool $isVariadic, string $parameterName, ConstExprNode $defaultValue = null)
	{
		$this->type = $type;
		$this->isReference = $isReference;
		$this->isVariadic = $isVariadic;
		$this->parameterName = $parameterName;
		$this->defaultValue = $defaultValue;
	}


	public function __toString(): string
	{
		$type = $this->type ? "{$this->type} " : '';
		$isReference = $this->isReference ? '&' : '';
		$isVariadic = $this->isVariadic ? '...' : '';
		$default = $this->defaultValue ? " = {$this->defaultValue}" : '';
		return "{$type}{$isReference}{$isVariadic}{$this->parameterName}{$default}";
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\PhpDoc;

use PHPStan\PhpDocParser\Ast\Type\TypeNode;

class ParamTagValueNode implements PhpDocTagValueNode
{

	/** @var TypeNode */
	public $type;

	/** @var bool */
	public $isVariadic;

	/** @var string (may be empty) */
	public $parameterName;

	/** @var string (may be empty) */
	public $description;

	public function __construct(TypeNode $type, bool $isVariadic, string $parameterName, string $description)
	{
		$this->type = $type;
		$this->isVariadic = $isVariadic;
		$this->parameterName = $parameterName;
		$this->description = $description;
	}


	public function __toString(): string
	{
		$variadic = $this->isVariadic ? '...' : '';
		return trim("{$this->type} {$variadic}{$this->parameterName} {$this->description}");
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\PhpDoc;

use PHPStan\PhpDocParser\Ast\Node;

interface PhpDocChildNode extends Node
{

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\PhpDoc;

use PHPStan\PhpDocParser\Ast\Node;

class PhpDocNode implements Node
{

	/** @var PhpDocChildNode[] */
	public $children;

	/**
	 * @param PhpDocChildNode[] $children
	 */
	public function __construct(array $children)
	{
		$this->children = $children;
	}


	/**
	 * @return PhpDocTagNode[]
	 */
	public function getTags(): array
	{
		return array_filter($this->children, function (PhpDocChildNode $child): bool {
			return $child instanceof PhpDocTagNode;
		});
	}


	/**
	 * @param  string $tagName
	 * @return PhpDocTagNode[]
	 */
	public function getTagsByName(string $tagName): array
	{
		return array_filter($this->getTags(), function (PhpDocTagNode $tag) use ($tagName): bool {
			return $tag->name === $tagName;
		});
	}


	/**
	 * @return VarTagValueNode[]
	 */
	public function getVarTagValues(): array
	{
		return array_column(
			array_filter($this->getTagsByName('@var'), function (PhpDocTagNode $tag): bool {
				return $tag->value instanceof VarTagValueNode;
			}),
			'value'
		);
	}


	/**
	 * @return ParamTagValueNode[]
	 */
	public function getParamTagValues(): array
	{
		return array_column(
			array_filter($this->getTagsByName('@param'), function (PhpDocTagNode $tag): bool {
				return $tag->value instanceof ParamTagValueNode;
			}),
			'value'
		);
	}


	/**
	 * @return ReturnTagValueNode[]
	 */
	public function getReturnTagValues(): array
	{
		return array_column(
			array_filter($this->getTagsByName('@return'), function (PhpDocTagNode $tag): bool {
				return $tag->value instanceof ReturnTagValueNode;
			}),
			'value'
		);
	}


	/**
	 * @return PropertyTagValueNode[]
	 */
	public function getPropertyTagValues(): array
	{
		return array_column(
			array_filter($this->getTagsByName('@property'), function (PhpDocTagNode $tag): bool {
				return $tag->value instanceof PropertyTagValueNode;
			}),
			'value'
		);
	}


	/**
	 * @return PropertyTagValueNode[]
	 */
	public function getPropertyReadTagValues(): array
	{
		return array_column(
			array_filter($this->getTagsByName('@property-read'), function (PhpDocTagNode $tag): bool {
				return $tag->value instanceof PropertyTagValueNode;
			}),
			'value'
		);
	}


	/**
	 * @return PropertyTagValueNode[]
	 */
	public function getPropertyWriteTagValues(): array
	{
		return array_column(
			array_filter($this->getTagsByName('@property-write'), function (PhpDocTagNode $tag): bool {
				return $tag->value instanceof PropertyTagValueNode;
			}),
			'value'
		);
	}


	/**
	 * @return MethodTagValueNode[]
	 */
	public function getMethodTagValues(): array
	{
		return array_column(
			array_filter($this->getTagsByName('@method'), function (PhpDocTagNode $tag): bool {
				return $tag->value instanceof MethodTagValueNode;
			}),
			'value'
		);
	}


	public function __toString(): string
	{
		return "/**\n * " . implode("\n * ", $this->children) . '*/';
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\PhpDoc;

class PhpDocTagNode implements PhpDocChildNode
{

	/** @var string */
	public $name;

	/** @var PhpDocTagValueNode */
	public $value;

	public function __construct(string $name, PhpDocTagValueNode $value)
	{
		$this->name = $name;
		$this->value = $value;
	}


	public function __toString(): string
	{
		return trim("{$this->name} {$this->value}");
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\PhpDoc;

use PHPStan\PhpDocParser\Ast\Node;

interface PhpDocTagValueNode extends Node
{

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\PhpDoc;

class PhpDocTextNode implements PhpDocChildNode
{

	/** @var string */
	public $text;

	public function __construct(string $text)
	{
		$this->text = $text;
	}


	public function __toString(): string
	{
		return $this->text;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\PhpDoc;

use PHPStan\PhpDocParser\Ast\Type\TypeNode;

class PropertyTagValueNode implements PhpDocTagValueNode
{

	/** @var TypeNode */
	public $type;

	/** @var string */
	public $propertyName;

	/** @var string (may be empty) */
	public $description;

	public function __construct(TypeNode $type, string $propertyName, string $description)
	{
		$this->type = $type;
		$this->propertyName = $propertyName;
		$this->description = $description;
	}


	public function __toString(): string
	{
		return trim("{$this->type} {$this->propertyName} {$this->description}");
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\PhpDoc;

use PHPStan\PhpDocParser\Ast\Type\TypeNode;

class ReturnTagValueNode implements PhpDocTagValueNode
{

	/** @var TypeNode */
	public $type;

	/** @var string (may be empty) */
	public $description;

	public function __construct(TypeNode $type, string $description)
	{
		$this->type = $type;
		$this->description = $description;
	}


	public function __toString(): string
	{
		return trim("{$this->type} {$this->description}");
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\PhpDoc;

use PHPStan\PhpDocParser\Ast\Type\TypeNode;

class ThrowsTagValueNode implements PhpDocTagValueNode
{

	/** @var TypeNode */
	public $type;

	/** @var string (may be empty) */
	public $description;

	public function __construct(TypeNode $type, string $description)
	{
		$this->type = $type;
		$this->description = $description;
	}


	public function __toString(): string
	{
		return trim("{$this->type} {$this->description}");
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\PhpDoc;

use PHPStan\PhpDocParser\Ast\Type\TypeNode;

class VarTagValueNode implements PhpDocTagValueNode
{

	/** @var TypeNode */
	public $type;

	/** @var string (may be empty) */
	public $variableName;

	/** @var string (may be empty) */
	public $description;

	public function __construct(TypeNode $type, string $variableName, string $description)
	{
		$this->type = $type;
		$this->variableName = $variableName;
		$this->description = $description;
	}


	public function __toString(): string
	{
		return trim("$this->type " . trim("{$this->variableName} {$this->description}"));
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\Type;

class ArrayTypeNode implements TypeNode
{

	/** @var TypeNode */
	public $type;

	public function __construct(TypeNode $type)
	{
		$this->type = $type;
	}


	public function __toString(): string
	{
		return $this->type . '[]';
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\Type;

class GenericTypeNode implements TypeNode
{

	/** @var IdentifierTypeNode */
	public $type;

	/** @var TypeNode[] */
	public $genericTypes;

	public function __construct(IdentifierTypeNode $type, array $genericTypes)
	{
		$this->type = $type;
		$this->genericTypes = $genericTypes;
	}


	public function __toString(): string
	{
		return $this->type . '<' . implode(', ', $this->genericTypes) . '>';
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\Type;

class IdentifierTypeNode implements TypeNode
{

	/** @var string */
	public $name;

	public function __construct(string $name)
	{
		$this->name = $name;
	}


	public function __toString(): string
	{
		return $this->name;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\Type;

class IntersectionTypeNode implements TypeNode
{

	/** @var TypeNode[] */
	public $types;

	public function __construct(array $types)
	{
		$this->types = $types;
	}


	public function __toString(): string
	{
		return '(' . implode(' & ', $this->types) . ')';
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\Type;

class NullableTypeNode implements TypeNode
{

	/** @var TypeNode */
	public $type;

	public function __construct(TypeNode $type)
	{
		$this->type = $type;
	}


	public function __toString(): string
	{
		return '?' . $this->type;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\Type;

class ThisTypeNode implements TypeNode
{

	public function __toString(): string
	{
		return '$this';
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\Type;

use PHPStan\PhpDocParser\Ast\Node;

interface TypeNode extends Node
{

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\Type;

class UnionTypeNode implements TypeNode
{

	/** @var TypeNode[] */
	public $types;

	public function __construct(array $types)
	{
		$this->types = $types;
	}


	public function __toString(): string
	{
		return '(' . implode(' | ', $this->types) . ')';
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Lexer;

/**
 * Implementation based on Nette Tokenizer (New BSD License; https://github.com/nette/tokenizer)
 */
class Lexer
{

	const TOKEN_REFERENCE = 0;
	const TOKEN_UNION = 1;
	const TOKEN_INTERSECTION = 2;
	const TOKEN_NULLABLE = 3;
	const TOKEN_OPEN_PARENTHESES = 4;
	const TOKEN_CLOSE_PARENTHESES = 5;
	const TOKEN_OPEN_ANGLE_BRACKET = 6;
	const TOKEN_CLOSE_ANGLE_BRACKET = 7;
	const TOKEN_OPEN_SQUARE_BRACKET = 8;
	const TOKEN_CLOSE_SQUARE_BRACKET = 9;
	const TOKEN_COMMA = 10;
	const TOKEN_VARIADIC = 11;
	const TOKEN_DOUBLE_COLON = 12;
	const TOKEN_DOUBLE_ARROW = 13;
	const TOKEN_EQUAL = 14;
	const TOKEN_OPEN_PHPDOC = 15;
	const TOKEN_CLOSE_PHPDOC = 16;
	const TOKEN_PHPDOC_TAG = 17;
	const TOKEN_PHPDOC_EOL = 26;
	const TOKEN_FLOAT = 18;
	const TOKEN_INTEGER = 19;
	const TOKEN_SINGLE_QUOTED_STRING = 20;
	const TOKEN_DOUBLE_QUOTED_STRING = 21;
	const TOKEN_IDENTIFIER = 22;
	const TOKEN_THIS_VARIABLE = 23;
	const TOKEN_VARIABLE = 24;
	const TOKEN_HORIZONTAL_WS = 25;
	const TOKEN_OTHER = 27;
	const TOKEN_END = 28;

	const TOKEN_LABELS = [
		self::TOKEN_REFERENCE => '\'&\'',
		self::TOKEN_UNION => '\'|\'',
		self::TOKEN_INTERSECTION => '\'&\'',
		self::TOKEN_NULLABLE => '\'?\'',
		self::TOKEN_OPEN_PARENTHESES => '\'(\'',
		self::TOKEN_CLOSE_PARENTHESES => '\')\'',
		self::TOKEN_OPEN_ANGLE_BRACKET => '\'<\'',
		self::TOKEN_CLOSE_ANGLE_BRACKET => '\'>\'',
		self::TOKEN_OPEN_SQUARE_BRACKET => '\'[\'',
		self::TOKEN_CLOSE_SQUARE_BRACKET => '\']\'',
		self::TOKEN_COMMA => '\',\'',
		self::TOKEN_VARIADIC => '\'...\'',
		self::TOKEN_DOUBLE_COLON => '\'::\'',
		self::TOKEN_DOUBLE_ARROW => '\'=>\'',
		self::TOKEN_EQUAL => '\'=\'',
		self::TOKEN_OPEN_PHPDOC => '\'/**\'',
		self::TOKEN_CLOSE_PHPDOC => '\'*/\'',
		self::TOKEN_PHPDOC_TAG => 'TOKEN_PHPDOC_TAG',
		self::TOKEN_FLOAT => 'TOKEN_FLOAT',
		self::TOKEN_INTEGER => 'TOKEN_INTEGER',
		self::TOKEN_SINGLE_QUOTED_STRING => 'TOKEN_SINGLE_QUOTED_STRING',
		self::TOKEN_DOUBLE_QUOTED_STRING => 'TOKEN_DOUBLE_QUOTED_STRING',
		self::TOKEN_IDENTIFIER => 'TOKEN_IDENTIFIER',
		self::TOKEN_THIS_VARIABLE => '\'$this\'',
		self::TOKEN_VARIABLE => 'TOKEN_VARIABLE',
		self::TOKEN_HORIZONTAL_WS => 'TOKEN_HORIZONTAL_WS',
		self::TOKEN_OTHER => 'TOKEN_OTHER',
		self::TOKEN_END => 'TOKEN_END',
	];

	const VALUE_OFFSET = 0;
	const TYPE_OFFSET = 1;

	/** @var null|string */
	private $regexp;

	/** @var null|int[] */
	private $types;

	public function tokenize(string $s): array
	{
		if ($this->regexp === null) {
			$this->initialize();
		}

		preg_match_all($this->regexp, $s, $tokens, PREG_SET_ORDER);

		assert($this->types !== null);
		$count = count($this->types);

		foreach ($tokens as &$match) {
			for ($i = 1; $i <= $count; $i++) {
				if ($match[$i] !== null && $match[$i] !== '') {
					$match = [$match[0], $this->types[$i - 1]];
					break;
				}
			}
		}

		$tokens[] = ['', self::TOKEN_END];

		return $tokens;
	}


	private function initialize()
	{
		$patterns = [
			// '&' followed by TOKEN_VARIADIC or TOKEN_VARIABLE
			self::TOKEN_REFERENCE => '&(?=\\s*+(?:(?:\\.\\.\\.)|(?:\\$(?!this\\b))))',
			self::TOKEN_UNION => '\\|',
			self::TOKEN_INTERSECTION => '&',
			self::TOKEN_NULLABLE => '\\?',

			self::TOKEN_OPEN_PARENTHESES => '\\(',
			self::TOKEN_CLOSE_PARENTHESES => '\\)',
			self::TOKEN_OPEN_ANGLE_BRACKET => '<',
			self::TOKEN_CLOSE_ANGLE_BRACKET => '>',
			self::TOKEN_OPEN_SQUARE_BRACKET => '\\[',
			self::TOKEN_CLOSE_SQUARE_BRACKET => '\\]',

			self::TOKEN_COMMA => ',',
			self::TOKEN_VARIADIC => '\\.\\.\\.',
			self::TOKEN_DOUBLE_COLON => '::',
			self::TOKEN_DOUBLE_ARROW => '=>',
			self::TOKEN_EQUAL => '=',

			self::TOKEN_OPEN_PHPDOC => '/\\*\\*(?=\\s)',
			self::TOKEN_CLOSE_PHPDOC => '\\*/',
			self::TOKEN_PHPDOC_TAG => '@[a-z-]++',
			self::TOKEN_PHPDOC_EOL => '\\r?+\\n[\\x09\\x20]*+(?:\\*(?!/))?',

			self::TOKEN_FLOAT => '(?:-?[0-9]++\\.[0-9]*+(?:e-?[0-9]++)?)|(?:-?[0-9]*+\\.[0-9]++(?:e-?[0-9]++)?)|(?:-?[0-9]++e-?[0-9]++)',
			self::TOKEN_INTEGER => '-?[0-9]++',
			self::TOKEN_SINGLE_QUOTED_STRING => '\'(?:\\\\.|[^\'\\r\\n])*+\'',
			self::TOKEN_DOUBLE_QUOTED_STRING => '"(?:\\\\.|[^"\\r\\n])*+"',

			self::TOKEN_IDENTIFIER => '(?:[\\\\]?+[a-z_\\x7F-\\xFF][0-9a-z_\\x7F-\\xFF]*+)++',
			self::TOKEN_THIS_VARIABLE => '\\$this\\b',
			self::TOKEN_VARIABLE => '\\$[a-z_\\x7F-\\xFF][0-9a-z_\\x7F-\\xFF]*+',

			self::TOKEN_HORIZONTAL_WS => '[\\x09\\x20]++',

			// anything but TOKEN_CLOSE_PHPDOC or TOKEN_HORIZONTAL_WS or TOKEN_EOL
			self::TOKEN_OTHER => '(?:(?!\\*/)[^\\s])++',
		];

		$this->regexp = '~(' . implode(')|(', $patterns) . ')~Asi';
		$this->types = array_keys($patterns);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Parser;

use PHPStan\PhpDocParser\Ast;
use PHPStan\PhpDocParser\Lexer\Lexer;

class ConstExprParser
{

	public function parse(TokenIterator $tokens): Ast\ConstExpr\ConstExprNode
	{
		if ($tokens->isCurrentTokenType(Lexer::TOKEN_FLOAT)) {
			$value = $tokens->currentTokenValue();
			$tokens->next();
			return new Ast\ConstExpr\ConstExprFloatNode($value);

		} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_INTEGER)) {
			$value = $tokens->currentTokenValue();
			$tokens->next();
			return new Ast\ConstExpr\ConstExprIntegerNode($value);

		} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) {
			$value = $tokens->currentTokenValue();
			$tokens->next();
			return new Ast\ConstExpr\ConstExprStringNode($value);

		} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) {
			$value = $tokens->currentTokenValue();
			$tokens->next();
			return new Ast\ConstExpr\ConstExprStringNode($value);

		} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) {
			$identifier = $tokens->currentTokenValue();
			$tokens->next();

			switch (strtolower($identifier)) {
				case 'true':
					return new Ast\ConstExpr\ConstExprTrueNode();
				case 'false':
					return new Ast\ConstExpr\ConstExprFalseNode();
				case 'null':
					return new Ast\ConstExpr\ConstExprNullNode();
				case 'array':
					$tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES);
					return $this->parseArray($tokens, Lexer::TOKEN_CLOSE_PARENTHESES);
			}

			if ($tokens->tryConsumeTokenType(Lexer::TOKEN_DOUBLE_COLON)) {
				$classConstantName = $tokens->currentTokenValue();
				$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
				return new Ast\ConstExpr\ConstFetchNode($identifier, $classConstantName);

			} else {
				return new Ast\ConstExpr\ConstFetchNode('', $identifier);
			}

		} elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
			return $this->parseArray($tokens, Lexer::TOKEN_CLOSE_SQUARE_BRACKET);
		}

		throw new \LogicException($tokens->currentTokenValue());
	}


	private function parseArray(TokenIterator $tokens, int $endToken): Ast\ConstExpr\ConstExprArrayNode
	{
		$items = [];

		if (!$tokens->tryConsumeTokenType($endToken)) {
			do {
				$items[] = $this->parseArrayItem($tokens);
			} while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA) && !$tokens->isCurrentTokenType($endToken));
			$tokens->consumeTokenType($endToken);
		}

		return new Ast\ConstExpr\ConstExprArrayNode($items);
	}


	private function parseArrayItem(TokenIterator $tokens): Ast\ConstExpr\ConstExprArrayItemNode
	{
		$expr = $this->parse($tokens);

		if ($tokens->tryConsumeTokenType(Lexer::TOKEN_DOUBLE_ARROW)) {
			$key = $expr;
			$value = $this->parse($tokens);

		} else {
			$key = null;
			$value = $expr;
		}

		return new Ast\ConstExpr\ConstExprArrayItemNode($key, $value);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Parser;

use PHPStan\PhpDocParser\Lexer\Lexer;

class ParserException extends \Exception
{

	/** @var string */
	private $currentTokenValue;

	/** @var int */
	private $currentTokenType;

	/** @var int */
	private $currentOffset;

	/** @var int */
	private $expectedTokenType;

	public function __construct(
		string $currentTokenValue,
		int $currentTokenType,
		int $currentOffset,
		int $expectedTokenType
	)
	{
		$this->currentTokenValue = $currentTokenValue;
		$this->currentTokenType = $currentTokenType;
		$this->currentOffset = $currentOffset;
		$this->expectedTokenType = $expectedTokenType;

		parent::__construct(sprintf(
			'Unexpected token %s, expected %s at offset %d',
			json_encode($currentTokenValue, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
			Lexer::TOKEN_LABELS[$expectedTokenType],
			$currentOffset
		));
	}


	public function getCurrentTokenValue(): string
	{
		return $this->currentTokenValue;
	}


	public function getCurrentTokenType(): int
	{
		return $this->currentTokenType;
	}


	public function getCurrentOffset(): int
	{
		return $this->currentOffset;
	}


	public function getExpectedTokenType(): int
	{
		return $this->expectedTokenType;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Parser;

use PHPStan\PhpDocParser\Ast;
use PHPStan\PhpDocParser\Lexer\Lexer;

class PhpDocParser
{

	const DISALLOWED_DESCRIPTION_START_TOKENS = [
		Lexer::TOKEN_UNION,
		Lexer::TOKEN_INTERSECTION,
		Lexer::TOKEN_OPEN_ANGLE_BRACKET,
	];

	/** @var TypeParser */
	private $typeParser;

	/** @var ConstExprParser */
	private $constantExprParser;

	public function __construct(TypeParser $typeParser, ConstExprParser $constantExprParser)
	{
		$this->typeParser = $typeParser;
		$this->constantExprParser = $constantExprParser;
	}


	public function parse(TokenIterator $tokens): Ast\PhpDoc\PhpDocNode
	{
		$tokens->consumeTokenType(Lexer::TOKEN_OPEN_PHPDOC);
		$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);

		$children = [];

		if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
			$children[] = $this->parseChild($tokens);
			while ($tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL) && !$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
				$children[] = $this->parseChild($tokens);
			}
		}

		$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PHPDOC);

		return new Ast\PhpDoc\PhpDocNode(array_values($children));
	}


	private function parseChild(TokenIterator $tokens): Ast\PhpDoc\PhpDocChildNode
	{
		if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG)) {
			return $this->parseTag($tokens);

		} else {
			return $this->parseText($tokens);
		}
	}


	private function parseText(TokenIterator $tokens): Ast\PhpDoc\PhpDocTextNode
	{
		$text = $tokens->joinUntil(Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END);
		$text = rtrim($text, " \t"); // the trimmed characters MUST match Lexer::TOKEN_HORIZONTAL_WS

		return new Ast\PhpDoc\PhpDocTextNode($text);
	}


	public function parseTag(TokenIterator $tokens): Ast\PhpDoc\PhpDocTagNode
	{
		$tag = $tokens->currentTokenValue();
		$tokens->next();
		$value = $this->parseTagValue($tokens, $tag);

		return new Ast\PhpDoc\PhpDocTagNode($tag, $value);
	}


	private function parseTagValue(TokenIterator $tokens, string $tag): Ast\PhpDoc\PhpDocTagValueNode
	{
		try {
			$tokens->pushSavePoint();

			switch ($tag) {
				case '@param':
					$tagValue = $this->parseParamTagValue($tokens);
					break;

				case '@var':
					$tagValue = $this->parseVarTagValue($tokens);
					break;

				case '@return':
					$tagValue = $this->parseReturnTagValue($tokens);
					break;

				case '@throws':
					$tagValue = $this->parseThrowsTagValue($tokens);
					break;

				case '@property':
				case '@property-read':
				case '@property-write':
					$tagValue = $this->parsePropertyTagValue($tokens);
					break;

				case '@method':
					$tagValue = $this->parseMethodTagValue($tokens);
					break;

				default:
					$tagValue = new Ast\PhpDoc\GenericTagValueNode($this->parseOptionalDescription($tokens));
					break;
			}

			$tokens->dropSavePoint();

		} catch (\PHPStan\PhpDocParser\Parser\ParserException $e) {
			$tokens->rollback();
			$tagValue = new Ast\PhpDoc\InvalidTagValueNode($this->parseOptionalDescription($tokens), $e);
		}

		return $tagValue;
	}


	private function parseParamTagValue(TokenIterator $tokens): Ast\PhpDoc\ParamTagValueNode
	{
		$type = $this->typeParser->parse($tokens);
		$isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC);
		$parameterName = $this->parseRequiredVariableName($tokens);
		$description = $this->parseOptionalDescription($tokens);
		return new Ast\PhpDoc\ParamTagValueNode($type, $isVariadic, $parameterName, $description);
	}


	private function parseVarTagValue(TokenIterator $tokens): Ast\PhpDoc\VarTagValueNode
	{
		$type = $this->typeParser->parse($tokens);
		$variableName = $this->parseOptionalVariableName($tokens);
		$description = $this->parseOptionalDescription($tokens, $variableName === '');
		return new Ast\PhpDoc\VarTagValueNode($type, $variableName, $description);
	}


	private function parseReturnTagValue(TokenIterator $tokens): Ast\PhpDoc\ReturnTagValueNode
	{
		$type = $this->typeParser->parse($tokens);
		$description = $this->parseOptionalDescription($tokens, true);
		return new Ast\PhpDoc\ReturnTagValueNode($type, $description);
	}


	private function parseThrowsTagValue(TokenIterator $tokens): Ast\PhpDoc\ThrowsTagValueNode
	{
		$type = $this->typeParser->parse($tokens);
		$description = $this->parseOptionalDescription($tokens, true);
		return new Ast\PhpDoc\ThrowsTagValueNode($type, $description);
	}


	private function parsePropertyTagValue(TokenIterator $tokens): Ast\PhpDoc\PropertyTagValueNode
	{
		$type = $this->typeParser->parse($tokens);
		$parameterName = $this->parseRequiredVariableName($tokens);
		$description = $this->parseOptionalDescription($tokens);
		return new Ast\PhpDoc\PropertyTagValueNode($type, $parameterName, $description);
	}


	private function parseMethodTagValue(TokenIterator $tokens): Ast\PhpDoc\MethodTagValueNode
	{
		$isStatic = $tokens->tryConsumeTokenValue('static');
		$returnTypeOrMethodName = $this->typeParser->parse($tokens);

		if ($tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) {
			$returnType = $returnTypeOrMethodName;
			$methodName = $tokens->currentTokenValue();
			$tokens->next();

		} elseif ($returnTypeOrMethodName instanceof Ast\Type\IdentifierTypeNode) {
			$returnType = $isStatic ? new Ast\Type\IdentifierTypeNode('static') : null;
			$methodName = $returnTypeOrMethodName->name;
			$isStatic = false;

		} else {
			$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); // will throw exception
			exit;
		}

		$parameters = [];
		$tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES);
		if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) {
			$parameters[] = $this->parseMethodTagValueParameter($tokens);
			while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) {
				$parameters[] = $this->parseMethodTagValueParameter($tokens);
			}
		}
		$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);

		$description = $this->parseOptionalDescription($tokens);
		return new Ast\PhpDoc\MethodTagValueNode($isStatic, $returnType, $methodName, $parameters, $description);
	}


	private function parseMethodTagValueParameter(TokenIterator $tokens): Ast\PhpDoc\MethodTagValueParameterNode
	{
		switch ($tokens->currentTokenType()) {
			case Lexer::TOKEN_IDENTIFIER:
			case Lexer::TOKEN_OPEN_PARENTHESES:
			case Lexer::TOKEN_NULLABLE:
				$parameterType = $this->typeParser->parse($tokens);
				break;

			default:
				$parameterType = null;
		}

		$isReference = $tokens->tryConsumeTokenType(Lexer::TOKEN_REFERENCE);
		$isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC);

		$parameterName = $tokens->currentTokenValue();
		$tokens->consumeTokenType(Lexer::TOKEN_VARIABLE);

		if ($tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL)) {
			$defaultValue = $this->constantExprParser->parse($tokens);

		} else {
			$defaultValue = null;
		}

		return new Ast\PhpDoc\MethodTagValueParameterNode($parameterType, $isReference, $isVariadic, $parameterName, $defaultValue);
	}


	private function parseOptionalVariableName(TokenIterator $tokens): string
	{
		if ($tokens->isCurrentTokenType(Lexer::TOKEN_VARIABLE)) {
			$parameterName = $tokens->currentTokenValue();
			$tokens->next();

		} else {
			$parameterName = '';
		}

		return $parameterName;
	}


	private function parseRequiredVariableName(TokenIterator $tokens): string
	{
		$parameterName = $tokens->currentTokenValue();
		$tokens->consumeTokenType(Lexer::TOKEN_VARIABLE);

		return $parameterName;
	}


	private function parseOptionalDescription(TokenIterator $tokens, bool $limitStartToken = false): string
	{
		if ($limitStartToken) {
			foreach (self::DISALLOWED_DESCRIPTION_START_TOKENS as $disallowedStartToken) {
				if ($tokens->isCurrentTokenType($disallowedStartToken)) {
					$tokens->consumeTokenType(Lexer::TOKEN_OTHER); // will throw exception
				}
			}
		}

		return $this->parseText($tokens)->text;
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Parser;

use PHPStan\PhpDocParser\Lexer\Lexer;

class TokenIterator
{

	/** @var mixed[][] */
	private $tokens;

	/** @var int */
	private $index;

	/** @var int[] */
	private $savePoints = [];

	public function __construct(array $tokens, int $index = 0)
	{
		$this->tokens = $tokens;
		$this->index = $index;

		if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
			$this->index++;
		}
	}


	public function currentTokenValue(): string
	{
		return $this->tokens[$this->index][Lexer::VALUE_OFFSET];
	}


	public function currentTokenType(): int
	{
		return $this->tokens[$this->index][Lexer::TYPE_OFFSET];
	}


	public function currentTokenOffset(): int
	{
		$offset = 0;
		for ($i = 0; $i < $this->index; $i++) {
			$offset += strlen($this->tokens[$i][Lexer::VALUE_OFFSET]);
		}

		return $offset;
	}


	public function isCurrentTokenValue(string $tokenValue): bool
	{
		return $this->tokens[$this->index][Lexer::VALUE_OFFSET] === $tokenValue;
	}


	public function isCurrentTokenType(int $tokenType): bool
	{
		return $this->tokens[$this->index][Lexer::TYPE_OFFSET] === $tokenType;
	}


	/**
	 * @param  int $tokenType
	 * @throws \PHPStan\PhpDocParser\Parser\ParserException
	 */
	public function consumeTokenType(int $tokenType)
	{
		if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== $tokenType) {
			$this->throwError($tokenType);
		}

		$this->index++;

		if (($this->tokens[$this->index][Lexer::TYPE_OFFSET] ?? -1) === Lexer::TOKEN_HORIZONTAL_WS) {
			$this->index++;
		}
	}


	public function tryConsumeTokenValue(string $tokenValue): bool
	{
		if ($this->tokens[$this->index][Lexer::VALUE_OFFSET] !== $tokenValue) {
			return false;
		}

		$this->index++;

		if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
			$this->index++;
		}

		return true;
	}


	public function tryConsumeTokenType(int $tokenType): bool
	{
		if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== $tokenType) {
			return false;
		}

		$this->index++;

		if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
			$this->index++;
		}

		return true;
	}


	public function getSkippedHorizontalWhiteSpaceIfAny(): string
	{
		if ($this->tokens[$this->index - 1][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
			return $this->tokens[$this->index - 1][Lexer::VALUE_OFFSET];
		}

		return '';
	}


	public function joinUntil(int ...$tokenType): string
	{
		$s = '';
		while (!in_array($this->tokens[$this->index][Lexer::TYPE_OFFSET], $tokenType, true)) {
			$s .= $this->tokens[$this->index++][Lexer::VALUE_OFFSET];
		}
		return $s;
	}


	public function next()
	{
		$this->index++;

		if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
			$this->index++;
		}
	}


	public function pushSavePoint()
	{
		$this->savePoints[] = $this->index;
	}


	public function dropSavePoint()
	{
		array_pop($this->savePoints);
	}


	public function rollback()
	{
		$this->index = array_pop($this->savePoints);
	}


	/**
	 * @param  int $expectedTokenType
	 * @throws \PHPStan\PhpDocParser\Parser\ParserException
	 */
	private function throwError(int $expectedTokenType)
	{
		throw new \PHPStan\PhpDocParser\Parser\ParserException(
			$this->currentTokenValue(),
			$this->currentTokenType(),
			$this->currentTokenOffset(),
			$expectedTokenType
		);
	}

}
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Parser;

use PHPStan\PhpDocParser\Ast;
use PHPStan\PhpDocParser\Lexer\Lexer;

class TypeParser
{

	public function parse(TokenIterator $tokens): Ast\Type\TypeNode
	{
		if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) {
			$type = $this->parseNullable($tokens);

		} else {
			$type = $this->parseAtomic($tokens);

			if ($tokens->isCurrentTokenType(Lexer::TOKEN_UNION)) {
				$type = $this->parseUnion($tokens, $type);

			} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_INTERSECTION)) {
				$type = $this->parseIntersection($tokens, $type);
			}
		}

		return $type;
	}


	private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode
	{
		if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
			$type = $this->parse($tokens);
			$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);

			if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
				$type = $this->tryParseArray($tokens, $type);
			}

		} elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_THIS_VARIABLE)) {
			return new Ast\Type\ThisTypeNode();

		} else {
			$type = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue());
			$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);

			if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) {
				$type = $this->parseGeneric($tokens, $type);

			} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
				$type = $this->tryParseArray($tokens, $type);
			}
		}

		return $type;
	}


	private function parseUnion(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode
	{
		$types = [$type];

		while ($tokens->tryConsumeTokenType(Lexer::TOKEN_UNION)) {
			$types[] = $this->parseAtomic($tokens);
		}

		return new Ast\Type\UnionTypeNode($types);
	}


	private function parseIntersection(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode
	{
		$types = [$type];

		while ($tokens->tryConsumeTokenType(Lexer::TOKEN_INTERSECTION)) {
			$types[] = $this->parseAtomic($tokens);
		}

		return new Ast\Type\IntersectionTypeNode($types);
	}


	private function parseNullable(TokenIterator $tokens): Ast\Type\TypeNode
	{
		$tokens->consumeTokenType(Lexer::TOKEN_NULLABLE);

		$type = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue());
		$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);

		if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) {
			$type = $this->parseGeneric($tokens, $type);
		}

		return new Ast\Type\NullableTypeNode($type);
	}


	private function parseGeneric(TokenIterator $tokens, Ast\Type\IdentifierTypeNode $baseType): Ast\Type\TypeNode
	{
		$tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET);
		$genericTypes[] = $this->parse($tokens);

		while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) {
			$genericTypes[] = $this->parse($tokens);
		}

		$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET);
		return new Ast\Type\GenericTypeNode($baseType, $genericTypes);
	}


	private function tryParseArray(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode
	{
		try {
			while ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
				$tokens->pushSavePoint();
				$tokens->consumeTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET);
				$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_SQUARE_BRACKET);
				$tokens->dropSavePoint();
				$type = new Ast\Type\ArrayTypeNode($type);
			}

		} catch (\PHPStan\PhpDocParser\Parser\ParserException $e) {
			$tokens->rollback();
		}

		return $type;
	}

}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console;

/**
 * An Application is the container for a collection of commands.
 *
 * It is the main entry point of a Console application.
 *
 * This class is optimized for a standard CLI environment.
 *
 * Usage:
 *
 *     $app = new Application('myapp', '1.0 (stable)');
 *     $app->add(new SimpleCommand());
 *     $app->run();
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Application
{
    private $commands = array();
    private $wantHelps = false;
    private $runningCommand;
    private $name;
    private $version;
    private $commandLoader;
    private $catchExceptions = true;
    private $autoExit = true;
    private $definition;
    private $helperSet;
    private $dispatcher;
    private $terminal;
    private $defaultCommand;
    private $singleCommand;
    private $initialized;

    /**
     * @param string $name    The name of the application
     * @param string $version The version of the application
     */
    public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
    {
        $this->name = $name;
        $this->version = $version;
        $this->terminal = new \PHPStanVendor\Symfony\Component\Console\Terminal();
        $this->defaultCommand = 'list';
    }

    public function setDispatcher(\PHPStanVendor\Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }

    public function setCommandLoader(\PHPStanVendor\Symfony\Component\Console\CommandLoader\CommandLoaderInterface $commandLoader)
    {
        $this->commandLoader = $commandLoader;
    }

    /**
     * Runs the current application.
     *
     * @return int 0 if everything went fine, or an error code
     *
     * @throws \Exception When running fails. Bypass this when {@link setCatchExceptions()}.
     */
    public function run(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input = null, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output = null)
    {
        putenv('LINES='.$this->terminal->getHeight());
        putenv('COLUMNS='.$this->terminal->getWidth());

        if (null === $input) {
            $input = new \PHPStanVendor\Symfony\Component\Console\Input\ArgvInput();
        }

        if (null === $output) {
            $output = new \PHPStanVendor\Symfony\Component\Console\Output\ConsoleOutput();
        }

        $renderException = function ($e) use ($output) {
            if (!$e instanceof \Exception) {
                $e = class_exists(\PHPStanVendor\Symfony\Component\Debug\Exception\FatalThrowableError::class) ? new \PHPStanVendor\Symfony\Component\Debug\Exception\FatalThrowableError($e) : new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine());
            }
            if ($output instanceof \PHPStanVendor\Symfony\Component\Console\Output\ConsoleOutputInterface) {
                $this->renderException($e, $output->getErrorOutput());
            } else {
                $this->renderException($e, $output);
            }
        };
        if ($phpHandler = set_exception_handler($renderException)) {
            restore_exception_handler();
            if (!is_array($phpHandler) || !$phpHandler[0] instanceof \PHPStanVendor\Symfony\Component\Debug\ErrorHandler) {
                $debugHandler = true;
            } elseif ($debugHandler = $phpHandler[0]->setExceptionHandler($renderException)) {
                $phpHandler[0]->setExceptionHandler($debugHandler);
            }
        }

        if (null !== $this->dispatcher && $this->dispatcher->hasListeners(\PHPStanVendor\Symfony\Component\Console\ConsoleEvents::EXCEPTION)) {
            @trigger_error(sprintf('The "ConsoleEvents::EXCEPTION" event is deprecated since Symfony 3.3 and will be removed in 4.0. Listen to the "ConsoleEvents::ERROR" event instead.'), E_USER_DEPRECATED);
        }

        $this->configureIO($input, $output);

        try {
            $exitCode = $this->doRun($input, $output);
        } catch (\Exception $e) {
            if (!$this->catchExceptions) {
                throw $e;
            }

            $renderException($e);

            $exitCode = $e->getCode();
            if (is_numeric($exitCode)) {
                $exitCode = (int) $exitCode;
                if (0 === $exitCode) {
                    $exitCode = 1;
                }
            } else {
                $exitCode = 1;
            }
        } finally {
            if (!$phpHandler) {
                restore_exception_handler();
            } elseif (!$debugHandler) {
                $phpHandler[0]->setExceptionHandler(null);
            }
        }

        if ($this->autoExit) {
            if ($exitCode > 255) {
                $exitCode = 255;
            }

            exit($exitCode);
        }

        return $exitCode;
    }

    /**
     * Runs the current application.
     *
     * @return int 0 if everything went fine, or an error code
     */
    public function doRun(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output)
    {
        if (true === $input->hasParameterOption(array('--version', '-V'), true)) {
            $output->writeln($this->getLongVersion());

            return 0;
        }

        $name = $this->getCommandName($input);
        if (true === $input->hasParameterOption(array('--help', '-h'), true)) {
            if (!$name) {
                $name = 'help';
                $input = new \PHPStanVendor\Symfony\Component\Console\Input\ArrayInput(array('command_name' => $this->defaultCommand));
            } else {
                $this->wantHelps = true;
            }
        }

        if (!$name) {
            $name = $this->defaultCommand;
            $definition = $this->getDefinition();
            $definition->setArguments(array_merge(
                $definition->getArguments(),
                array(
                    'command' => new \PHPStanVendor\Symfony\Component\Console\Input\InputArgument('command', \PHPStanVendor\Symfony\Component\Console\Input\InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name),
                )
            ));
        }

        try {
            $e = $this->runningCommand = null;
            // the command name MUST be the first element of the input
            $command = $this->find($name);
        } catch (\Exception $e) {
        } catch (\Throwable $e) {
        }
        if (null !== $e) {
            if (null !== $this->dispatcher) {
                $event = new \PHPStanVendor\Symfony\Component\Console\Event\ConsoleErrorEvent($input, $output, $e);
                $this->dispatcher->dispatch(\PHPStanVendor\Symfony\Component\Console\ConsoleEvents::ERROR, $event);
                $e = $event->getError();

                if (0 === $event->getExitCode()) {
                    return 0;
                }
            }

            throw $e;
        }

        $this->runningCommand = $command;
        $exitCode = $this->doRunCommand($command, $input, $output);
        $this->runningCommand = null;

        return $exitCode;
    }

    public function setHelperSet(\PHPStanVendor\Symfony\Component\Console\Helper\HelperSet $helperSet)
    {
        $this->helperSet = $helperSet;
    }

    /**
     * Get the helper set associated with the command.
     *
     * @return HelperSet The HelperSet instance associated with this command
     */
    public function getHelperSet()
    {
        if (!$this->helperSet) {
            $this->helperSet = $this->getDefaultHelperSet();
        }

        return $this->helperSet;
    }

    public function setDefinition(\PHPStanVendor\Symfony\Component\Console\Input\InputDefinition $definition)
    {
        $this->definition = $definition;
    }

    /**
     * Gets the InputDefinition related to this Application.
     *
     * @return InputDefinition The InputDefinition instance
     */
    public function getDefinition()
    {
        if (!$this->definition) {
            $this->definition = $this->getDefaultInputDefinition();
        }

        if ($this->singleCommand) {
            $inputDefinition = $this->definition;
            $inputDefinition->setArguments();

            return $inputDefinition;
        }

        return $this->definition;
    }

    /**
     * Gets the help message.
     *
     * @return string A help message
     */
    public function getHelp()
    {
        return $this->getLongVersion();
    }

    /**
     * Gets whether to catch exceptions or not during commands execution.
     *
     * @return bool Whether to catch exceptions or not during commands execution
     */
    public function areExceptionsCaught()
    {
        return $this->catchExceptions;
    }

    /**
     * Sets whether to catch exceptions or not during commands execution.
     *
     * @param bool $boolean Whether to catch exceptions or not during commands execution
     */
    public function setCatchExceptions($boolean)
    {
        $this->catchExceptions = (bool) $boolean;
    }

    /**
     * Gets whether to automatically exit after a command execution or not.
     *
     * @return bool Whether to automatically exit after a command execution or not
     */
    public function isAutoExitEnabled()
    {
        return $this->autoExit;
    }

    /**
     * Sets whether to automatically exit after a command execution or not.
     *
     * @param bool $boolean Whether to automatically exit after a command execution or not
     */
    public function setAutoExit($boolean)
    {
        $this->autoExit = (bool) $boolean;
    }

    /**
     * Gets the name of the application.
     *
     * @return string The application name
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Sets the application name.
     *
     * @param string $name The application name
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * Gets the application version.
     *
     * @return string The application version
     */
    public function getVersion()
    {
        return $this->version;
    }

    /**
     * Sets the application version.
     *
     * @param string $version The application version
     */
    public function setVersion($version)
    {
        $this->version = $version;
    }

    /**
     * Returns the long version of the application.
     *
     * @return string The long application version
     */
    public function getLongVersion()
    {
        if ('UNKNOWN' !== $this->getName()) {
            if ('UNKNOWN' !== $this->getVersion()) {
                return sprintf('%s <info>%s</info>', $this->getName(), $this->getVersion());
            }

            return $this->getName();
        }

        return 'Console Tool';
    }

    /**
     * Registers a new command.
     *
     * @param string $name The command name
     *
     * @return Command The newly created command
     */
    public function register($name)
    {
        return $this->add(new \PHPStanVendor\Symfony\Component\Console\Command\Command($name));
    }

    /**
     * Adds an array of command objects.
     *
     * If a Command is not enabled it will not be added.
     *
     * @param Command[] $commands An array of commands
     */
    public function addCommands(array $commands)
    {
        foreach ($commands as $command) {
            $this->add($command);
        }
    }

    /**
     * Adds a command object.
     *
     * If a command with the same name already exists, it will be overridden.
     * If the command is not enabled it will not be added.
     *
     * @return Command|null The registered command if enabled or null
     */
    public function add(\PHPStanVendor\Symfony\Component\Console\Command\Command $command)
    {
        $this->init();

        $command->setApplication($this);

        if (!$command->isEnabled()) {
            $command->setApplication(null);

            return;
        }

        if (null === $command->getDefinition()) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
        }

        if (!$command->getName()) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($command)));
        }

        $this->commands[$command->getName()] = $command;

        foreach ($command->getAliases() as $alias) {
            $this->commands[$alias] = $command;
        }

        return $command;
    }

    /**
     * Returns a registered command by name or alias.
     *
     * @param string $name The command name or alias
     *
     * @return Command A Command object
     *
     * @throws CommandNotFoundException When given command name does not exist
     */
    public function get($name)
    {
        $this->init();

        if (!$this->has($name)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
        }

        $command = $this->commands[$name];

        if ($this->wantHelps) {
            $this->wantHelps = false;

            $helpCommand = $this->get('help');
            $helpCommand->setCommand($command);

            return $helpCommand;
        }

        return $command;
    }

    /**
     * Returns true if the command exists, false otherwise.
     *
     * @param string $name The command name or alias
     *
     * @return bool true if the command exists, false otherwise
     */
    public function has($name)
    {
        $this->init();

        return isset($this->commands[$name]) || ($this->commandLoader && $this->commandLoader->has($name) && $this->add($this->commandLoader->get($name)));
    }

    /**
     * Returns an array of all unique namespaces used by currently registered commands.
     *
     * It does not return the global namespace which always exists.
     *
     * @return string[] An array of namespaces
     */
    public function getNamespaces()
    {
        $namespaces = array();
        foreach ($this->all() as $command) {
            $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));

            foreach ($command->getAliases() as $alias) {
                $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
            }
        }

        return array_values(array_unique(array_filter($namespaces)));
    }

    /**
     * Finds a registered namespace by a name or an abbreviation.
     *
     * @param string $namespace A namespace or abbreviation to search for
     *
     * @return string A registered namespace
     *
     * @throws CommandNotFoundException When namespace is incorrect or ambiguous
     */
    public function findNamespace($namespace)
    {
        $allNamespaces = $this->getNamespaces();
        $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace);
        $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);

        if (empty($namespaces)) {
            $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);

            if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
                if (1 == count($alternatives)) {
                    $message .= "\n\nDid you mean this?\n    ";
                } else {
                    $message .= "\n\nDid you mean one of these?\n    ";
                }

                $message .= implode("\n    ", $alternatives);
            }

            throw new \PHPStanVendor\Symfony\Component\Console\Exception\CommandNotFoundException($message, $alternatives);
        }

        $exact = in_array($namespace, $namespaces, true);
        if (count($namespaces) > 1 && !$exact) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\CommandNotFoundException(sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
        }

        return $exact ? $namespace : reset($namespaces);
    }

    /**
     * Finds a command by name or alias.
     *
     * Contrary to get, this command tries to find the best
     * match if you give it an abbreviation of a name or alias.
     *
     * @param string $name A command name or a command alias
     *
     * @return Command A Command instance
     *
     * @throws CommandNotFoundException When command name is incorrect or ambiguous
     */
    public function find($name)
    {
        $this->init();

        $aliases = array();
        $allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands);
        $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
        $commands = preg_grep('{^'.$expr.'}', $allCommands);

        if (empty($commands)) {
            $commands = preg_grep('{^'.$expr.'}i', $allCommands);
        }

        // if no commands matched or we just matched namespaces
        if (empty($commands) || count(preg_grep('{^'.$expr.'$}i', $commands)) < 1) {
            if (false !== $pos = strrpos($name, ':')) {
                // check if a namespace exists and contains commands
                $this->findNamespace(substr($name, 0, $pos));
            }

            $message = sprintf('Command "%s" is not defined.', $name);

            if ($alternatives = $this->findAlternatives($name, $allCommands)) {
                if (1 == count($alternatives)) {
                    $message .= "\n\nDid you mean this?\n    ";
                } else {
                    $message .= "\n\nDid you mean one of these?\n    ";
                }
                $message .= implode("\n    ", $alternatives);
            }

            throw new \PHPStanVendor\Symfony\Component\Console\Exception\CommandNotFoundException($message, $alternatives);
        }

        // filter out aliases for commands which are already on the list
        if (count($commands) > 1) {
            $commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands;
            $commands = array_unique(array_filter($commands, function ($nameOrAlias) use ($commandList, $commands, &$aliases) {
                $commandName = $commandList[$nameOrAlias] instanceof \PHPStanVendor\Symfony\Component\Console\Command\Command ? $commandList[$nameOrAlias]->getName() : $nameOrAlias;
                $aliases[$nameOrAlias] = $commandName;

                return $commandName === $nameOrAlias || !in_array($commandName, $commands);
            }));
        }

        $exact = in_array($name, $commands, true) || isset($aliases[$name]);
        if (count($commands) > 1 && !$exact) {
            $usableWidth = $this->terminal->getWidth() - 10;
            $abbrevs = array_values($commands);
            $maxLen = 0;
            foreach ($abbrevs as $abbrev) {
                $maxLen = max(\PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($abbrev), $maxLen);
            }
            $abbrevs = array_map(function ($cmd) use ($commandList, $usableWidth, $maxLen) {
                if (!$commandList[$cmd] instanceof \PHPStanVendor\Symfony\Component\Console\Command\Command) {
                    return $cmd;
                }
                $abbrev = str_pad($cmd, $maxLen, ' ').' '.$commandList[$cmd]->getDescription();

                return \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($abbrev) > $usableWidth ? \PHPStanVendor\Symfony\Component\Console\Helper\Helper::substr($abbrev, 0, $usableWidth - 3).'...' : $abbrev;
            }, array_values($commands));
            $suggestions = $this->getAbbreviationSuggestions($abbrevs);

            throw new \PHPStanVendor\Symfony\Component\Console\Exception\CommandNotFoundException(sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $name, $suggestions), array_values($commands));
        }

        return $this->get($exact ? $name : reset($commands));
    }

    /**
     * Gets the commands (registered in the given namespace if provided).
     *
     * The array keys are the full names and the values the command instances.
     *
     * @param string $namespace A namespace name
     *
     * @return Command[] An array of Command instances
     */
    public function all($namespace = null)
    {
        $this->init();

        if (null === $namespace) {
            if (!$this->commandLoader) {
                return $this->commands;
            }

            $commands = $this->commands;
            foreach ($this->commandLoader->getNames() as $name) {
                if (!isset($commands[$name]) && $this->has($name)) {
                    $commands[$name] = $this->get($name);
                }
            }

            return $commands;
        }

        $commands = array();
        foreach ($this->commands as $name => $command) {
            if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
                $commands[$name] = $command;
            }
        }

        if ($this->commandLoader) {
            foreach ($this->commandLoader->getNames() as $name) {
                if (!isset($commands[$name]) && $namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1) && $this->has($name)) {
                    $commands[$name] = $this->get($name);
                }
            }
        }

        return $commands;
    }

    /**
     * Returns an array of possible abbreviations given a set of names.
     *
     * @param array $names An array of names
     *
     * @return array An array of abbreviations
     */
    public static function getAbbreviations($names)
    {
        $abbrevs = array();
        foreach ($names as $name) {
            for ($len = strlen($name); $len > 0; --$len) {
                $abbrev = substr($name, 0, $len);
                $abbrevs[$abbrev][] = $name;
            }
        }

        return $abbrevs;
    }

    /**
     * Renders a caught exception.
     */
    public function renderException(\Exception $e, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output)
    {
        $output->writeln('', \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET);

        $this->doRenderException($e, $output);

        if (null !== $this->runningCommand) {
            $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET);
            $output->writeln('', \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET);
        }
    }

    protected function doRenderException(\Exception $e, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output)
    {
        do {
            $message = trim($e->getMessage());
            if ('' === $message || \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $title = sprintf('  [%s%s]  ', get_class($e), 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : '');
                $len = \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($title);
            } else {
                $len = 0;
            }

            $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : PHP_INT_MAX;
            // HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327
            if (defined('HHVM_VERSION') && $width > 1 << 31) {
                $width = 1 << 31;
            }
            $lines = array();
            foreach ('' !== $message ? preg_split('/\r?\n/', $message) : array() as $line) {
                foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
                    // pre-format lines to get the right string length
                    $lineLength = \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($line) + 4;
                    $lines[] = array($line, $lineLength);

                    $len = max($lineLength, $len);
                }
            }

            $messages = array();
            if (!$e instanceof \PHPStanVendor\Symfony\Component\Console\Exception\ExceptionInterface || \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $messages[] = sprintf('<comment>%s</comment>', \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatter::escape(sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a')));
            }
            $messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len));
            if ('' === $message || \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($title))));
            }
            foreach ($lines as $line) {
                $messages[] = sprintf('<error>  %s  %s</error>', \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1]));
            }
            $messages[] = $emptyLine;
            $messages[] = '';

            $output->writeln($messages, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET);

            if (\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $output->writeln('<comment>Exception trace:</comment>', \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET);

                // exception related properties
                $trace = $e->getTrace();

                for ($i = 0, $count = count($trace); $i < $count; ++$i) {
                    $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
                    $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
                    $function = $trace[$i]['function'];
                    $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
                    $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';

                    $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line), \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET);
                }

                $output->writeln('', \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET);
            }
        } while ($e = $e->getPrevious());
    }

    /**
     * Tries to figure out the terminal width in which this application runs.
     *
     * @return int|null
     *
     * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead.
     */
    protected function getTerminalWidth()
    {
        @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED);

        return $this->terminal->getWidth();
    }

    /**
     * Tries to figure out the terminal height in which this application runs.
     *
     * @return int|null
     *
     * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead.
     */
    protected function getTerminalHeight()
    {
        @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED);

        return $this->terminal->getHeight();
    }

    /**
     * Tries to figure out the terminal dimensions based on the current environment.
     *
     * @return array Array containing width and height
     *
     * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead.
     */
    public function getTerminalDimensions()
    {
        @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED);

        return array($this->terminal->getWidth(), $this->terminal->getHeight());
    }

    /**
     * Sets terminal dimensions.
     *
     * Can be useful to force terminal dimensions for functional tests.
     *
     * @param int $width  The width
     * @param int $height The height
     *
     * @return $this
     *
     * @deprecated since version 3.2, to be removed in 4.0. Set the COLUMNS and LINES env vars instead.
     */
    public function setTerminalDimensions($width, $height)
    {
        @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Set the COLUMNS and LINES env vars instead.', __METHOD__), E_USER_DEPRECATED);

        putenv('COLUMNS='.$width);
        putenv('LINES='.$height);

        return $this;
    }

    /**
     * Configures the input and output instances based on the user arguments and options.
     */
    protected function configureIO(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output)
    {
        if (true === $input->hasParameterOption(array('--ansi'), true)) {
            $output->setDecorated(true);
        } elseif (true === $input->hasParameterOption(array('--no-ansi'), true)) {
            $output->setDecorated(false);
        }

        if (true === $input->hasParameterOption(array('--no-interaction', '-n'), true)) {
            $input->setInteractive(false);
        } elseif (function_exists('posix_isatty')) {
            $inputStream = null;

            if ($input instanceof \PHPStanVendor\Symfony\Component\Console\Input\StreamableInputInterface) {
                $inputStream = $input->getStream();
            }

            // This check ensures that calling QuestionHelper::setInputStream() works
            // To be removed in 4.0 (in the same time as QuestionHelper::setInputStream)
            if (!$inputStream && $this->getHelperSet()->has('question')) {
                $inputStream = $this->getHelperSet()->get('question')->getInputStream(false);
            }

            if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) {
                $input->setInteractive(false);
            }
        }

        switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) {
            case -1: $output->setVerbosity(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET); break;
            case 1: $output->setVerbosity(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE); break;
            case 2: $output->setVerbosity(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERY_VERBOSE); break;
            case 3: $output->setVerbosity(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_DEBUG); break;
            default: $shellVerbosity = 0; break;
        }

        if (true === $input->hasParameterOption(array('--quiet', '-q'), true)) {
            $output->setVerbosity(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET);
            $shellVerbosity = -1;
        } else {
            if ($input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || 3 === $input->getParameterOption('--verbose', false, true)) {
                $output->setVerbosity(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_DEBUG);
                $shellVerbosity = 3;
            } elseif ($input->hasParameterOption('-vv', true) || $input->hasParameterOption('--verbose=2', true) || 2 === $input->getParameterOption('--verbose', false, true)) {
                $output->setVerbosity(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERY_VERBOSE);
                $shellVerbosity = 2;
            } elseif ($input->hasParameterOption('-v', true) || $input->hasParameterOption('--verbose=1', true) || $input->hasParameterOption('--verbose', true) || $input->getParameterOption('--verbose', false, true)) {
                $output->setVerbosity(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE);
                $shellVerbosity = 1;
            }
        }

        if (-1 === $shellVerbosity) {
            $input->setInteractive(false);
        }

        putenv('SHELL_VERBOSITY='.$shellVerbosity);
        $_ENV['SHELL_VERBOSITY'] = $shellVerbosity;
        $_SERVER['SHELL_VERBOSITY'] = $shellVerbosity;
    }

    /**
     * Runs the current command.
     *
     * If an event dispatcher has been attached to the application,
     * events are also dispatched during the life-cycle of the command.
     *
     * @return int 0 if everything went fine, or an error code
     */
    protected function doRunCommand(\PHPStanVendor\Symfony\Component\Console\Command\Command $command, \PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output)
    {
        foreach ($command->getHelperSet() as $helper) {
            if ($helper instanceof \PHPStanVendor\Symfony\Component\Console\Input\InputAwareInterface) {
                $helper->setInput($input);
            }
        }

        if (null === $this->dispatcher) {
            return $command->run($input, $output);
        }

        // bind before the console.command event, so the listeners have access to input options/arguments
        try {
            $command->mergeApplicationDefinition();
            $input->bind($command->getDefinition());
        } catch (\PHPStanVendor\Symfony\Component\Console\Exception\ExceptionInterface $e) {
            // ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition
        }

        $event = new \PHPStanVendor\Symfony\Component\Console\Event\ConsoleCommandEvent($command, $input, $output);
        $e = null;

        try {
            $this->dispatcher->dispatch(\PHPStanVendor\Symfony\Component\Console\ConsoleEvents::COMMAND, $event);

            if ($event->commandShouldRun()) {
                $exitCode = $command->run($input, $output);
            } else {
                $exitCode = \PHPStanVendor\Symfony\Component\Console\Event\ConsoleCommandEvent::RETURN_CODE_DISABLED;
            }
        } catch (\Exception $e) {
        } catch (\Throwable $e) {
        }
        if (null !== $e) {
            if ($this->dispatcher->hasListeners(\PHPStanVendor\Symfony\Component\Console\ConsoleEvents::EXCEPTION)) {
                $x = $e instanceof \Exception ? $e : new \PHPStanVendor\Symfony\Component\Debug\Exception\FatalThrowableError($e);
                $event = new \PHPStanVendor\Symfony\Component\Console\Event\ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode());
                $this->dispatcher->dispatch(\PHPStanVendor\Symfony\Component\Console\ConsoleEvents::EXCEPTION, $event);

                if ($x !== $event->getException()) {
                    $e = $event->getException();
                }
            }
            $event = new \PHPStanVendor\Symfony\Component\Console\Event\ConsoleErrorEvent($input, $output, $e, $command);
            $this->dispatcher->dispatch(\PHPStanVendor\Symfony\Component\Console\ConsoleEvents::ERROR, $event);
            $e = $event->getError();

            if (0 === $exitCode = $event->getExitCode()) {
                $e = null;
            }
        }

        $event = new \PHPStanVendor\Symfony\Component\Console\Event\ConsoleTerminateEvent($command, $input, $output, $exitCode);
        $this->dispatcher->dispatch(\PHPStanVendor\Symfony\Component\Console\ConsoleEvents::TERMINATE, $event);

        if (null !== $e) {
            throw $e;
        }

        return $event->getExitCode();
    }

    /**
     * Gets the name of the command based on input.
     *
     * @return string The command name
     */
    protected function getCommandName(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input)
    {
        return $this->singleCommand ? $this->defaultCommand : $input->getFirstArgument();
    }

    /**
     * Gets the default input definition.
     *
     * @return InputDefinition An InputDefinition instance
     */
    protected function getDefaultInputDefinition()
    {
        return new \PHPStanVendor\Symfony\Component\Console\Input\InputDefinition(array(
            new \PHPStanVendor\Symfony\Component\Console\Input\InputArgument('command', \PHPStanVendor\Symfony\Component\Console\Input\InputArgument::REQUIRED, 'The command to execute'),

            new \PHPStanVendor\Symfony\Component\Console\Input\InputOption('--help', '-h', \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'Display this help message'),
            new \PHPStanVendor\Symfony\Component\Console\Input\InputOption('--quiet', '-q', \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'Do not output any message'),
            new \PHPStanVendor\Symfony\Component\Console\Input\InputOption('--verbose', '-v|vv|vvv', \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
            new \PHPStanVendor\Symfony\Component\Console\Input\InputOption('--version', '-V', \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'Display this application version'),
            new \PHPStanVendor\Symfony\Component\Console\Input\InputOption('--ansi', '', \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'Force ANSI output'),
            new \PHPStanVendor\Symfony\Component\Console\Input\InputOption('--no-ansi', '', \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'Disable ANSI output'),
            new \PHPStanVendor\Symfony\Component\Console\Input\InputOption('--no-interaction', '-n', \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'Do not ask any interactive question'),
        ));
    }

    /**
     * Gets the default commands that should always be available.
     *
     * @return Command[] An array of default Command instances
     */
    protected function getDefaultCommands()
    {
        return array(new \PHPStanVendor\Symfony\Component\Console\Command\HelpCommand(), new \PHPStanVendor\Symfony\Component\Console\Command\ListCommand());
    }

    /**
     * Gets the default helper set with the helpers that should always be available.
     *
     * @return HelperSet A HelperSet instance
     */
    protected function getDefaultHelperSet()
    {
        return new \PHPStanVendor\Symfony\Component\Console\Helper\HelperSet(array(
            new \PHPStanVendor\Symfony\Component\Console\Helper\FormatterHelper(),
            new \PHPStanVendor\Symfony\Component\Console\Helper\DebugFormatterHelper(),
            new \PHPStanVendor\Symfony\Component\Console\Helper\ProcessHelper(),
            new \PHPStanVendor\Symfony\Component\Console\Helper\QuestionHelper(),
        ));
    }

    /**
     * Returns abbreviated suggestions in string format.
     *
     * @param array $abbrevs Abbreviated suggestions to convert
     *
     * @return string A formatted string of abbreviated suggestions
     */
    private function getAbbreviationSuggestions($abbrevs)
    {
        return '    '.implode("\n    ", $abbrevs);
    }

    /**
     * Returns the namespace part of the command name.
     *
     * This method is not part of public API and should not be used directly.
     *
     * @param string $name  The full name of the command
     * @param string $limit The maximum number of parts of the namespace
     *
     * @return string The namespace of the command
     */
    public function extractNamespace($name, $limit = null)
    {
        $parts = explode(':', $name);
        array_pop($parts);

        return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
    }

    /**
     * Finds alternative of $name among $collection,
     * if nothing is found in $collection, try in $abbrevs.
     *
     * @param string   $name       The string
     * @param iterable $collection The collection
     *
     * @return string[] A sorted array of similar string
     */
    private function findAlternatives($name, $collection)
    {
        $threshold = 1e3;
        $alternatives = array();

        $collectionParts = array();
        foreach ($collection as $item) {
            $collectionParts[$item] = explode(':', $item);
        }

        foreach (explode(':', $name) as $i => $subname) {
            foreach ($collectionParts as $collectionName => $parts) {
                $exists = isset($alternatives[$collectionName]);
                if (!isset($parts[$i]) && $exists) {
                    $alternatives[$collectionName] += $threshold;
                    continue;
                } elseif (!isset($parts[$i])) {
                    continue;
                }

                $lev = levenshtein($subname, $parts[$i]);
                if ($lev <= strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
                    $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
                } elseif ($exists) {
                    $alternatives[$collectionName] += $threshold;
                }
            }
        }

        foreach ($collection as $item) {
            $lev = levenshtein($name, $item);
            if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
                $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
            }
        }

        $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
        ksort($alternatives, SORT_NATURAL | SORT_FLAG_CASE);

        return array_keys($alternatives);
    }

    /**
     * Sets the default Command name.
     *
     * @param string $commandName     The Command name
     * @param bool   $isSingleCommand Set to true if there is only one command in this application
     *
     * @return self
     */
    public function setDefaultCommand($commandName, $isSingleCommand = false)
    {
        $this->defaultCommand = $commandName;

        if ($isSingleCommand) {
            // Ensure the command exist
            $this->find($commandName);

            $this->singleCommand = true;
        }

        return $this;
    }

    private function splitStringByWidth($string, $width)
    {
        // str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly.
        // additionally, array_slice() is not enough as some character has doubled width.
        // we need a function to split string not by character count but by string width
        if (false === $encoding = mb_detect_encoding($string, null, true)) {
            return str_split($string, $width);
        }

        $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
        $lines = array();
        $line = '';
        foreach (preg_split('//u', $utf8String) as $char) {
            // test if $char could be appended to current line
            if (mb_strwidth($line.$char, 'utf8') <= $width) {
                $line .= $char;
                continue;
            }
            // if not, push current line to array and make new line
            $lines[] = str_pad($line, $width);
            $line = $char;
        }

        $lines[] = count($lines) ? str_pad($line, $width) : $line;

        mb_convert_variables($encoding, 'utf8', $lines);

        return $lines;
    }

    /**
     * Returns all namespaces of the command name.
     *
     * @param string $name The full name of the command
     *
     * @return string[] The namespaces of the command
     */
    private function extractAllNamespaces($name)
    {
        // -1 as third argument is needed to skip the command short name when exploding
        $parts = explode(':', $name, -1);
        $namespaces = array();

        foreach ($parts as $part) {
            if (count($namespaces)) {
                $namespaces[] = end($namespaces).':'.$part;
            } else {
                $namespaces[] = $part;
            }
        }

        return $namespaces;
    }

    private function init()
    {
        if ($this->initialized) {
            return;
        }
        $this->initialized = true;

        foreach ($this->getDefaultCommands() as $command) {
            $this->add($command);
        }
    }
}
CHANGELOG
=========

3.4.0
-----

 * added `SHELL_VERBOSITY` env var to control verbosity
 * added `CommandLoaderInterface`, `FactoryCommandLoader` and PSR-11
   `ContainerCommandLoader` for commands lazy-loading
 * added a case-insensitive command name matching fallback
 * added static `Command::$defaultName/getDefaultName()`, allowing for
   commands to be registered at compile time in the application command loader.
   Setting the `$defaultName` property avoids the need for filling the `command`
   attribute on the `console.command` tag when using `AddConsoleCommandPass`.

3.3.0
-----

* added `ExceptionListener`
* added `AddConsoleCommandPass` (originally in FrameworkBundle)
* [BC BREAK] `Input::getOption()` no longer returns the default value for options
  with value optional explicitly passed empty
* added console.error event to catch exceptions thrown by other listeners
* deprecated console.exception event in favor of console.error
* added ability to handle `CommandNotFoundException` through the 
 `console.error` event
* deprecated default validation in `SymfonyQuestionHelper::ask`

3.2.0
------

* added `setInputs()` method to CommandTester for ease testing of commands expecting inputs
* added `setStream()` and `getStream()` methods to Input (implement StreamableInputInterface)
* added StreamableInputInterface
* added LockableTrait

3.1.0
-----

 * added truncate method to FormatterHelper
 * added setColumnWidth(s) method to Table 

2.8.3
-----

 * remove readline support from the question helper as it caused issues

2.8.0
-----

 * use readline for user input in the question helper when available to allow
   the use of arrow keys

2.6.0
-----

 * added a Process helper
 * added a DebugFormatter helper

2.5.0
-----

 * deprecated the dialog helper (use the question helper instead)
 * deprecated TableHelper in favor of Table
 * deprecated ProgressHelper in favor of ProgressBar
 * added ConsoleLogger
 * added a question helper
 * added a way to set the process name of a command
 * added a way to set a default command instead of `ListCommand`

2.4.0
-----

 * added a way to force terminal dimensions
 * added a convenient method to detect verbosity level
 * [BC BREAK] made descriptors use output instead of returning a string

2.3.0
-----

 * added multiselect support to the select dialog helper
 * added Table Helper for tabular data rendering
 * added support for events in `Application`
 * added a way to normalize EOLs in `ApplicationTester::getDisplay()` and `CommandTester::getDisplay()`
 * added a way to set the progress bar progress via the `setCurrent` method
 * added support for multiple InputOption shortcuts, written as `'-a|-b|-c'`
 * added two additional verbosity levels, VERBOSITY_VERY_VERBOSE and VERBOSITY_DEBUG

2.2.0
-----

 * added support for colorization on Windows via ConEmu
 * add a method to Dialog Helper to ask for a question and hide the response
 * added support for interactive selections in console (DialogHelper::select())
 * added support for autocompletion as you type in Dialog Helper

2.1.0
-----

 * added ConsoleOutputInterface
 * added the possibility to disable a command (Command::isEnabled())
 * added suggestions when a command does not exist
 * added a --raw option to the list command
 * added support for STDERR in the console output class (errors are now sent
   to STDERR)
 * made the defaults (helper set, commands, input definition) in Application
   more easily customizable
 * added support for the shell even if readline is not available
 * added support for process isolation in Symfony shell via
   `--process-isolation` switch
 * added support for `--`, which disables options parsing after that point
   (tokens will be parsed as arguments)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Command;

/**
 * Base class for all commands.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Command
{
    /**
     * @var string|null The default command name
     */
    protected static $defaultName;

    private $application;
    private $name;
    private $processTitle;
    private $aliases = array();
    private $definition;
    private $hidden = false;
    private $help;
    private $description;
    private $ignoreValidationErrors = false;
    private $applicationDefinitionMerged = false;
    private $applicationDefinitionMergedWithArgs = false;
    private $code;
    private $synopsis = array();
    private $usages = array();
    private $helperSet;

    /**
     * @return string|null The default command name or null when no default name is set
     */
    public static function getDefaultName()
    {
        $class = get_called_class();
        $r = new \ReflectionProperty($class, 'defaultName');

        return $class === $r->class ? static::$defaultName : null;
    }

    /**
     * @param string|null $name The name of the command; passing null means it must be set in configure()
     *
     * @throws LogicException When the command name is empty
     */
    public function __construct($name = null)
    {
        $this->definition = new \PHPStanVendor\Symfony\Component\Console\Input\InputDefinition();

        if (null !== $name || null !== $name = static::getDefaultName()) {
            $this->setName($name);
        }

        $this->configure();
    }

    /**
     * Ignores validation errors.
     *
     * This is mainly useful for the help command.
     */
    public function ignoreValidationErrors()
    {
        $this->ignoreValidationErrors = true;
    }

    public function setApplication(\PHPStanVendor\Symfony\Component\Console\Application $application = null)
    {
        $this->application = $application;
        if ($application) {
            $this->setHelperSet($application->getHelperSet());
        } else {
            $this->helperSet = null;
        }
    }

    public function setHelperSet(\PHPStanVendor\Symfony\Component\Console\Helper\HelperSet $helperSet)
    {
        $this->helperSet = $helperSet;
    }

    /**
     * Gets the helper set.
     *
     * @return HelperSet A HelperSet instance
     */
    public function getHelperSet()
    {
        return $this->helperSet;
    }

    /**
     * Gets the application instance for this command.
     *
     * @return Application An Application instance
     */
    public function getApplication()
    {
        return $this->application;
    }

    /**
     * Checks whether the command is enabled or not in the current environment.
     *
     * Override this to check for x or y and return false if the command can not
     * run properly under the current conditions.
     *
     * @return bool
     */
    public function isEnabled()
    {
        return true;
    }

    /**
     * Configures the current command.
     */
    protected function configure()
    {
    }

    /**
     * Executes the current command.
     *
     * This method is not abstract because you can use this class
     * as a concrete class. In this case, instead of defining the
     * execute() method, you set the code to execute by passing
     * a Closure to the setCode() method.
     *
     * @return null|int null or 0 if everything went fine, or an error code
     *
     * @throws LogicException When this abstract method is not implemented
     *
     * @see setCode()
     */
    protected function execute(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output)
    {
        throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException('You must override the execute() method in the concrete command class.');
    }

    /**
     * Interacts with the user.
     *
     * This method is executed before the InputDefinition is validated.
     * This means that this is the only place where the command can
     * interactively ask for values of missing required arguments.
     */
    protected function interact(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output)
    {
    }

    /**
     * Initializes the command just after the input has been validated.
     *
     * This is mainly useful when a lot of commands extends one main command
     * where some things need to be initialized based on the input arguments and options.
     */
    protected function initialize(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output)
    {
    }

    /**
     * Runs the command.
     *
     * The code to execute is either defined directly with the
     * setCode() method or by overriding the execute() method
     * in a sub-class.
     *
     * @return int The command exit code
     *
     * @throws \Exception When binding input fails. Bypass this by calling {@link ignoreValidationErrors()}.
     *
     * @see setCode()
     * @see execute()
     */
    public function run(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output)
    {
        // force the creation of the synopsis before the merge with the app definition
        $this->getSynopsis(true);
        $this->getSynopsis(false);

        // add the application arguments and options
        $this->mergeApplicationDefinition();

        // bind the input against the command specific arguments/options
        try {
            $input->bind($this->definition);
        } catch (\PHPStanVendor\Symfony\Component\Console\Exception\ExceptionInterface $e) {
            if (!$this->ignoreValidationErrors) {
                throw $e;
            }
        }

        $this->initialize($input, $output);

        if (null !== $this->processTitle) {
            if (function_exists('cli_set_process_title')) {
                if (false === @cli_set_process_title($this->processTitle)) {
                    if ('Darwin' === PHP_OS) {
                        $output->writeln('<comment>Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.</comment>');
                    } else {
                        $error = error_get_last();
                        trigger_error($error['message'], E_USER_WARNING);
                    }
                }
            } elseif (function_exists('setproctitle')) {
                setproctitle($this->processTitle);
            } elseif (\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
                $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
            }
        }

        if ($input->isInteractive()) {
            $this->interact($input, $output);
        }

        // The command name argument is often omitted when a command is executed directly with its run() method.
        // It would fail the validation if we didn't make sure the command argument is present,
        // since it's required by the application.
        if ($input->hasArgument('command') && null === $input->getArgument('command')) {
            $input->setArgument('command', $this->getName());
        }

        $input->validate();

        if ($this->code) {
            $statusCode = call_user_func($this->code, $input, $output);
        } else {
            $statusCode = $this->execute($input, $output);
        }

        return is_numeric($statusCode) ? (int) $statusCode : 0;
    }

    /**
     * Sets the code to execute when running this command.
     *
     * If this method is used, it overrides the code defined
     * in the execute() method.
     *
     * @param callable $code A callable(InputInterface $input, OutputInterface $output)
     *
     * @return $this
     *
     * @throws InvalidArgumentException
     *
     * @see execute()
     */
    public function setCode(callable $code)
    {
        if ($code instanceof \Closure) {
            $r = new \ReflectionFunction($code);
            if (null === $r->getClosureThis()) {
                if (\PHP_VERSION_ID < 70000) {
                    // Bug in PHP5: https://bugs.php.net/bug.php?id=64761
                    // This means that we cannot bind static closures and therefore we must
                    // ignore any errors here.  There is no way to test if the closure is
                    // bindable.
                    $code = @\Closure::bind($code, $this);
                } else {
                    $code = \Closure::bind($code, $this);
                }
            }
        }

        $this->code = $code;

        return $this;
    }

    /**
     * Merges the application definition with the command definition.
     *
     * This method is not part of public API and should not be used directly.
     *
     * @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments
     */
    public function mergeApplicationDefinition($mergeArgs = true)
    {
        if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
            return;
        }

        $this->definition->addOptions($this->application->getDefinition()->getOptions());

        if ($mergeArgs) {
            $currentArguments = $this->definition->getArguments();
            $this->definition->setArguments($this->application->getDefinition()->getArguments());
            $this->definition->addArguments($currentArguments);
        }

        $this->applicationDefinitionMerged = true;
        if ($mergeArgs) {
            $this->applicationDefinitionMergedWithArgs = true;
        }
    }

    /**
     * Sets an array of argument and option instances.
     *
     * @param array|InputDefinition $definition An array of argument and option instances or a definition instance
     *
     * @return $this
     */
    public function setDefinition($definition)
    {
        if ($definition instanceof \PHPStanVendor\Symfony\Component\Console\Input\InputDefinition) {
            $this->definition = $definition;
        } else {
            $this->definition->setDefinition($definition);
        }

        $this->applicationDefinitionMerged = false;

        return $this;
    }

    /**
     * Gets the InputDefinition attached to this Command.
     *
     * @return InputDefinition An InputDefinition instance
     */
    public function getDefinition()
    {
        return $this->definition;
    }

    /**
     * Gets the InputDefinition to be used to create representations of this Command.
     *
     * Can be overridden to provide the original command representation when it would otherwise
     * be changed by merging with the application InputDefinition.
     *
     * This method is not part of public API and should not be used directly.
     *
     * @return InputDefinition An InputDefinition instance
     */
    public function getNativeDefinition()
    {
        return $this->getDefinition();
    }

    /**
     * Adds an argument.
     *
     * @param string $name        The argument name
     * @param int    $mode        The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
     * @param string $description A description text
     * @param mixed  $default     The default value (for InputArgument::OPTIONAL mode only)
     *
     * @return $this
     */
    public function addArgument($name, $mode = null, $description = '', $default = null)
    {
        $this->definition->addArgument(new \PHPStanVendor\Symfony\Component\Console\Input\InputArgument($name, $mode, $description, $default));

        return $this;
    }

    /**
     * Adds an option.
     *
     * @param string $name        The option name
     * @param string $shortcut    The shortcut (can be null)
     * @param int    $mode        The option mode: One of the InputOption::VALUE_* constants
     * @param string $description A description text
     * @param mixed  $default     The default value (must be null for InputOption::VALUE_NONE)
     *
     * @return $this
     */
    public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
    {
        $this->definition->addOption(new \PHPStanVendor\Symfony\Component\Console\Input\InputOption($name, $shortcut, $mode, $description, $default));

        return $this;
    }

    /**
     * Sets the name of the command.
     *
     * This method can set both the namespace and the name if
     * you separate them by a colon (:)
     *
     *     $command->setName('foo:bar');
     *
     * @param string $name The command name
     *
     * @return $this
     *
     * @throws InvalidArgumentException When the name is invalid
     */
    public function setName($name)
    {
        $this->validateName($name);

        $this->name = $name;

        return $this;
    }

    /**
     * Sets the process title of the command.
     *
     * This feature should be used only when creating a long process command,
     * like a daemon.
     *
     * PHP 5.5+ or the proctitle PECL library is required
     *
     * @param string $title The process title
     *
     * @return $this
     */
    public function setProcessTitle($title)
    {
        $this->processTitle = $title;

        return $this;
    }

    /**
     * Returns the command name.
     *
     * @return string The command name
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param bool $hidden Whether or not the command should be hidden from the list of commands
     *
     * @return Command The current instance
     */
    public function setHidden($hidden)
    {
        $this->hidden = (bool) $hidden;

        return $this;
    }

    /**
     * @return bool whether the command should be publicly shown or not
     */
    public function isHidden()
    {
        return $this->hidden;
    }

    /**
     * Sets the description for the command.
     *
     * @param string $description The description for the command
     *
     * @return $this
     */
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }

    /**
     * Returns the description for the command.
     *
     * @return string The description for the command
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * Sets the help for the command.
     *
     * @param string $help The help for the command
     *
     * @return $this
     */
    public function setHelp($help)
    {
        $this->help = $help;

        return $this;
    }

    /**
     * Returns the help for the command.
     *
     * @return string The help for the command
     */
    public function getHelp()
    {
        return $this->help;
    }

    /**
     * Returns the processed help for the command replacing the %command.name% and
     * %command.full_name% patterns with the real values dynamically.
     *
     * @return string The processed help for the command
     */
    public function getProcessedHelp()
    {
        $name = $this->name;

        $placeholders = array(
            '%command.name%',
            '%command.full_name%',
        );
        $replacements = array(
            $name,
            $_SERVER['PHP_SELF'].' '.$name,
        );

        return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
    }

    /**
     * Sets the aliases for the command.
     *
     * @param string[] $aliases An array of aliases for the command
     *
     * @return $this
     *
     * @throws InvalidArgumentException When an alias is invalid
     */
    public function setAliases($aliases)
    {
        if (!is_array($aliases) && !$aliases instanceof \Traversable) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
        }

        foreach ($aliases as $alias) {
            $this->validateName($alias);
        }

        $this->aliases = $aliases;

        return $this;
    }

    /**
     * Returns the aliases for the command.
     *
     * @return array An array of aliases for the command
     */
    public function getAliases()
    {
        return $this->aliases;
    }

    /**
     * Returns the synopsis for the command.
     *
     * @param bool $short Whether to show the short version of the synopsis (with options folded) or not
     *
     * @return string The synopsis
     */
    public function getSynopsis($short = false)
    {
        $key = $short ? 'short' : 'long';

        if (!isset($this->synopsis[$key])) {
            $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
        }

        return $this->synopsis[$key];
    }

    /**
     * Add a command usage example.
     *
     * @param string $usage The usage, it'll be prefixed with the command name
     *
     * @return $this
     */
    public function addUsage($usage)
    {
        if (0 !== strpos($usage, $this->name)) {
            $usage = sprintf('%s %s', $this->name, $usage);
        }

        $this->usages[] = $usage;

        return $this;
    }

    /**
     * Returns alternative usages of the command.
     *
     * @return array
     */
    public function getUsages()
    {
        return $this->usages;
    }

    /**
     * Gets a helper instance by name.
     *
     * @param string $name The helper name
     *
     * @return mixed The helper value
     *
     * @throws LogicException           if no HelperSet is defined
     * @throws InvalidArgumentException if the helper is not defined
     */
    public function getHelper($name)
    {
        if (null === $this->helperSet) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException(sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name));
        }

        return $this->helperSet->get($name);
    }

    /**
     * Validates a command name.
     *
     * It must be non-empty and parts can optionally be separated by ":".
     *
     * @param string $name
     *
     * @throws InvalidArgumentException When the name is invalid
     */
    private function validateName($name)
    {
        if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Command;

/**
 * HelpCommand displays the help for a given command.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HelpCommand extends \PHPStanVendor\Symfony\Component\Console\Command\Command
{
    private $command;

    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this->ignoreValidationErrors();

        $this
            ->setName('help')
            ->setDefinition(array(
                new \PHPStanVendor\Symfony\Component\Console\Input\InputArgument('command_name', \PHPStanVendor\Symfony\Component\Console\Input\InputArgument::OPTIONAL, 'The command name', 'help'),
                new \PHPStanVendor\Symfony\Component\Console\Input\InputOption('format', null, \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
                new \PHPStanVendor\Symfony\Component\Console\Input\InputOption('raw', null, \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'To output raw command help'),
            ))
            ->setDescription('Displays help for a command')
            ->setHelp(<<<'EOF'
The <info>%command.name%</info> command displays help for a given command:

  <info>php %command.full_name% list</info>

You can also output the help in other formats by using the <comment>--format</comment> option:

  <info>php %command.full_name% --format=xml list</info>

To display the list of available commands, please use the <info>list</info> command.
EOF
            )
        ;
    }

    public function setCommand(\PHPStanVendor\Symfony\Component\Console\Command\Command $command)
    {
        $this->command = $command;
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output)
    {
        if (null === $this->command) {
            $this->command = $this->getApplication()->find($input->getArgument('command_name'));
        }

        $helper = new \PHPStanVendor\Symfony\Component\Console\Helper\DescriptorHelper();
        $helper->describe($output, $this->command, array(
            'format' => $input->getOption('format'),
            'raw_text' => $input->getOption('raw'),
        ));

        $this->command = null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Command;

/**
 * ListCommand displays the list of all available commands for the application.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ListCommand extends \PHPStanVendor\Symfony\Component\Console\Command\Command
{
    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this
            ->setName('list')
            ->setDefinition($this->createDefinition())
            ->setDescription('Lists commands')
            ->setHelp(<<<'EOF'
The <info>%command.name%</info> command lists all commands:

  <info>php %command.full_name%</info>

You can also display the commands for a specific namespace:

  <info>php %command.full_name% test</info>

You can also output the information in other formats by using the <comment>--format</comment> option:

  <info>php %command.full_name% --format=xml</info>

It's also possible to get raw list of commands (useful for embedding command runner):

  <info>php %command.full_name% --raw</info>
EOF
            )
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function getNativeDefinition()
    {
        return $this->createDefinition();
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output)
    {
        $helper = new \PHPStanVendor\Symfony\Component\Console\Helper\DescriptorHelper();
        $helper->describe($output, $this->getApplication(), array(
            'format' => $input->getOption('format'),
            'raw_text' => $input->getOption('raw'),
            'namespace' => $input->getArgument('namespace'),
        ));
    }

    /**
     * {@inheritdoc}
     */
    private function createDefinition()
    {
        return new \PHPStanVendor\Symfony\Component\Console\Input\InputDefinition(array(
            new \PHPStanVendor\Symfony\Component\Console\Input\InputArgument('namespace', \PHPStanVendor\Symfony\Component\Console\Input\InputArgument::OPTIONAL, 'The namespace name'),
            new \PHPStanVendor\Symfony\Component\Console\Input\InputOption('raw', null, \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'To output raw command list'),
            new \PHPStanVendor\Symfony\Component\Console\Input\InputOption('format', null, \PHPStanVendor\Symfony\Component\Console\Input\InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
        ));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Command;

/**
 * Basic lock feature for commands.
 *
 * @author Geoffrey Brier <geoffrey.brier@gmail.com>
 */
trait LockableTrait
{
    /** @var Lock */
    private $lock;

    /**
     * Locks a command.
     *
     * @return bool
     */
    private function lock($name = null, $blocking = false)
    {
        if (!class_exists(\PHPStanVendor\Symfony\Component\Lock\Store\SemaphoreStore::class)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\RuntimeException('To enable the locking feature you must install the symfony/lock component.');
        }

        if (null !== $this->lock) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException('A lock is already in place.');
        }

        if (\PHPStanVendor\Symfony\Component\Lock\Store\SemaphoreStore::isSupported($blocking)) {
            $store = new \PHPStanVendor\Symfony\Component\Lock\Store\SemaphoreStore();
        } else {
            $store = new \PHPStanVendor\Symfony\Component\Lock\Store\FlockStore();
        }

        $this->lock = (new \PHPStanVendor\Symfony\Component\Lock\Factory($store))->createLock($name ?: $this->getName());
        if (!$this->lock->acquire($blocking)) {
            $this->lock = null;

            return false;
        }

        return true;
    }

    /**
     * Releases the command lock if there is one.
     */
    private function release()
    {
        if ($this->lock) {
            $this->lock->release();
            $this->lock = null;
        }
    }
}
<?php

namespace PHPStanVendor\Symfony\Component\Console\CommandLoader;

/**
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
interface CommandLoaderInterface
{
    /**
     * Loads a command.
     *
     * @param string $name
     *
     * @return Command
     *
     * @throws CommandNotFoundException
     */
    public function get($name);

    /**
     * Checks if a command exists.
     *
     * @param string $name
     *
     * @return bool
     */
    public function has($name);

    /**
     * @return string[] All registered command names
     */
    public function getNames();
}
<?php

namespace PHPStanVendor\Symfony\Component\Console\CommandLoader;

/**
 * Loads commands from a PSR-11 container.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
class ContainerCommandLoader implements \PHPStanVendor\Symfony\Component\Console\CommandLoader\CommandLoaderInterface
{
    private $container;
    private $commandMap;

    /**
     * @param ContainerInterface $container  A container from which to load command services
     * @param array              $commandMap An array with command names as keys and service ids as values
     */
    public function __construct(\Psr\Container\ContainerInterface $container, array $commandMap)
    {
        $this->container = $container;
        $this->commandMap = $commandMap;
    }

    /**
     * {@inheritdoc}
     */
    public function get($name)
    {
        if (!$this->has($name)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\CommandNotFoundException(sprintf('Command "%s" does not exist.', $name));
        }

        return $this->container->get($this->commandMap[$name]);
    }

    /**
     * {@inheritdoc}
     */
    public function has($name)
    {
        return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]);
    }

    /**
     * {@inheritdoc}
     */
    public function getNames()
    {
        return array_keys($this->commandMap);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\CommandLoader;

/**
 * A simple command loader using factories to instantiate commands lazily.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
class FactoryCommandLoader implements \PHPStanVendor\Symfony\Component\Console\CommandLoader\CommandLoaderInterface
{
    private $factories;

    /**
     * @param callable[] $factories Indexed by command names
     */
    public function __construct(array $factories)
    {
        $this->factories = $factories;
    }

    /**
     * {@inheritdoc}
     */
    public function has($name)
    {
        return isset($this->factories[$name]);
    }

    /**
     * {@inheritdoc}
     */
    public function get($name)
    {
        if (!isset($this->factories[$name])) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\CommandNotFoundException(sprintf('Command "%s" does not exist.', $name));
        }

        $factory = $this->factories[$name];

        return $factory();
    }

    /**
     * {@inheritdoc}
     */
    public function getNames()
    {
        return array_keys($this->factories);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console;

/**
 * Contains all events dispatched by an Application.
 *
 * @author Francesco Levorato <git@flevour.net>
 */
final class ConsoleEvents
{
    /**
     * The COMMAND event allows you to attach listeners before any command is
     * executed by the console. It also allows you to modify the command, input and output
     * before they are handled to the command.
     *
     * @Event("Symfony\Component\Console\Event\ConsoleCommandEvent")
     */
    const COMMAND = 'console.command';

    /**
     * The TERMINATE event allows you to attach listeners after a command is
     * executed by the console.
     *
     * @Event("Symfony\Component\Console\Event\ConsoleTerminateEvent")
     */
    const TERMINATE = 'console.terminate';

    /**
     * The EXCEPTION event occurs when an uncaught exception appears
     * while executing Command#run().
     *
     * This event allows you to deal with the exception or
     * to modify the thrown exception.
     *
     * @Event("Symfony\Component\Console\Event\ConsoleExceptionEvent")
     *
     * @deprecated The console.exception event is deprecated since version 3.3 and will be removed in 4.0. Use the console.error event instead.
     */
    const EXCEPTION = 'console.exception';

    /**
     * The ERROR event occurs when an uncaught exception or error appears.
     *
     * This event allows you to deal with the exception/error or
     * to modify the thrown exception.
     *
     * @Event("Symfony\Component\Console\Event\ConsoleErrorEvent")
     */
    const ERROR = 'console.error';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\DependencyInjection;

/**
 * Registers console commands.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
class AddConsoleCommandPass implements \PHPStanVendor\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface
{
    private $commandLoaderServiceId;
    private $commandTag;

    public function __construct($commandLoaderServiceId = 'console.command_loader', $commandTag = 'console.command')
    {
        $this->commandLoaderServiceId = $commandLoaderServiceId;
        $this->commandTag = $commandTag;
    }

    public function process(\PHPStanVendor\Symfony\Component\DependencyInjection\ContainerBuilder $container)
    {
        $commandServices = $container->findTaggedServiceIds($this->commandTag, true);
        $lazyCommandMap = array();
        $lazyCommandRefs = array();
        $serviceIds = array();
        $lazyServiceIds = array();

        foreach ($commandServices as $id => $tags) {
            $definition = $container->getDefinition($id);
            $class = $container->getParameterBag()->resolveValue($definition->getClass());

            $commandId = 'console.command.'.strtolower(str_replace('\\', '_', $class));

            if (isset($tags[0]['command'])) {
                $commandName = $tags[0]['command'];
            } else {
                if (!$r = $container->getReflectionClass($class)) {
                    throw new \PHPStanVendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
                }
                if (!$r->isSubclassOf(\PHPStanVendor\Symfony\Component\Console\Command\Command::class)) {
                    throw new \PHPStanVendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, \PHPStanVendor\Symfony\Component\Console\Command\Command::class));
                }
                $commandName = $class::getDefaultName();
            }

            if (null === $commandName) {
                if (isset($serviceIds[$commandId]) || $container->hasAlias($commandId)) {
                    $commandId = $commandId.'_'.$id;
                }
                if (!$definition->isPublic() || $definition->isPrivate()) {
                    $container->setAlias($commandId, $id)->setPublic(true);
                    $id = $commandId;
                }
                $serviceIds[$commandId] = $id;

                continue;
            }

            $serviceIds[$commandId] = $id;
            $lazyServiceIds[$id] = true;
            unset($tags[0]);
            $lazyCommandMap[$commandName] = $id;
            $lazyCommandRefs[$id] = new \PHPStanVendor\Symfony\Component\DependencyInjection\TypedReference($id, $class);
            $aliases = array();

            foreach ($tags as $tag) {
                if (isset($tag['command'])) {
                    $aliases[] = $tag['command'];
                    $lazyCommandMap[$tag['command']] = $id;
                }
            }

            $definition->addMethodCall('setName', array($commandName));

            if ($aliases) {
                $definition->addMethodCall('setAliases', array($aliases));
            }
        }

        $container
            ->register($this->commandLoaderServiceId, \PHPStanVendor\Symfony\Component\Console\CommandLoader\ContainerCommandLoader::class)
            ->setPublic(true)
            ->setArguments(array(\PHPStanVendor\Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap));

        $container->setParameter('console.command.ids', $serviceIds);
        $container->setParameter('console.lazy_command.ids', $lazyServiceIds);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Descriptor;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 *
 * @internal
 */
class ApplicationDescription
{
    const GLOBAL_NAMESPACE = '_global';

    private $application;
    private $namespace;
    private $showHidden;

    /**
     * @var array
     */
    private $namespaces;

    /**
     * @var Command[]
     */
    private $commands;

    /**
     * @var Command[]
     */
    private $aliases;

    /**
     * @param Application $application
     * @param string|null $namespace
     * @param bool        $showHidden
     */
    public function __construct(\PHPStanVendor\Symfony\Component\Console\Application $application, $namespace = null, $showHidden = false)
    {
        $this->application = $application;
        $this->namespace = $namespace;
        $this->showHidden = $showHidden;
    }

    /**
     * @return array
     */
    public function getNamespaces()
    {
        if (null === $this->namespaces) {
            $this->inspectApplication();
        }

        return $this->namespaces;
    }

    /**
     * @return Command[]
     */
    public function getCommands()
    {
        if (null === $this->commands) {
            $this->inspectApplication();
        }

        return $this->commands;
    }

    /**
     * @param string $name
     *
     * @return Command
     *
     * @throws CommandNotFoundException
     */
    public function getCommand($name)
    {
        if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\CommandNotFoundException(sprintf('Command %s does not exist.', $name));
        }

        return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
    }

    private function inspectApplication()
    {
        $this->commands = array();
        $this->namespaces = array();

        $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
        foreach ($this->sortCommands($all) as $namespace => $commands) {
            $names = array();

            /** @var Command $command */
            foreach ($commands as $name => $command) {
                if (!$command->getName() || (!$this->showHidden && $command->isHidden())) {
                    continue;
                }

                if ($command->getName() === $name) {
                    $this->commands[$name] = $command;
                } else {
                    $this->aliases[$name] = $command;
                }

                $names[] = $name;
            }

            $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names);
        }
    }

    /**
     * @return array
     */
    private function sortCommands(array $commands)
    {
        $namespacedCommands = array();
        $globalCommands = array();
        foreach ($commands as $name => $command) {
            $key = $this->application->extractNamespace($name, 1);
            if (!$key) {
                $globalCommands['_global'][$name] = $command;
            } else {
                $namespacedCommands[$key][$name] = $command;
            }
        }
        ksort($namespacedCommands);
        $namespacedCommands = array_merge($globalCommands, $namespacedCommands);

        foreach ($namespacedCommands as &$commandsSet) {
            ksort($commandsSet);
        }
        // unset reference to keep scope clear
        unset($commandsSet);

        return $namespacedCommands;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Descriptor;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 *
 * @internal
 */
abstract class Descriptor implements \PHPStanVendor\Symfony\Component\Console\Descriptor\DescriptorInterface
{
    /**
     * @var OutputInterface
     */
    protected $output;

    /**
     * {@inheritdoc}
     */
    public function describe(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, $object, array $options = array())
    {
        $this->output = $output;

        switch (true) {
            case $object instanceof \PHPStanVendor\Symfony\Component\Console\Input\InputArgument:
                $this->describeInputArgument($object, $options);
                break;
            case $object instanceof \PHPStanVendor\Symfony\Component\Console\Input\InputOption:
                $this->describeInputOption($object, $options);
                break;
            case $object instanceof \PHPStanVendor\Symfony\Component\Console\Input\InputDefinition:
                $this->describeInputDefinition($object, $options);
                break;
            case $object instanceof \PHPStanVendor\Symfony\Component\Console\Command\Command:
                $this->describeCommand($object, $options);
                break;
            case $object instanceof \PHPStanVendor\Symfony\Component\Console\Application:
                $this->describeApplication($object, $options);
                break;
            default:
                throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
        }
    }

    /**
     * Writes content to output.
     *
     * @param string $content
     * @param bool   $decorated
     */
    protected function write($content, $decorated = false)
    {
        $this->output->write($content, false, $decorated ? \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::OUTPUT_NORMAL : \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::OUTPUT_RAW);
    }

    /**
     * Describes an InputArgument instance.
     *
     * @return string|mixed
     */
    abstract protected function describeInputArgument(\PHPStanVendor\Symfony\Component\Console\Input\InputArgument $argument, array $options = array());

    /**
     * Describes an InputOption instance.
     *
     * @return string|mixed
     */
    abstract protected function describeInputOption(\PHPStanVendor\Symfony\Component\Console\Input\InputOption $option, array $options = array());

    /**
     * Describes an InputDefinition instance.
     *
     * @return string|mixed
     */
    abstract protected function describeInputDefinition(\PHPStanVendor\Symfony\Component\Console\Input\InputDefinition $definition, array $options = array());

    /**
     * Describes a Command instance.
     *
     * @return string|mixed
     */
    abstract protected function describeCommand(\PHPStanVendor\Symfony\Component\Console\Command\Command $command, array $options = array());

    /**
     * Describes an Application instance.
     *
     * @return string|mixed
     */
    abstract protected function describeApplication(\PHPStanVendor\Symfony\Component\Console\Application $application, array $options = array());
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Descriptor;

/**
 * Descriptor interface.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
interface DescriptorInterface
{
    /**
     * Describes an InputArgument instance.
     *
     * @param OutputInterface $output
     * @param object          $object
     * @param array           $options
     */
    public function describe(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, $object, array $options = array());
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Descriptor;

/**
 * JSON descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 *
 * @internal
 */
class JsonDescriptor extends \PHPStanVendor\Symfony\Component\Console\Descriptor\Descriptor
{
    /**
     * {@inheritdoc}
     */
    protected function describeInputArgument(\PHPStanVendor\Symfony\Component\Console\Input\InputArgument $argument, array $options = array())
    {
        $this->writeData($this->getInputArgumentData($argument), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputOption(\PHPStanVendor\Symfony\Component\Console\Input\InputOption $option, array $options = array())
    {
        $this->writeData($this->getInputOptionData($option), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputDefinition(\PHPStanVendor\Symfony\Component\Console\Input\InputDefinition $definition, array $options = array())
    {
        $this->writeData($this->getInputDefinitionData($definition), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeCommand(\PHPStanVendor\Symfony\Component\Console\Command\Command $command, array $options = array())
    {
        $this->writeData($this->getCommandData($command), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeApplication(\PHPStanVendor\Symfony\Component\Console\Application $application, array $options = array())
    {
        $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
        $description = new \PHPStanVendor\Symfony\Component\Console\Descriptor\ApplicationDescription($application, $describedNamespace, true);
        $commands = array();

        foreach ($description->getCommands() as $command) {
            $commands[] = $this->getCommandData($command);
        }

        $data = array();
        if ('UNKNOWN' !== $application->getName()) {
            $data['application']['name'] = $application->getName();
            if ('UNKNOWN' !== $application->getVersion()) {
                $data['application']['version'] = $application->getVersion();
            }
        }

        $data['commands'] = $commands;

        if ($describedNamespace) {
            $data['namespace'] = $describedNamespace;
        } else {
            $data['namespaces'] = array_values($description->getNamespaces());
        }

        $this->writeData($data, $options);
    }

    /**
     * Writes data as json.
     *
     * @return array|string
     */
    private function writeData(array $data, array $options)
    {
        $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
    }

    /**
     * @return array
     */
    private function getInputArgumentData(\PHPStanVendor\Symfony\Component\Console\Input\InputArgument $argument)
    {
        return array(
            'name' => $argument->getName(),
            'is_required' => $argument->isRequired(),
            'is_array' => $argument->isArray(),
            'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()),
            'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(),
        );
    }

    /**
     * @return array
     */
    private function getInputOptionData(\PHPStanVendor\Symfony\Component\Console\Input\InputOption $option)
    {
        return array(
            'name' => '--'.$option->getName(),
            'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '',
            'accept_value' => $option->acceptValue(),
            'is_value_required' => $option->isValueRequired(),
            'is_multiple' => $option->isArray(),
            'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
            'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(),
        );
    }

    /**
     * @return array
     */
    private function getInputDefinitionData(\PHPStanVendor\Symfony\Component\Console\Input\InputDefinition $definition)
    {
        $inputArguments = array();
        foreach ($definition->getArguments() as $name => $argument) {
            $inputArguments[$name] = $this->getInputArgumentData($argument);
        }

        $inputOptions = array();
        foreach ($definition->getOptions() as $name => $option) {
            $inputOptions[$name] = $this->getInputOptionData($option);
        }

        return array('arguments' => $inputArguments, 'options' => $inputOptions);
    }

    /**
     * @return array
     */
    private function getCommandData(\PHPStanVendor\Symfony\Component\Console\Command\Command $command)
    {
        $command->getSynopsis();
        $command->mergeApplicationDefinition(false);

        return array(
            'name' => $command->getName(),
            'usage' => array_merge(array($command->getSynopsis()), $command->getUsages(), $command->getAliases()),
            'description' => $command->getDescription(),
            'help' => $command->getProcessedHelp(),
            'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
            'hidden' => $command->isHidden(),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Descriptor;

/**
 * Markdown descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 *
 * @internal
 */
class MarkdownDescriptor extends \PHPStanVendor\Symfony\Component\Console\Descriptor\Descriptor
{
    /**
     * {@inheritdoc}
     */
    public function describe(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, $object, array $options = array())
    {
        $decorated = $output->isDecorated();
        $output->setDecorated(false);

        parent::describe($output, $object, $options);

        $output->setDecorated($decorated);
    }

    /**
     * {@inheritdoc}
     */
    protected function write($content, $decorated = true)
    {
        parent::write($content, $decorated);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputArgument(\PHPStanVendor\Symfony\Component\Console\Input\InputArgument $argument, array $options = array())
    {
        $this->write(
            '#### `'.($argument->getName() ?: '<none>')."`\n\n"
            .($argument->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $argument->getDescription())."\n\n" : '')
            .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
            .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
            .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
        );
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputOption(\PHPStanVendor\Symfony\Component\Console\Input\InputOption $option, array $options = array())
    {
        $name = '--'.$option->getName();
        if ($option->getShortcut()) {
            $name .= '|-'.implode('|-', explode('|', $option->getShortcut())).'';
        }

        $this->write(
            '#### `'.$name.'`'."\n\n"
            .($option->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $option->getDescription())."\n\n" : '')
            .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
            .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
            .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
            .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
        );
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputDefinition(\PHPStanVendor\Symfony\Component\Console\Input\InputDefinition $definition, array $options = array())
    {
        if ($showArguments = count($definition->getArguments()) > 0) {
            $this->write('### Arguments');
            foreach ($definition->getArguments() as $argument) {
                $this->write("\n\n");
                $this->write($this->describeInputArgument($argument));
            }
        }

        if (count($definition->getOptions()) > 0) {
            if ($showArguments) {
                $this->write("\n\n");
            }

            $this->write('### Options');
            foreach ($definition->getOptions() as $option) {
                $this->write("\n\n");
                $this->write($this->describeInputOption($option));
            }
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function describeCommand(\PHPStanVendor\Symfony\Component\Console\Command\Command $command, array $options = array())
    {
        $command->getSynopsis();
        $command->mergeApplicationDefinition(false);

        $this->write(
            '`'.$command->getName()."`\n"
            .str_repeat('-', \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($command->getName()) + 2)."\n\n"
            .($command->getDescription() ? $command->getDescription()."\n\n" : '')
            .'### Usage'."\n\n"
            .array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
                return $carry.'* `'.$usage.'`'."\n";
            })
        );

        if ($help = $command->getProcessedHelp()) {
            $this->write("\n");
            $this->write($help);
        }

        if ($command->getNativeDefinition()) {
            $this->write("\n\n");
            $this->describeInputDefinition($command->getNativeDefinition());
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function describeApplication(\PHPStanVendor\Symfony\Component\Console\Application $application, array $options = array())
    {
        $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
        $description = new \PHPStanVendor\Symfony\Component\Console\Descriptor\ApplicationDescription($application, $describedNamespace);
        $title = $this->getApplicationTitle($application);

        $this->write($title."\n".str_repeat('=', \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($title)));

        foreach ($description->getNamespaces() as $namespace) {
            if (\PHPStanVendor\Symfony\Component\Console\Descriptor\ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
                $this->write("\n\n");
                $this->write('**'.$namespace['id'].':**');
            }

            $this->write("\n\n");
            $this->write(implode("\n", array_map(function ($commandName) use ($description) {
                return sprintf('* [`%s`](#%s)', $commandName, str_replace(':', '', $description->getCommand($commandName)->getName()));
            }, $namespace['commands'])));
        }

        foreach ($description->getCommands() as $command) {
            $this->write("\n\n");
            $this->write($this->describeCommand($command));
        }
    }

    private function getApplicationTitle(\PHPStanVendor\Symfony\Component\Console\Application $application)
    {
        if ('UNKNOWN' !== $application->getName()) {
            if ('UNKNOWN' !== $application->getVersion()) {
                return sprintf('%s %s', $application->getName(), $application->getVersion());
            }

            return $application->getName();
        }

        return 'Console Tool';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Descriptor;

/**
 * Text descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 *
 * @internal
 */
class TextDescriptor extends \PHPStanVendor\Symfony\Component\Console\Descriptor\Descriptor
{
    /**
     * {@inheritdoc}
     */
    protected function describeInputArgument(\PHPStanVendor\Symfony\Component\Console\Input\InputArgument $argument, array $options = array())
    {
        if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
            $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
        } else {
            $default = '';
        }

        $totalWidth = isset($options['total_width']) ? $options['total_width'] : \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($argument->getName());
        $spacingWidth = $totalWidth - strlen($argument->getName());

        $this->writeText(sprintf('  <info>%s</info>  %s%s%s',
            $argument->getName(),
            str_repeat(' ', $spacingWidth),
            // + 4 = 2 spaces before <info>, 2 spaces after </info>
            preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()),
            $default
        ), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputOption(\PHPStanVendor\Symfony\Component\Console\Input\InputOption $option, array $options = array())
    {
        if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
            $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
        } else {
            $default = '';
        }

        $value = '';
        if ($option->acceptValue()) {
            $value = '='.strtoupper($option->getName());

            if ($option->isValueOptional()) {
                $value = '['.$value.']';
            }
        }

        $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions(array($option));
        $synopsis = sprintf('%s%s',
            $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : '    ',
            sprintf('--%s%s', $option->getName(), $value)
        );

        $spacingWidth = $totalWidth - \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($synopsis);

        $this->writeText(sprintf('  <info>%s</info>  %s%s%s%s',
            $synopsis,
            str_repeat(' ', $spacingWidth),
            // + 4 = 2 spaces before <info>, 2 spaces after </info>
            preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()),
            $default,
            $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
        ), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputDefinition(\PHPStanVendor\Symfony\Component\Console\Input\InputDefinition $definition, array $options = array())
    {
        $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
        foreach ($definition->getArguments() as $argument) {
            $totalWidth = max($totalWidth, \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($argument->getName()));
        }

        if ($definition->getArguments()) {
            $this->writeText('<comment>Arguments:</comment>', $options);
            $this->writeText("\n");
            foreach ($definition->getArguments() as $argument) {
                $this->describeInputArgument($argument, array_merge($options, array('total_width' => $totalWidth)));
                $this->writeText("\n");
            }
        }

        if ($definition->getArguments() && $definition->getOptions()) {
            $this->writeText("\n");
        }

        if ($definition->getOptions()) {
            $laterOptions = array();

            $this->writeText('<comment>Options:</comment>', $options);
            foreach ($definition->getOptions() as $option) {
                if (strlen($option->getShortcut()) > 1) {
                    $laterOptions[] = $option;
                    continue;
                }
                $this->writeText("\n");
                $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
            }
            foreach ($laterOptions as $option) {
                $this->writeText("\n");
                $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
            }
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function describeCommand(\PHPStanVendor\Symfony\Component\Console\Command\Command $command, array $options = array())
    {
        $command->getSynopsis(true);
        $command->getSynopsis(false);
        $command->mergeApplicationDefinition(false);

        $this->writeText('<comment>Usage:</comment>', $options);
        foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) {
            $this->writeText("\n");
            $this->writeText('  '.\PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatter::escape($usage), $options);
        }
        $this->writeText("\n");

        $definition = $command->getNativeDefinition();
        if ($definition->getOptions() || $definition->getArguments()) {
            $this->writeText("\n");
            $this->describeInputDefinition($definition, $options);
            $this->writeText("\n");
        }

        if ($help = $command->getProcessedHelp()) {
            $this->writeText("\n");
            $this->writeText('<comment>Help:</comment>', $options);
            $this->writeText("\n");
            $this->writeText('  '.str_replace("\n", "\n  ", $help), $options);
            $this->writeText("\n");
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function describeApplication(\PHPStanVendor\Symfony\Component\Console\Application $application, array $options = array())
    {
        $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
        $description = new \PHPStanVendor\Symfony\Component\Console\Descriptor\ApplicationDescription($application, $describedNamespace);

        if (isset($options['raw_text']) && $options['raw_text']) {
            $width = $this->getColumnWidth($description->getCommands());

            foreach ($description->getCommands() as $command) {
                $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options);
                $this->writeText("\n");
            }
        } else {
            if ('' != $help = $application->getHelp()) {
                $this->writeText("$help\n\n", $options);
            }

            $this->writeText("<comment>Usage:</comment>\n", $options);
            $this->writeText("  command [options] [arguments]\n\n", $options);

            $this->describeInputDefinition(new \PHPStanVendor\Symfony\Component\Console\Input\InputDefinition($application->getDefinition()->getOptions()), $options);

            $this->writeText("\n");
            $this->writeText("\n");

            $commands = $description->getCommands();
            $namespaces = $description->getNamespaces();
            if ($describedNamespace && $namespaces) {
                // make sure all alias commands are included when describing a specific namespace
                $describedNamespaceInfo = reset($namespaces);
                foreach ($describedNamespaceInfo['commands'] as $name) {
                    $commands[$name] = $description->getCommand($name);
                }
            }

            // calculate max. width based on available commands per namespace
            $width = $this->getColumnWidth(call_user_func_array('array_merge', array_map(function ($namespace) use ($commands) {
                return array_intersect($namespace['commands'], array_keys($commands));
            }, $namespaces)));

            if ($describedNamespace) {
                $this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
            } else {
                $this->writeText('<comment>Available commands:</comment>', $options);
            }

            foreach ($namespaces as $namespace) {
                $namespace['commands'] = array_filter($namespace['commands'], function ($name) use ($commands) {
                    return isset($commands[$name]);
                });

                if (!$namespace['commands']) {
                    continue;
                }

                if (!$describedNamespace && \PHPStanVendor\Symfony\Component\Console\Descriptor\ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
                    $this->writeText("\n");
                    $this->writeText(' <comment>'.$namespace['id'].'</comment>', $options);
                }

                foreach ($namespace['commands'] as $name) {
                    $this->writeText("\n");
                    $spacingWidth = $width - \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($name);
                    $command = $commands[$name];
                    $commandAliases = $name === $command->getName() ? $this->getCommandAliasesText($command) : '';
                    $this->writeText(sprintf('  <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $commandAliases.$command->getDescription()), $options);
                }
            }

            $this->writeText("\n");
        }
    }

    /**
     * {@inheritdoc}
     */
    private function writeText($content, array $options = array())
    {
        $this->write(
            isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
            isset($options['raw_output']) ? !$options['raw_output'] : true
        );
    }

    /**
     * Formats command aliases to show them in the command description.
     *
     * @return string
     */
    private function getCommandAliasesText(\PHPStanVendor\Symfony\Component\Console\Command\Command $command)
    {
        $text = '';
        $aliases = $command->getAliases();

        if ($aliases) {
            $text = '['.implode('|', $aliases).'] ';
        }

        return $text;
    }

    /**
     * Formats input option/argument default value.
     *
     * @param mixed $default
     *
     * @return string
     */
    private function formatDefaultValue($default)
    {
        if (INF === $default) {
            return 'INF';
        }

        if (is_string($default)) {
            $default = \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatter::escape($default);
        } elseif (is_array($default)) {
            foreach ($default as $key => $value) {
                if (is_string($value)) {
                    $default[$key] = \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatter::escape($value);
                }
            }
        }

        return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
    }

    /**
     * @param (Command|string)[] $commands
     *
     * @return int
     */
    private function getColumnWidth(array $commands)
    {
        $widths = array();

        foreach ($commands as $command) {
            if ($command instanceof \PHPStanVendor\Symfony\Component\Console\Command\Command) {
                $widths[] = \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($command->getName());
                foreach ($command->getAliases() as $alias) {
                    $widths[] = \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($alias);
                }
            } else {
                $widths[] = \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($command);
            }
        }

        return $widths ? max($widths) + 2 : 0;
    }

    /**
     * @param InputOption[] $options
     *
     * @return int
     */
    private function calculateTotalWidthForOptions(array $options)
    {
        $totalWidth = 0;
        foreach ($options as $option) {
            // "-" + shortcut + ", --" + name
            $nameLength = 1 + max(\PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($option->getShortcut()), 1) + 4 + \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($option->getName());

            if ($option->acceptValue()) {
                $valueLength = 1 + \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($option->getName()); // = + value
                $valueLength += $option->isValueOptional() ? 2 : 0; // [ + ]

                $nameLength += $valueLength;
            }
            $totalWidth = max($totalWidth, $nameLength);
        }

        return $totalWidth;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Descriptor;

/**
 * XML descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 *
 * @internal
 */
class XmlDescriptor extends \PHPStanVendor\Symfony\Component\Console\Descriptor\Descriptor
{
    /**
     * @return \DOMDocument
     */
    public function getInputDefinitionDocument(\PHPStanVendor\Symfony\Component\Console\Input\InputDefinition $definition)
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($definitionXML = $dom->createElement('definition'));

        $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
        foreach ($definition->getArguments() as $argument) {
            $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
        }

        $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
        foreach ($definition->getOptions() as $option) {
            $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
        }

        return $dom;
    }

    /**
     * @return \DOMDocument
     */
    public function getCommandDocument(\PHPStanVendor\Symfony\Component\Console\Command\Command $command)
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($commandXML = $dom->createElement('command'));

        $command->getSynopsis();
        $command->mergeApplicationDefinition(false);

        $commandXML->setAttribute('id', $command->getName());
        $commandXML->setAttribute('name', $command->getName());
        $commandXML->setAttribute('hidden', $command->isHidden() ? 1 : 0);

        $commandXML->appendChild($usagesXML = $dom->createElement('usages'));

        foreach (array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()) as $usage) {
            $usagesXML->appendChild($dom->createElement('usage', $usage));
        }

        $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));

        $commandXML->appendChild($helpXML = $dom->createElement('help'));
        $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));

        $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
        $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));

        return $dom;
    }

    /**
     * @param Application $application
     * @param string|null $namespace
     *
     * @return \DOMDocument
     */
    public function getApplicationDocument(\PHPStanVendor\Symfony\Component\Console\Application $application, $namespace = null)
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($rootXml = $dom->createElement('symfony'));

        if ('UNKNOWN' !== $application->getName()) {
            $rootXml->setAttribute('name', $application->getName());
            if ('UNKNOWN' !== $application->getVersion()) {
                $rootXml->setAttribute('version', $application->getVersion());
            }
        }

        $rootXml->appendChild($commandsXML = $dom->createElement('commands'));

        $description = new \PHPStanVendor\Symfony\Component\Console\Descriptor\ApplicationDescription($application, $namespace, true);

        if ($namespace) {
            $commandsXML->setAttribute('namespace', $namespace);
        }

        foreach ($description->getCommands() as $command) {
            $this->appendDocument($commandsXML, $this->getCommandDocument($command));
        }

        if (!$namespace) {
            $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));

            foreach ($description->getNamespaces() as $namespaceDescription) {
                $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
                $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);

                foreach ($namespaceDescription['commands'] as $name) {
                    $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
                    $commandXML->appendChild($dom->createTextNode($name));
                }
            }
        }

        return $dom;
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputArgument(\PHPStanVendor\Symfony\Component\Console\Input\InputArgument $argument, array $options = array())
    {
        $this->writeDocument($this->getInputArgumentDocument($argument));
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputOption(\PHPStanVendor\Symfony\Component\Console\Input\InputOption $option, array $options = array())
    {
        $this->writeDocument($this->getInputOptionDocument($option));
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputDefinition(\PHPStanVendor\Symfony\Component\Console\Input\InputDefinition $definition, array $options = array())
    {
        $this->writeDocument($this->getInputDefinitionDocument($definition));
    }

    /**
     * {@inheritdoc}
     */
    protected function describeCommand(\PHPStanVendor\Symfony\Component\Console\Command\Command $command, array $options = array())
    {
        $this->writeDocument($this->getCommandDocument($command));
    }

    /**
     * {@inheritdoc}
     */
    protected function describeApplication(\PHPStanVendor\Symfony\Component\Console\Application $application, array $options = array())
    {
        $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null));
    }

    /**
     * Appends document children to parent node.
     */
    private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
    {
        foreach ($importedParent->childNodes as $childNode) {
            $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
        }
    }

    /**
     * Writes DOM document.
     *
     * @return \DOMDocument|string
     */
    private function writeDocument(\DOMDocument $dom)
    {
        $dom->formatOutput = true;
        $this->write($dom->saveXML());
    }

    /**
     * @return \DOMDocument
     */
    private function getInputArgumentDocument(\PHPStanVendor\Symfony\Component\Console\Input\InputArgument $argument)
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');

        $dom->appendChild($objectXML = $dom->createElement('argument'));
        $objectXML->setAttribute('name', $argument->getName());
        $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
        $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
        $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));

        $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
        $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
        foreach ($defaults as $default) {
            $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
            $defaultXML->appendChild($dom->createTextNode($default));
        }

        return $dom;
    }

    /**
     * @return \DOMDocument
     */
    private function getInputOptionDocument(\PHPStanVendor\Symfony\Component\Console\Input\InputOption $option)
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');

        $dom->appendChild($objectXML = $dom->createElement('option'));
        $objectXML->setAttribute('name', '--'.$option->getName());
        $pos = strpos($option->getShortcut(), '|');
        if (false !== $pos) {
            $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
            $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut())));
        } else {
            $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
        }
        $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
        $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
        $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
        $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));

        if ($option->acceptValue()) {
            $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
            $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));

            if (!empty($defaults)) {
                foreach ($defaults as $default) {
                    $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
                    $defaultXML->appendChild($dom->createTextNode($default));
                }
            }
        }

        return $dom;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Event;

/**
 * Allows to do things before the command is executed, like skipping the command or changing the input.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ConsoleCommandEvent extends \PHPStanVendor\Symfony\Component\Console\Event\ConsoleEvent
{
    /**
     * The return code for skipped commands, this will also be passed into the terminate event.
     */
    const RETURN_CODE_DISABLED = 113;

    /**
     * Indicates if the command should be run or skipped.
     */
    private $commandShouldRun = true;

    /**
     * Disables the command, so it won't be run.
     *
     * @return bool
     */
    public function disableCommand()
    {
        return $this->commandShouldRun = false;
    }

    /**
     * Enables the command.
     *
     * @return bool
     */
    public function enableCommand()
    {
        return $this->commandShouldRun = true;
    }

    /**
     * Returns true if the command is runnable, false otherwise.
     *
     * @return bool
     */
    public function commandShouldRun()
    {
        return $this->commandShouldRun;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Event;

/**
 * Allows to handle throwables thrown while running a command.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class ConsoleErrorEvent extends \PHPStanVendor\Symfony\Component\Console\Event\ConsoleEvent
{
    private $error;
    private $exitCode;

    public function __construct(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, $error, \PHPStanVendor\Symfony\Component\Console\Command\Command $command = null)
    {
        parent::__construct($command, $input, $output);

        $this->setError($error);
    }

    /**
     * Returns the thrown error/exception.
     *
     * @return \Throwable
     */
    public function getError()
    {
        return $this->error;
    }

    /**
     * Replaces the thrown error/exception.
     *
     * @param \Throwable $error
     */
    public function setError($error)
    {
        if (!$error instanceof \Throwable && !$error instanceof \Exception) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('The error passed to ConsoleErrorEvent must be an instance of \Throwable or \Exception, "%s" was passed instead.', is_object($error) ? get_class($error) : gettype($error)));
        }

        $this->error = $error;
    }

    /**
     * Sets the exit code.
     *
     * @param int $exitCode The command exit code
     */
    public function setExitCode($exitCode)
    {
        $this->exitCode = (int) $exitCode;

        $r = new \ReflectionProperty($this->error, 'code');
        $r->setAccessible(true);
        $r->setValue($this->error, $this->exitCode);
    }

    /**
     * Gets the exit code.
     *
     * @return int The command exit code
     */
    public function getExitCode()
    {
        return null !== $this->exitCode ? $this->exitCode : (is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Event;

/**
 * Allows to inspect input and output of a command.
 *
 * @author Francesco Levorato <git@flevour.net>
 */
class ConsoleEvent extends \PHPStanVendor\Symfony\Component\EventDispatcher\Event
{
    protected $command;

    private $input;
    private $output;

    public function __construct(\PHPStanVendor\Symfony\Component\Console\Command\Command $command = null, \PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output)
    {
        $this->command = $command;
        $this->input = $input;
        $this->output = $output;
    }

    /**
     * Gets the command that is executed.
     *
     * @return Command|null A Command instance
     */
    public function getCommand()
    {
        return $this->command;
    }

    /**
     * Gets the input instance.
     *
     * @return InputInterface An InputInterface instance
     */
    public function getInput()
    {
        return $this->input;
    }

    /**
     * Gets the output instance.
     *
     * @return OutputInterface An OutputInterface instance
     */
    public function getOutput()
    {
        return $this->output;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Event;

@trigger_error(sprintf('The "%s" class is deprecated since Symfony 3.3 and will be removed in 4.0. Use the ConsoleErrorEvent instead.', \PHPStanVendor\Symfony\Component\Console\Event\ConsoleExceptionEvent::class), E_USER_DEPRECATED);

/**
 * Allows to handle exception thrown in a command.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @deprecated since version 3.3, to be removed in 4.0. Use ConsoleErrorEvent instead.
 */
class ConsoleExceptionEvent extends \PHPStanVendor\Symfony\Component\Console\Event\ConsoleEvent
{
    private $exception;
    private $exitCode;

    public function __construct(\PHPStanVendor\Symfony\Component\Console\Command\Command $command, \PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, \Exception $exception, $exitCode)
    {
        parent::__construct($command, $input, $output);

        $this->setException($exception);
        $this->exitCode = (int) $exitCode;
    }

    /**
     * Returns the thrown exception.
     *
     * @return \Exception The thrown exception
     */
    public function getException()
    {
        return $this->exception;
    }

    /**
     * Replaces the thrown exception.
     *
     * This exception will be thrown if no response is set in the event.
     *
     * @param \Exception $exception The thrown exception
     */
    public function setException(\Exception $exception)
    {
        $this->exception = $exception;
    }

    /**
     * Gets the exit code.
     *
     * @return int The command exit code
     */
    public function getExitCode()
    {
        return $this->exitCode;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Event;

/**
 * Allows to manipulate the exit code of a command after its execution.
 *
 * @author Francesco Levorato <git@flevour.net>
 */
class ConsoleTerminateEvent extends \PHPStanVendor\Symfony\Component\Console\Event\ConsoleEvent
{
    /**
     * The exit code of the command.
     *
     * @var int
     */
    private $exitCode;

    public function __construct(\PHPStanVendor\Symfony\Component\Console\Command\Command $command, \PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, $exitCode)
    {
        parent::__construct($command, $input, $output);

        $this->setExitCode($exitCode);
    }

    /**
     * Sets the exit code.
     *
     * @param int $exitCode The command exit code
     */
    public function setExitCode($exitCode)
    {
        $this->exitCode = (int) $exitCode;
    }

    /**
     * Gets the exit code.
     *
     * @return int The command exit code
     */
    public function getExitCode()
    {
        return $this->exitCode;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\EventListener;

/**
 * @author James Halsall <james.t.halsall@googlemail.com>
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
class ErrorListener implements \PHPStanVendor\Symfony\Component\EventDispatcher\EventSubscriberInterface
{
    private $logger;

    public function __construct(\Psr\Log\LoggerInterface $logger = null)
    {
        $this->logger = $logger;
    }

    public function onConsoleError(\PHPStanVendor\Symfony\Component\Console\Event\ConsoleErrorEvent $event)
    {
        if (null === $this->logger) {
            return;
        }

        $error = $event->getError();

        if (!$inputString = $this->getInputString($event)) {
            return $this->logger->error('An error occurred while using the console. Message: "{message}"', array('error' => $error, 'message' => $error->getMessage()));
        }

        $this->logger->error('Error thrown while running command "{command}". Message: "{message}"', array('error' => $error, 'command' => $inputString, 'message' => $error->getMessage()));
    }

    public function onConsoleTerminate(\PHPStanVendor\Symfony\Component\Console\Event\ConsoleTerminateEvent $event)
    {
        if (null === $this->logger) {
            return;
        }

        $exitCode = $event->getExitCode();

        if (0 === $exitCode) {
            return;
        }

        if (!$inputString = $this->getInputString($event)) {
            return $this->logger->debug('The console exited with code "{code}"', array('code' => $exitCode));
        }

        $this->logger->debug('Command "{command}" exited with code "{code}"', array('command' => $inputString, 'code' => $exitCode));
    }

    public static function getSubscribedEvents()
    {
        return array(
            \PHPStanVendor\Symfony\Component\Console\ConsoleEvents::ERROR => array('onConsoleError', -128),
            \PHPStanVendor\Symfony\Component\Console\ConsoleEvents::TERMINATE => array('onConsoleTerminate', -128),
        );
    }

    private static function getInputString(\PHPStanVendor\Symfony\Component\Console\Event\ConsoleEvent $event)
    {
        $commandName = $event->getCommand() ? $event->getCommand()->getName() : null;
        $input = $event->getInput();

        if (method_exists($input, '__toString')) {
            if ($commandName) {
                return str_replace(array("'$commandName'", "\"$commandName\""), $commandName, (string) $input);
            }

            return (string) $input;
        }

        return $commandName;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Exception;

/**
 * Represents an incorrect command name typed in the console.
 *
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class CommandNotFoundException extends \InvalidArgumentException implements \PHPStanVendor\Symfony\Component\Console\Exception\ExceptionInterface
{
    private $alternatives;

    /**
     * @param string     $message      Exception message to throw
     * @param array      $alternatives List of similar defined names
     * @param int        $code         Exception code
     * @param \Exception $previous     Previous exception used for the exception chaining
     */
    public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null)
    {
        parent::__construct($message, $code, $previous);

        $this->alternatives = $alternatives;
    }

    /**
     * @return array A list of similar defined names
     */
    public function getAlternatives()
    {
        return $this->alternatives;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Exception;

/**
 * ExceptionInterface.
 *
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
interface ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Exception;

/**
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class InvalidArgumentException extends \InvalidArgumentException implements \PHPStanVendor\Symfony\Component\Console\Exception\ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Exception;

/**
 * Represents an incorrect option name typed in the console.
 *
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class InvalidOptionException extends \InvalidArgumentException implements \PHPStanVendor\Symfony\Component\Console\Exception\ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Exception;

/**
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class LogicException extends \LogicException implements \PHPStanVendor\Symfony\Component\Console\Exception\ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Exception;

/**
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class RuntimeException extends \RuntimeException implements \PHPStanVendor\Symfony\Component\Console\Exception\ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Formatter;

/**
 * Formatter class for console output.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
class OutputFormatter implements \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface
{
    private $decorated;
    private $styles = array();
    private $styleStack;

    /**
     * Escapes "<" special char in given text.
     *
     * @param string $text Text to escape
     *
     * @return string Escaped text
     */
    public static function escape($text)
    {
        $text = preg_replace('/([^\\\\]?)</', '$1\\<', $text);

        return self::escapeTrailingBackslash($text);
    }

    /**
     * Escapes trailing "\" in given text.
     *
     * @param string $text Text to escape
     *
     * @return string Escaped text
     *
     * @internal
     */
    public static function escapeTrailingBackslash($text)
    {
        if ('\\' === substr($text, -1)) {
            $len = strlen($text);
            $text = rtrim($text, '\\');
            $text = str_replace("\0", '', $text);
            $text .= str_repeat("\0", $len - strlen($text));
        }

        return $text;
    }

    /**
     * Initializes console output formatter.
     *
     * @param bool                            $decorated Whether this formatter should actually decorate strings
     * @param OutputFormatterStyleInterface[] $styles    Array of "name => FormatterStyle" instances
     */
    public function __construct($decorated = false, array $styles = array())
    {
        $this->decorated = (bool) $decorated;

        $this->setStyle('error', new \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterStyle('white', 'red'));
        $this->setStyle('info', new \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterStyle('green'));
        $this->setStyle('comment', new \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterStyle('yellow'));
        $this->setStyle('question', new \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterStyle('black', 'cyan'));

        foreach ($styles as $name => $style) {
            $this->setStyle($name, $style);
        }

        $this->styleStack = new \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterStyleStack();
    }

    /**
     * {@inheritdoc}
     */
    public function setDecorated($decorated)
    {
        $this->decorated = (bool) $decorated;
    }

    /**
     * {@inheritdoc}
     */
    public function isDecorated()
    {
        return $this->decorated;
    }

    /**
     * {@inheritdoc}
     */
    public function setStyle($name, \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface $style)
    {
        $this->styles[strtolower($name)] = $style;
    }

    /**
     * {@inheritdoc}
     */
    public function hasStyle($name)
    {
        return isset($this->styles[strtolower($name)]);
    }

    /**
     * {@inheritdoc}
     */
    public function getStyle($name)
    {
        if (!$this->hasStyle($name)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('Undefined style: %s', $name));
        }

        return $this->styles[strtolower($name)];
    }

    /**
     * {@inheritdoc}
     */
    public function format($message)
    {
        $message = (string) $message;
        $offset = 0;
        $output = '';
        $tagRegex = '[a-z][a-z0-9,_=;-]*+';
        preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
        foreach ($matches[0] as $i => $match) {
            $pos = $match[1];
            $text = $match[0];

            if (0 != $pos && '\\' == $message[$pos - 1]) {
                continue;
            }

            // add the text up to the next tag
            $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
            $offset = $pos + strlen($text);

            // opening tag?
            if ($open = '/' != $text[1]) {
                $tag = $matches[1][$i][0];
            } else {
                $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : '';
            }

            if (!$open && !$tag) {
                // </>
                $this->styleStack->pop();
            } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
                $output .= $this->applyCurrentStyle($text);
            } elseif ($open) {
                $this->styleStack->push($style);
            } else {
                $this->styleStack->pop($style);
            }
        }

        $output .= $this->applyCurrentStyle(substr($message, $offset));

        if (false !== strpos($output, "\0")) {
            return strtr($output, array("\0" => '\\', '\\<' => '<'));
        }

        return str_replace('\\<', '<', $output);
    }

    /**
     * @return OutputFormatterStyleStack
     */
    public function getStyleStack()
    {
        return $this->styleStack;
    }

    /**
     * Tries to create new style instance from string.
     *
     * @param string $string
     *
     * @return OutputFormatterStyle|false false if string is not format string
     */
    private function createStyleFromString($string)
    {
        if (isset($this->styles[$string])) {
            return $this->styles[$string];
        }

        if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, PREG_SET_ORDER)) {
            return false;
        }

        $style = new \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterStyle();
        foreach ($matches as $match) {
            array_shift($match);

            if ('fg' == $match[0]) {
                $style->setForeground($match[1]);
            } elseif ('bg' == $match[0]) {
                $style->setBackground($match[1]);
            } elseif ('options' === $match[0]) {
                preg_match_all('([^,;]+)', $match[1], $options);
                $options = array_shift($options);
                foreach ($options as $option) {
                    try {
                        $style->setOption($option);
                    } catch (\InvalidArgumentException $e) {
                        @trigger_error(sprintf('Unknown style options are deprecated since Symfony 3.2 and will be removed in 4.0. Exception "%s".', $e->getMessage()), E_USER_DEPRECATED);

                        return false;
                    }
                }
            } else {
                return false;
            }
        }

        return $style;
    }

    /**
     * Applies current style from stack to text, if must be applied.
     *
     * @param string $text Input text
     *
     * @return string Styled text
     */
    private function applyCurrentStyle($text)
    {
        return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Formatter;

/**
 * Formatter interface for console output.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
interface OutputFormatterInterface
{
    /**
     * Sets the decorated flag.
     *
     * @param bool $decorated Whether to decorate the messages or not
     */
    public function setDecorated($decorated);

    /**
     * Gets the decorated flag.
     *
     * @return bool true if the output will decorate messages, false otherwise
     */
    public function isDecorated();

    /**
     * Sets a new style.
     *
     * @param string                        $name  The style name
     * @param OutputFormatterStyleInterface $style The style instance
     */
    public function setStyle($name, \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface $style);

    /**
     * Checks if output formatter has style with specified name.
     *
     * @param string $name
     *
     * @return bool
     */
    public function hasStyle($name);

    /**
     * Gets style options from style with specified name.
     *
     * @param string $name
     *
     * @return OutputFormatterStyleInterface
     *
     * @throws \InvalidArgumentException When style isn't defined
     */
    public function getStyle($name);

    /**
     * Formats a message according to the given styles.
     *
     * @param string $message The message to style
     *
     * @return string The styled message
     */
    public function format($message);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Formatter;

/**
 * Formatter style class for defining styles.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
class OutputFormatterStyle implements \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface
{
    private static $availableForegroundColors = array(
        'black' => array('set' => 30, 'unset' => 39),
        'red' => array('set' => 31, 'unset' => 39),
        'green' => array('set' => 32, 'unset' => 39),
        'yellow' => array('set' => 33, 'unset' => 39),
        'blue' => array('set' => 34, 'unset' => 39),
        'magenta' => array('set' => 35, 'unset' => 39),
        'cyan' => array('set' => 36, 'unset' => 39),
        'white' => array('set' => 37, 'unset' => 39),
        'default' => array('set' => 39, 'unset' => 39),
    );
    private static $availableBackgroundColors = array(
        'black' => array('set' => 40, 'unset' => 49),
        'red' => array('set' => 41, 'unset' => 49),
        'green' => array('set' => 42, 'unset' => 49),
        'yellow' => array('set' => 43, 'unset' => 49),
        'blue' => array('set' => 44, 'unset' => 49),
        'magenta' => array('set' => 45, 'unset' => 49),
        'cyan' => array('set' => 46, 'unset' => 49),
        'white' => array('set' => 47, 'unset' => 49),
        'default' => array('set' => 49, 'unset' => 49),
    );
    private static $availableOptions = array(
        'bold' => array('set' => 1, 'unset' => 22),
        'underscore' => array('set' => 4, 'unset' => 24),
        'blink' => array('set' => 5, 'unset' => 25),
        'reverse' => array('set' => 7, 'unset' => 27),
        'conceal' => array('set' => 8, 'unset' => 28),
    );

    private $foreground;
    private $background;
    private $options = array();

    /**
     * Initializes output formatter style.
     *
     * @param string|null $foreground The style foreground color name
     * @param string|null $background The style background color name
     * @param array       $options    The style options
     */
    public function __construct($foreground = null, $background = null, array $options = array())
    {
        if (null !== $foreground) {
            $this->setForeground($foreground);
        }
        if (null !== $background) {
            $this->setBackground($background);
        }
        if (count($options)) {
            $this->setOptions($options);
        }
    }

    /**
     * Sets style foreground color.
     *
     * @param string|null $color The color name
     *
     * @throws InvalidArgumentException When the color name isn't defined
     */
    public function setForeground($color = null)
    {
        if (null === $color) {
            $this->foreground = null;

            return;
        }

        if (!isset(static::$availableForegroundColors[$color])) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf(
                'Invalid foreground color specified: "%s". Expected one of (%s)',
                $color,
                implode(', ', array_keys(static::$availableForegroundColors))
            ));
        }

        $this->foreground = static::$availableForegroundColors[$color];
    }

    /**
     * Sets style background color.
     *
     * @param string|null $color The color name
     *
     * @throws InvalidArgumentException When the color name isn't defined
     */
    public function setBackground($color = null)
    {
        if (null === $color) {
            $this->background = null;

            return;
        }

        if (!isset(static::$availableBackgroundColors[$color])) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf(
                'Invalid background color specified: "%s". Expected one of (%s)',
                $color,
                implode(', ', array_keys(static::$availableBackgroundColors))
            ));
        }

        $this->background = static::$availableBackgroundColors[$color];
    }

    /**
     * Sets some specific style option.
     *
     * @param string $option The option name
     *
     * @throws InvalidArgumentException When the option name isn't defined
     */
    public function setOption($option)
    {
        if (!isset(static::$availableOptions[$option])) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf(
                'Invalid option specified: "%s". Expected one of (%s)',
                $option,
                implode(', ', array_keys(static::$availableOptions))
            ));
        }

        if (!in_array(static::$availableOptions[$option], $this->options)) {
            $this->options[] = static::$availableOptions[$option];
        }
    }

    /**
     * Unsets some specific style option.
     *
     * @param string $option The option name
     *
     * @throws InvalidArgumentException When the option name isn't defined
     */
    public function unsetOption($option)
    {
        if (!isset(static::$availableOptions[$option])) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf(
                'Invalid option specified: "%s". Expected one of (%s)',
                $option,
                implode(', ', array_keys(static::$availableOptions))
            ));
        }

        $pos = array_search(static::$availableOptions[$option], $this->options);
        if (false !== $pos) {
            unset($this->options[$pos]);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function setOptions(array $options)
    {
        $this->options = array();

        foreach ($options as $option) {
            $this->setOption($option);
        }
    }

    /**
     * Applies the style to a given text.
     *
     * @param string $text The text to style
     *
     * @return string
     */
    public function apply($text)
    {
        $setCodes = array();
        $unsetCodes = array();

        if (null !== $this->foreground) {
            $setCodes[] = $this->foreground['set'];
            $unsetCodes[] = $this->foreground['unset'];
        }
        if (null !== $this->background) {
            $setCodes[] = $this->background['set'];
            $unsetCodes[] = $this->background['unset'];
        }
        if (count($this->options)) {
            foreach ($this->options as $option) {
                $setCodes[] = $option['set'];
                $unsetCodes[] = $option['unset'];
            }
        }

        if (0 === count($setCodes)) {
            return $text;
        }

        return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Formatter;

/**
 * Formatter style interface for defining styles.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
interface OutputFormatterStyleInterface
{
    /**
     * Sets style foreground color.
     *
     * @param string $color The color name
     */
    public function setForeground($color = null);

    /**
     * Sets style background color.
     *
     * @param string $color The color name
     */
    public function setBackground($color = null);

    /**
     * Sets some specific style option.
     *
     * @param string $option The option name
     */
    public function setOption($option);

    /**
     * Unsets some specific style option.
     *
     * @param string $option The option name
     */
    public function unsetOption($option);

    /**
     * Sets multiple style options at once.
     */
    public function setOptions(array $options);

    /**
     * Applies the style to a given text.
     *
     * @param string $text The text to style
     *
     * @return string
     */
    public function apply($text);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Formatter;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class OutputFormatterStyleStack
{
    /**
     * @var OutputFormatterStyleInterface[]
     */
    private $styles;

    private $emptyStyle;

    public function __construct(\PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface $emptyStyle = null)
    {
        $this->emptyStyle = $emptyStyle ?: new \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterStyle();
        $this->reset();
    }

    /**
     * Resets stack (ie. empty internal arrays).
     */
    public function reset()
    {
        $this->styles = array();
    }

    /**
     * Pushes a style in the stack.
     */
    public function push(\PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface $style)
    {
        $this->styles[] = $style;
    }

    /**
     * Pops a style from the stack.
     *
     * @return OutputFormatterStyleInterface
     *
     * @throws InvalidArgumentException When style tags incorrectly nested
     */
    public function pop(\PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface $style = null)
    {
        if (empty($this->styles)) {
            return $this->emptyStyle;
        }

        if (null === $style) {
            return array_pop($this->styles);
        }

        foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
            if ($style->apply('') === $stackedStyle->apply('')) {
                $this->styles = array_slice($this->styles, 0, $index);

                return $stackedStyle;
            }
        }

        throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException('Incorrectly nested style tag found.');
    }

    /**
     * Computes current style with stacks top codes.
     *
     * @return OutputFormatterStyle
     */
    public function getCurrent()
    {
        if (empty($this->styles)) {
            return $this->emptyStyle;
        }

        return $this->styles[count($this->styles) - 1];
    }

    /**
     * @return $this
     */
    public function setEmptyStyle(\PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface $emptyStyle)
    {
        $this->emptyStyle = $emptyStyle;

        return $this;
    }

    /**
     * @return OutputFormatterStyleInterface
     */
    public function getEmptyStyle()
    {
        return $this->emptyStyle;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Helper;

/**
 * Helps outputting debug information when running an external program from a command.
 *
 * An external program can be a Process, an HTTP request, or anything else.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DebugFormatterHelper extends \PHPStanVendor\Symfony\Component\Console\Helper\Helper
{
    private $colors = array('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default');
    private $started = array();
    private $count = -1;

    /**
     * Starts a debug formatting session.
     *
     * @param string $id      The id of the formatting session
     * @param string $message The message to display
     * @param string $prefix  The prefix to use
     *
     * @return string
     */
    public function start($id, $message, $prefix = 'RUN')
    {
        $this->started[$id] = array('border' => ++$this->count % count($this->colors));

        return sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message);
    }

    /**
     * Adds progress to a formatting session.
     *
     * @param string $id          The id of the formatting session
     * @param string $buffer      The message to display
     * @param bool   $error       Whether to consider the buffer as error
     * @param string $prefix      The prefix for output
     * @param string $errorPrefix The prefix for error output
     *
     * @return string
     */
    public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPrefix = 'ERR')
    {
        $message = '';

        if ($error) {
            if (isset($this->started[$id]['out'])) {
                $message .= "\n";
                unset($this->started[$id]['out']);
            }
            if (!isset($this->started[$id]['err'])) {
                $message .= sprintf('%s<bg=red;fg=white> %s </> ', $this->getBorder($id), $errorPrefix);
                $this->started[$id]['err'] = true;
            }

            $message .= str_replace("\n", sprintf("\n%s<bg=red;fg=white> %s </> ", $this->getBorder($id), $errorPrefix), $buffer);
        } else {
            if (isset($this->started[$id]['err'])) {
                $message .= "\n";
                unset($this->started[$id]['err']);
            }
            if (!isset($this->started[$id]['out'])) {
                $message .= sprintf('%s<bg=green;fg=white> %s </> ', $this->getBorder($id), $prefix);
                $this->started[$id]['out'] = true;
            }

            $message .= str_replace("\n", sprintf("\n%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix), $buffer);
        }

        return $message;
    }

    /**
     * Stops a formatting session.
     *
     * @param string $id         The id of the formatting session
     * @param string $message    The message to display
     * @param bool   $successful Whether to consider the result as success
     * @param string $prefix     The prefix for the end output
     *
     * @return string
     */
    public function stop($id, $message, $successful, $prefix = 'RES')
    {
        $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';

        if ($successful) {
            return sprintf("%s%s<bg=green;fg=white> %s </> <fg=green>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
        }

        $message = sprintf("%s%s<bg=red;fg=white> %s </> <fg=red>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);

        unset($this->started[$id]['out'], $this->started[$id]['err']);

        return $message;
    }

    /**
     * @param string $id The id of the formatting session
     *
     * @return string
     */
    private function getBorder($id)
    {
        return sprintf('<bg=%s> </>', $this->colors[$this->started[$id]['border']]);
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'debug_formatter';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Helper;

/**
 * This class adds helper method to describe objects in various formats.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class DescriptorHelper extends \PHPStanVendor\Symfony\Component\Console\Helper\Helper
{
    /**
     * @var DescriptorInterface[]
     */
    private $descriptors = array();

    public function __construct()
    {
        $this
            ->register('txt', new \PHPStanVendor\Symfony\Component\Console\Descriptor\TextDescriptor())
            ->register('xml', new \PHPStanVendor\Symfony\Component\Console\Descriptor\XmlDescriptor())
            ->register('json', new \PHPStanVendor\Symfony\Component\Console\Descriptor\JsonDescriptor())
            ->register('md', new \PHPStanVendor\Symfony\Component\Console\Descriptor\MarkdownDescriptor())
        ;
    }

    /**
     * Describes an object if supported.
     *
     * Available options are:
     * * format: string, the output format name
     * * raw_text: boolean, sets output type as raw
     *
     * @param OutputInterface $output
     * @param object          $object
     * @param array           $options
     *
     * @throws InvalidArgumentException when the given format is not supported
     */
    public function describe(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, $object, array $options = array())
    {
        $options = array_merge(array(
            'raw_text' => false,
            'format' => 'txt',
        ), $options);

        if (!isset($this->descriptors[$options['format']])) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
        }

        $descriptor = $this->descriptors[$options['format']];
        $descriptor->describe($output, $object, $options);
    }

    /**
     * Registers a descriptor.
     *
     * @param string              $format
     * @param DescriptorInterface $descriptor
     *
     * @return $this
     */
    public function register($format, \PHPStanVendor\Symfony\Component\Console\Descriptor\DescriptorInterface $descriptor)
    {
        $this->descriptors[$format] = $descriptor;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'descriptor';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Helper;

/**
 * The Formatter class provides helpers to format messages.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FormatterHelper extends \PHPStanVendor\Symfony\Component\Console\Helper\Helper
{
    /**
     * Formats a message within a section.
     *
     * @param string $section The section name
     * @param string $message The message
     * @param string $style   The style to apply to the section
     *
     * @return string The format section
     */
    public function formatSection($section, $message, $style = 'info')
    {
        return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
    }

    /**
     * Formats a message as a block of text.
     *
     * @param string|array $messages The message to write in the block
     * @param string       $style    The style to apply to the whole block
     * @param bool         $large    Whether to return a large block
     *
     * @return string The formatter message
     */
    public function formatBlock($messages, $style, $large = false)
    {
        if (!is_array($messages)) {
            $messages = array($messages);
        }

        $len = 0;
        $lines = array();
        foreach ($messages as $message) {
            $message = \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatter::escape($message);
            $lines[] = sprintf($large ? '  %s  ' : ' %s ', $message);
            $len = max($this->strlen($message) + ($large ? 4 : 2), $len);
        }

        $messages = $large ? array(str_repeat(' ', $len)) : array();
        for ($i = 0; isset($lines[$i]); ++$i) {
            $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i]));
        }
        if ($large) {
            $messages[] = str_repeat(' ', $len);
        }

        for ($i = 0; isset($messages[$i]); ++$i) {
            $messages[$i] = sprintf('<%s>%s</%s>', $style, $messages[$i], $style);
        }

        return implode("\n", $messages);
    }

    /**
     * Truncates a message to the given length.
     *
     * @param string $message
     * @param int    $length
     * @param string $suffix
     *
     * @return string
     */
    public function truncate($message, $length, $suffix = '...')
    {
        $computedLength = $length - $this->strlen($suffix);

        if ($computedLength > $this->strlen($message)) {
            return $message;
        }

        if (false === $encoding = mb_detect_encoding($message, null, true)) {
            return substr($message, 0, $length).$suffix;
        }

        return mb_substr($message, 0, $length, $encoding).$suffix;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'formatter';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Helper;

/**
 * Helper is the base class for all helper classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Helper implements \PHPStanVendor\Symfony\Component\Console\Helper\HelperInterface
{
    protected $helperSet = null;

    /**
     * {@inheritdoc}
     */
    public function setHelperSet(\PHPStanVendor\Symfony\Component\Console\Helper\HelperSet $helperSet = null)
    {
        $this->helperSet = $helperSet;
    }

    /**
     * {@inheritdoc}
     */
    public function getHelperSet()
    {
        return $this->helperSet;
    }

    /**
     * Returns the length of a string, using mb_strwidth if it is available.
     *
     * @param string $string The string to check its length
     *
     * @return int The length of the string
     */
    public static function strlen($string)
    {
        if (false === $encoding = mb_detect_encoding($string, null, true)) {
            return strlen($string);
        }

        return mb_strwidth($string, $encoding);
    }

    /**
     * Returns the subset of a string, using mb_substr if it is available.
     *
     * @param string   $string String to subset
     * @param int      $from   Start offset
     * @param int|null $length Length to read
     *
     * @return string The string subset
     */
    public static function substr($string, $from, $length = null)
    {
        if (false === $encoding = mb_detect_encoding($string, null, true)) {
            return substr($string, $from, $length);
        }

        return mb_substr($string, $from, $length, $encoding);
    }

    public static function formatTime($secs)
    {
        static $timeFormats = array(
            array(0, '< 1 sec'),
            array(1, '1 sec'),
            array(2, 'secs', 1),
            array(60, '1 min'),
            array(120, 'mins', 60),
            array(3600, '1 hr'),
            array(7200, 'hrs', 3600),
            array(86400, '1 day'),
            array(172800, 'days', 86400),
        );

        foreach ($timeFormats as $index => $format) {
            if ($secs >= $format[0]) {
                if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0])
                    || $index == count($timeFormats) - 1
                ) {
                    if (2 == count($format)) {
                        return $format[1];
                    }

                    return floor($secs / $format[2]).' '.$format[1];
                }
            }
        }
    }

    public static function formatMemory($memory)
    {
        if ($memory >= 1024 * 1024 * 1024) {
            return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
        }

        if ($memory >= 1024 * 1024) {
            return sprintf('%.1f MiB', $memory / 1024 / 1024);
        }

        if ($memory >= 1024) {
            return sprintf('%d KiB', $memory / 1024);
        }

        return sprintf('%d B', $memory);
    }

    public static function strlenWithoutDecoration(\PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter, $string)
    {
        return self::strlen(self::removeDecoration($formatter, $string));
    }

    public static function removeDecoration(\PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter, $string)
    {
        $isDecorated = $formatter->isDecorated();
        $formatter->setDecorated(false);
        // remove <...> formatting
        $string = $formatter->format($string);
        // remove already formatted characters
        $string = preg_replace("/\033\[[^m]*m/", '', $string);
        $formatter->setDecorated($isDecorated);

        return $string;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Helper;

/**
 * HelperInterface is the interface all helpers must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface HelperInterface
{
    /**
     * Sets the helper set associated with this helper.
     */
    public function setHelperSet(\PHPStanVendor\Symfony\Component\Console\Helper\HelperSet $helperSet = null);

    /**
     * Gets the helper set associated with this helper.
     *
     * @return HelperSet A HelperSet instance
     */
    public function getHelperSet();

    /**
     * Returns the canonical name of this helper.
     *
     * @return string The canonical name
     */
    public function getName();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Helper;

/**
 * HelperSet represents a set of helpers to be used with a command.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HelperSet implements \IteratorAggregate
{
    /**
     * @var Helper[]
     */
    private $helpers = array();
    private $command;

    /**
     * @param Helper[] $helpers An array of helper
     */
    public function __construct(array $helpers = array())
    {
        foreach ($helpers as $alias => $helper) {
            $this->set($helper, is_int($alias) ? null : $alias);
        }
    }

    /**
     * Sets a helper.
     *
     * @param HelperInterface $helper The helper instance
     * @param string          $alias  An alias
     */
    public function set(\PHPStanVendor\Symfony\Component\Console\Helper\HelperInterface $helper, $alias = null)
    {
        $this->helpers[$helper->getName()] = $helper;
        if (null !== $alias) {
            $this->helpers[$alias] = $helper;
        }

        $helper->setHelperSet($this);
    }

    /**
     * Returns true if the helper if defined.
     *
     * @param string $name The helper name
     *
     * @return bool true if the helper is defined, false otherwise
     */
    public function has($name)
    {
        return isset($this->helpers[$name]);
    }

    /**
     * Gets a helper value.
     *
     * @param string $name The helper name
     *
     * @return HelperInterface The helper instance
     *
     * @throws InvalidArgumentException if the helper is not defined
     */
    public function get($name)
    {
        if (!$this->has($name)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
        }

        return $this->helpers[$name];
    }

    public function setCommand(\PHPStanVendor\Symfony\Component\Console\Command\Command $command = null)
    {
        $this->command = $command;
    }

    /**
     * Gets the command associated with this helper set.
     *
     * @return Command A Command instance
     */
    public function getCommand()
    {
        return $this->command;
    }

    /**
     * @return Helper[]
     */
    public function getIterator()
    {
        return new \ArrayIterator($this->helpers);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Helper;

/**
 * An implementation of InputAwareInterface for Helpers.
 *
 * @author Wouter J <waldio.webdesign@gmail.com>
 */
abstract class InputAwareHelper extends \PHPStanVendor\Symfony\Component\Console\Helper\Helper implements \PHPStanVendor\Symfony\Component\Console\Input\InputAwareInterface
{
    protected $input;

    /**
     * {@inheritdoc}
     */
    public function setInput(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input)
    {
        $this->input = $input;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Helper;

/**
 * The ProcessHelper class provides helpers to run external processes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ProcessHelper extends \PHPStanVendor\Symfony\Component\Console\Helper\Helper
{
    /**
     * Runs an external process.
     *
     * @param OutputInterface      $output    An OutputInterface instance
     * @param string|array|Process $cmd       An instance of Process or an array of arguments to escape and run or a command to run
     * @param string|null          $error     An error message that must be displayed if something went wrong
     * @param callable|null        $callback  A PHP callback to run whenever there is some
     *                                        output available on STDOUT or STDERR
     * @param int                  $verbosity The threshold for verbosity
     *
     * @return Process The process that ran
     */
    public function run(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, $cmd, $error = null, callable $callback = null, $verbosity = \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERY_VERBOSE)
    {
        if ($output instanceof \PHPStanVendor\Symfony\Component\Console\Output\ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }

        $formatter = $this->getHelperSet()->get('debug_formatter');

        if ($cmd instanceof \PHPStanVendor\Symfony\Component\Process\Process) {
            $process = $cmd;
        } else {
            $process = new \PHPStanVendor\Symfony\Component\Process\Process($cmd);
        }

        if ($verbosity <= $output->getVerbosity()) {
            $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine())));
        }

        if ($output->isDebug()) {
            $callback = $this->wrapCallback($output, $process, $callback);
        }

        $process->run($callback);

        if ($verbosity <= $output->getVerbosity()) {
            $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode());
            $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful()));
        }

        if (!$process->isSuccessful() && null !== $error) {
            $output->writeln(sprintf('<error>%s</error>', $this->escapeString($error)));
        }

        return $process;
    }

    /**
     * Runs the process.
     *
     * This is identical to run() except that an exception is thrown if the process
     * exits with a non-zero exit code.
     *
     * @param OutputInterface $output   An OutputInterface instance
     * @param string|Process  $cmd      An instance of Process or a command to run
     * @param string|null     $error    An error message that must be displayed if something went wrong
     * @param callable|null   $callback A PHP callback to run whenever there is some
     *                                  output available on STDOUT or STDERR
     *
     * @return Process The process that ran
     *
     * @throws ProcessFailedException
     *
     * @see run()
     */
    public function mustRun(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, $cmd, $error = null, callable $callback = null)
    {
        $process = $this->run($output, $cmd, $error, $callback);

        if (!$process->isSuccessful()) {
            throw new \PHPStanVendor\Symfony\Component\Process\Exception\ProcessFailedException($process);
        }

        return $process;
    }

    /**
     * Wraps a Process callback to add debugging output.
     *
     * @param OutputInterface $output   An OutputInterface interface
     * @param Process         $process  The Process
     * @param callable|null   $callback A PHP callable
     *
     * @return callable
     */
    public function wrapCallback(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, \PHPStanVendor\Symfony\Component\Process\Process $process, callable $callback = null)
    {
        if ($output instanceof \PHPStanVendor\Symfony\Component\Console\Output\ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }

        $formatter = $this->getHelperSet()->get('debug_formatter');

        return function ($type, $buffer) use ($output, $process, $callback, $formatter) {
            $output->write($formatter->progress(spl_object_hash($process), $this->escapeString($buffer), \PHPStanVendor\Symfony\Component\Process\Process::ERR === $type));

            if (null !== $callback) {
                call_user_func($callback, $type, $buffer);
            }
        };
    }

    private function escapeString($str)
    {
        return str_replace('<', '\\<', $str);
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'process';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Helper;

/**
 * The ProgressBar provides helpers to display progress output.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Chris Jones <leeked@gmail.com>
 */
final class ProgressBar
{
    private $barWidth = 28;
    private $barChar;
    private $emptyBarChar = '-';
    private $progressChar = '>';
    private $format;
    private $internalFormat;
    private $redrawFreq = 1;
    private $output;
    private $step = 0;
    private $max;
    private $startTime;
    private $stepWidth;
    private $percent = 0.0;
    private $formatLineCount;
    private $messages = array();
    private $overwrite = true;
    private $terminal;
    private $firstRun = true;

    private static $formatters;
    private static $formats;

    /**
     * @param OutputInterface $output An OutputInterface instance
     * @param int             $max    Maximum steps (0 if unknown)
     */
    public function __construct(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, $max = 0)
    {
        if ($output instanceof \PHPStanVendor\Symfony\Component\Console\Output\ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }

        $this->output = $output;
        $this->setMaxSteps($max);
        $this->terminal = new \PHPStanVendor\Symfony\Component\Console\Terminal();

        if (!$this->output->isDecorated()) {
            // disable overwrite when output does not support ANSI codes.
            $this->overwrite = false;

            // set a reasonable redraw frequency so output isn't flooded
            $this->setRedrawFrequency($max / 10);
        }

        $this->startTime = time();
    }

    /**
     * Sets a placeholder formatter for a given name.
     *
     * This method also allow you to override an existing placeholder.
     *
     * @param string   $name     The placeholder name (including the delimiter char like %)
     * @param callable $callable A PHP callable
     */
    public static function setPlaceholderFormatterDefinition($name, callable $callable)
    {
        if (!self::$formatters) {
            self::$formatters = self::initPlaceholderFormatters();
        }

        self::$formatters[$name] = $callable;
    }

    /**
     * Gets the placeholder formatter for a given name.
     *
     * @param string $name The placeholder name (including the delimiter char like %)
     *
     * @return callable|null A PHP callable
     */
    public static function getPlaceholderFormatterDefinition($name)
    {
        if (!self::$formatters) {
            self::$formatters = self::initPlaceholderFormatters();
        }

        return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
    }

    /**
     * Sets a format for a given name.
     *
     * This method also allow you to override an existing format.
     *
     * @param string $name   The format name
     * @param string $format A format string
     */
    public static function setFormatDefinition($name, $format)
    {
        if (!self::$formats) {
            self::$formats = self::initFormats();
        }

        self::$formats[$name] = $format;
    }

    /**
     * Gets the format for a given name.
     *
     * @param string $name The format name
     *
     * @return string|null A format string
     */
    public static function getFormatDefinition($name)
    {
        if (!self::$formats) {
            self::$formats = self::initFormats();
        }

        return isset(self::$formats[$name]) ? self::$formats[$name] : null;
    }

    /**
     * Associates a text with a named placeholder.
     *
     * The text is displayed when the progress bar is rendered but only
     * when the corresponding placeholder is part of the custom format line
     * (by wrapping the name with %).
     *
     * @param string $message The text to associate with the placeholder
     * @param string $name    The name of the placeholder
     */
    public function setMessage($message, $name = 'message')
    {
        $this->messages[$name] = $message;
    }

    public function getMessage($name = 'message')
    {
        return $this->messages[$name];
    }

    /**
     * Gets the progress bar start time.
     *
     * @return int The progress bar start time
     */
    public function getStartTime()
    {
        return $this->startTime;
    }

    /**
     * Gets the progress bar maximal steps.
     *
     * @return int The progress bar max steps
     */
    public function getMaxSteps()
    {
        return $this->max;
    }

    /**
     * Gets the current step position.
     *
     * @return int The progress bar step
     */
    public function getProgress()
    {
        return $this->step;
    }

    /**
     * Gets the progress bar step width.
     *
     * @return int The progress bar step width
     */
    private function getStepWidth()
    {
        return $this->stepWidth;
    }

    /**
     * Gets the current progress bar percent.
     *
     * @return float The current progress bar percent
     */
    public function getProgressPercent()
    {
        return $this->percent;
    }

    /**
     * Sets the progress bar width.
     *
     * @param int $size The progress bar size
     */
    public function setBarWidth($size)
    {
        $this->barWidth = max(1, (int) $size);
    }

    /**
     * Gets the progress bar width.
     *
     * @return int The progress bar size
     */
    public function getBarWidth()
    {
        return $this->barWidth;
    }

    /**
     * Sets the bar character.
     *
     * @param string $char A character
     */
    public function setBarCharacter($char)
    {
        $this->barChar = $char;
    }

    /**
     * Gets the bar character.
     *
     * @return string A character
     */
    public function getBarCharacter()
    {
        if (null === $this->barChar) {
            return $this->max ? '=' : $this->emptyBarChar;
        }

        return $this->barChar;
    }

    /**
     * Sets the empty bar character.
     *
     * @param string $char A character
     */
    public function setEmptyBarCharacter($char)
    {
        $this->emptyBarChar = $char;
    }

    /**
     * Gets the empty bar character.
     *
     * @return string A character
     */
    public function getEmptyBarCharacter()
    {
        return $this->emptyBarChar;
    }

    /**
     * Sets the progress bar character.
     *
     * @param string $char A character
     */
    public function setProgressCharacter($char)
    {
        $this->progressChar = $char;
    }

    /**
     * Gets the progress bar character.
     *
     * @return string A character
     */
    public function getProgressCharacter()
    {
        return $this->progressChar;
    }

    /**
     * Sets the progress bar format.
     *
     * @param string $format The format
     */
    public function setFormat($format)
    {
        $this->format = null;
        $this->internalFormat = $format;
    }

    /**
     * Sets the redraw frequency.
     *
     * @param int|float $freq The frequency in steps
     */
    public function setRedrawFrequency($freq)
    {
        $this->redrawFreq = max((int) $freq, 1);
    }

    /**
     * Starts the progress output.
     *
     * @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged
     */
    public function start($max = null)
    {
        $this->startTime = time();
        $this->step = 0;
        $this->percent = 0.0;

        if (null !== $max) {
            $this->setMaxSteps($max);
        }

        $this->display();
    }

    /**
     * Advances the progress output X steps.
     *
     * @param int $step Number of steps to advance
     */
    public function advance($step = 1)
    {
        $this->setProgress($this->step + $step);
    }

    /**
     * Sets whether to overwrite the progressbar, false for new line.
     *
     * @param bool $overwrite
     */
    public function setOverwrite($overwrite)
    {
        $this->overwrite = (bool) $overwrite;
    }

    /**
     * Sets the current progress.
     *
     * @param int $step The current progress
     */
    public function setProgress($step)
    {
        $step = (int) $step;

        if ($this->max && $step > $this->max) {
            $this->max = $step;
        } elseif ($step < 0) {
            $step = 0;
        }

        $prevPeriod = (int) ($this->step / $this->redrawFreq);
        $currPeriod = (int) ($step / $this->redrawFreq);
        $this->step = $step;
        $this->percent = $this->max ? (float) $this->step / $this->max : 0;
        if ($prevPeriod !== $currPeriod || $this->max === $step) {
            $this->display();
        }
    }

    /**
     * Finishes the progress output.
     */
    public function finish()
    {
        if (!$this->max) {
            $this->max = $this->step;
        }

        if ($this->step === $this->max && !$this->overwrite) {
            // prevent double 100% output
            return;
        }

        $this->setProgress($this->max);
    }

    /**
     * Outputs the current progress string.
     */
    public function display()
    {
        if (\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
            return;
        }

        if (null === $this->format) {
            $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
        }

        $this->overwrite($this->buildLine());
    }

    /**
     * Removes the progress bar from the current line.
     *
     * This is useful if you wish to write some output
     * while a progress bar is running.
     * Call display() to show the progress bar again.
     */
    public function clear()
    {
        if (!$this->overwrite) {
            return;
        }

        if (null === $this->format) {
            $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
        }

        $this->overwrite('');
    }

    /**
     * Sets the progress bar format.
     *
     * @param string $format The format
     */
    private function setRealFormat($format)
    {
        // try to use the _nomax variant if available
        if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
            $this->format = self::getFormatDefinition($format.'_nomax');
        } elseif (null !== self::getFormatDefinition($format)) {
            $this->format = self::getFormatDefinition($format);
        } else {
            $this->format = $format;
        }

        $this->formatLineCount = substr_count($this->format, "\n");
    }

    /**
     * Sets the progress bar maximal steps.
     *
     * @param int $max The progress bar max steps
     */
    private function setMaxSteps($max)
    {
        $this->max = max(0, (int) $max);
        $this->stepWidth = $this->max ? \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($this->max) : 4;
    }

    /**
     * Overwrites a previous message to the output.
     *
     * @param string $message The message
     */
    private function overwrite($message)
    {
        if ($this->overwrite) {
            if (!$this->firstRun) {
                // Move the cursor to the beginning of the line
                $this->output->write("\x0D");

                // Erase the line
                $this->output->write("\x1B[2K");

                // Erase previous lines
                if ($this->formatLineCount > 0) {
                    $this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount));
                }
            }
        } elseif ($this->step > 0) {
            $this->output->writeln('');
        }

        $this->firstRun = false;

        $this->output->write($message);
    }

    private function determineBestFormat()
    {
        switch ($this->output->getVerbosity()) {
            // OutputInterface::VERBOSITY_QUIET: display is disabled anyway
            case \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE:
                return $this->max ? 'verbose' : 'verbose_nomax';
            case \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERY_VERBOSE:
                return $this->max ? 'very_verbose' : 'very_verbose_nomax';
            case \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_DEBUG:
                return $this->max ? 'debug' : 'debug_nomax';
            default:
                return $this->max ? 'normal' : 'normal_nomax';
        }
    }

    private static function initPlaceholderFormatters()
    {
        return array(
            'bar' => function (\PHPStanVendor\Symfony\Component\Console\Helper\ProgressBar $bar, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output) {
                $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth());
                $display = str_repeat($bar->getBarCharacter(), $completeBars);
                if ($completeBars < $bar->getBarWidth()) {
                    $emptyBars = $bar->getBarWidth() - $completeBars - \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter());
                    $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
                }

                return $display;
            },
            'elapsed' => function (\PHPStanVendor\Symfony\Component\Console\Helper\ProgressBar $bar) {
                return \PHPStanVendor\Symfony\Component\Console\Helper\Helper::formatTime(time() - $bar->getStartTime());
            },
            'remaining' => function (\PHPStanVendor\Symfony\Component\Console\Helper\ProgressBar $bar) {
                if (!$bar->getMaxSteps()) {
                    throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
                }

                if (!$bar->getProgress()) {
                    $remaining = 0;
                } else {
                    $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress()));
                }

                return \PHPStanVendor\Symfony\Component\Console\Helper\Helper::formatTime($remaining);
            },
            'estimated' => function (\PHPStanVendor\Symfony\Component\Console\Helper\ProgressBar $bar) {
                if (!$bar->getMaxSteps()) {
                    throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
                }

                if (!$bar->getProgress()) {
                    $estimated = 0;
                } else {
                    $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps());
                }

                return \PHPStanVendor\Symfony\Component\Console\Helper\Helper::formatTime($estimated);
            },
            'memory' => function (\PHPStanVendor\Symfony\Component\Console\Helper\ProgressBar $bar) {
                return \PHPStanVendor\Symfony\Component\Console\Helper\Helper::formatMemory(memory_get_usage(true));
            },
            'current' => function (\PHPStanVendor\Symfony\Component\Console\Helper\ProgressBar $bar) {
                return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT);
            },
            'max' => function (\PHPStanVendor\Symfony\Component\Console\Helper\ProgressBar $bar) {
                return $bar->getMaxSteps();
            },
            'percent' => function (\PHPStanVendor\Symfony\Component\Console\Helper\ProgressBar $bar) {
                return floor($bar->getProgressPercent() * 100);
            },
        );
    }

    private static function initFormats()
    {
        return array(
            'normal' => ' %current%/%max% [%bar%] %percent:3s%%',
            'normal_nomax' => ' %current% [%bar%]',

            'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%',
            'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',

            'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%',
            'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',

            'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%',
            'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%',
        );
    }

    /**
     * @return string
     */
    private function buildLine()
    {
        $regex = "{%([a-z\-_]+)(?:\:([^%]+))?%}i";
        $callback = function ($matches) {
            if ($formatter = $this::getPlaceholderFormatterDefinition($matches[1])) {
                $text = call_user_func($formatter, $this, $this->output);
            } elseif (isset($this->messages[$matches[1]])) {
                $text = $this->messages[$matches[1]];
            } else {
                return $matches[0];
            }

            if (isset($matches[2])) {
                $text = sprintf('%'.$matches[2], $text);
            }

            return $text;
        };
        $line = preg_replace_callback($regex, $callback, $this->format);

        // gets string length for each sub line with multiline format
        $linesLength = array_map(function ($subLine) {
            return \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($this->output->getFormatter(), rtrim($subLine, "\r"));
        }, explode("\n", $line));

        $linesWidth = max($linesLength);

        $terminalWidth = $this->terminal->getWidth();
        if ($linesWidth <= $terminalWidth) {
            return $line;
        }

        $this->setBarWidth($this->barWidth - $linesWidth + $terminalWidth);

        return preg_replace_callback($regex, $callback, $this->format);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Helper;

/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class ProgressIndicator
{
    private $output;
    private $startTime;
    private $format;
    private $message;
    private $indicatorValues;
    private $indicatorCurrent;
    private $indicatorChangeInterval;
    private $indicatorUpdateTime;
    private $started = false;

    private static $formatters;
    private static $formats;

    /**
     * @param OutputInterface $output
     * @param string|null     $format                  Indicator format
     * @param int             $indicatorChangeInterval Change interval in milliseconds
     * @param array|null      $indicatorValues         Animated indicator characters
     */
    public function __construct(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, $format = null, $indicatorChangeInterval = 100, $indicatorValues = null)
    {
        $this->output = $output;

        if (null === $format) {
            $format = $this->determineBestFormat();
        }

        if (null === $indicatorValues) {
            $indicatorValues = array('-', '\\', '|', '/');
        }

        $indicatorValues = array_values($indicatorValues);

        if (2 > count($indicatorValues)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException('Must have at least 2 indicator value characters.');
        }

        $this->format = self::getFormatDefinition($format);
        $this->indicatorChangeInterval = $indicatorChangeInterval;
        $this->indicatorValues = $indicatorValues;
        $this->startTime = time();
    }

    /**
     * Sets the current indicator message.
     *
     * @param string|null $message
     */
    public function setMessage($message)
    {
        $this->message = $message;

        $this->display();
    }

    /**
     * Starts the indicator output.
     *
     * @param $message
     */
    public function start($message)
    {
        if ($this->started) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException('Progress indicator already started.');
        }

        $this->message = $message;
        $this->started = true;
        $this->startTime = time();
        $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
        $this->indicatorCurrent = 0;

        $this->display();
    }

    /**
     * Advances the indicator.
     */
    public function advance()
    {
        if (!$this->started) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException('Progress indicator has not yet been started.');
        }

        if (!$this->output->isDecorated()) {
            return;
        }

        $currentTime = $this->getCurrentTimeInMilliseconds();

        if ($currentTime < $this->indicatorUpdateTime) {
            return;
        }

        $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval;
        ++$this->indicatorCurrent;

        $this->display();
    }

    /**
     * Finish the indicator with message.
     *
     * @param $message
     */
    public function finish($message)
    {
        if (!$this->started) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException('Progress indicator has not yet been started.');
        }

        $this->message = $message;
        $this->display();
        $this->output->writeln('');
        $this->started = false;
    }

    /**
     * Gets the format for a given name.
     *
     * @param string $name The format name
     *
     * @return string|null A format string
     */
    public static function getFormatDefinition($name)
    {
        if (!self::$formats) {
            self::$formats = self::initFormats();
        }

        return isset(self::$formats[$name]) ? self::$formats[$name] : null;
    }

    /**
     * Sets a placeholder formatter for a given name.
     *
     * This method also allow you to override an existing placeholder.
     *
     * @param string   $name     The placeholder name (including the delimiter char like %)
     * @param callable $callable A PHP callable
     */
    public static function setPlaceholderFormatterDefinition($name, $callable)
    {
        if (!self::$formatters) {
            self::$formatters = self::initPlaceholderFormatters();
        }

        self::$formatters[$name] = $callable;
    }

    /**
     * Gets the placeholder formatter for a given name.
     *
     * @param string $name The placeholder name (including the delimiter char like %)
     *
     * @return callable|null A PHP callable
     */
    public static function getPlaceholderFormatterDefinition($name)
    {
        if (!self::$formatters) {
            self::$formatters = self::initPlaceholderFormatters();
        }

        return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
    }

    private function display()
    {
        if (\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
            return;
        }

        $self = $this;

        $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self) {
            if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
                return call_user_func($formatter, $self);
            }

            return $matches[0];
        }, $this->format));
    }

    private function determineBestFormat()
    {
        switch ($this->output->getVerbosity()) {
            // OutputInterface::VERBOSITY_QUIET: display is disabled anyway
            case \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE:
                return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi';
            case \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERY_VERBOSE:
            case \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_DEBUG:
                return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi';
            default:
                return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi';
        }
    }

    /**
     * Overwrites a previous message to the output.
     *
     * @param string $message The message
     */
    private function overwrite($message)
    {
        if ($this->output->isDecorated()) {
            $this->output->write("\x0D\x1B[2K");
            $this->output->write($message);
        } else {
            $this->output->writeln($message);
        }
    }

    private function getCurrentTimeInMilliseconds()
    {
        return round(microtime(true) * 1000);
    }

    private static function initPlaceholderFormatters()
    {
        return array(
            'indicator' => function (\PHPStanVendor\Symfony\Component\Console\Helper\ProgressIndicator $indicator) {
                return $indicator->indicatorValues[$indicator->indicatorCurrent % count($indicator->indicatorValues)];
            },
            'message' => function (\PHPStanVendor\Symfony\Component\Console\Helper\ProgressIndicator $indicator) {
                return $indicator->message;
            },
            'elapsed' => function (\PHPStanVendor\Symfony\Component\Console\Helper\ProgressIndicator $indicator) {
                return \PHPStanVendor\Symfony\Component\Console\Helper\Helper::formatTime(time() - $indicator->startTime);
            },
            'memory' => function () {
                return \PHPStanVendor\Symfony\Component\Console\Helper\Helper::formatMemory(memory_get_usage(true));
            },
        );
    }

    private static function initFormats()
    {
        return array(
            'normal' => ' %indicator% %message%',
            'normal_no_ansi' => ' %message%',

            'verbose' => ' %indicator% %message% (%elapsed:6s%)',
            'verbose_no_ansi' => ' %message% (%elapsed:6s%)',

            'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)',
            'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)',
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Helper;

/**
 * The QuestionHelper class provides helpers to interact with the user.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class QuestionHelper extends \PHPStanVendor\Symfony\Component\Console\Helper\Helper
{
    private $inputStream;
    private static $shell;
    private static $stty;

    /**
     * Asks a question to the user.
     *
     * @return mixed The user answer
     *
     * @throws RuntimeException If there is no data to read in the input stream
     */
    public function ask(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, \PHPStanVendor\Symfony\Component\Console\Question\Question $question)
    {
        if ($output instanceof \PHPStanVendor\Symfony\Component\Console\Output\ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }

        if (!$input->isInteractive()) {
            if ($question instanceof \PHPStanVendor\Symfony\Component\Console\Question\ChoiceQuestion) {
                $choices = $question->getChoices();

                return $choices[$question->getDefault()];
            }

            return $question->getDefault();
        }

        if ($input instanceof \PHPStanVendor\Symfony\Component\Console\Input\StreamableInputInterface && $stream = $input->getStream()) {
            $this->inputStream = $stream;
        }

        if (!$question->getValidator()) {
            return $this->doAsk($output, $question);
        }

        $interviewer = function () use ($output, $question) {
            return $this->doAsk($output, $question);
        };

        return $this->validateAttempts($interviewer, $output, $question);
    }

    /**
     * Sets the input stream to read from when interacting with the user.
     *
     * This is mainly useful for testing purpose.
     *
     * @deprecated since version 3.2, to be removed in 4.0. Use
     *             StreamableInputInterface::setStream() instead.
     *
     * @param resource $stream The input stream
     *
     * @throws InvalidArgumentException In case the stream is not a resource
     */
    public function setInputStream($stream)
    {
        @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.2 and will be removed in 4.0. Use %s::setStream() instead.', __METHOD__, \PHPStanVendor\Symfony\Component\Console\Input\StreamableInputInterface::class), E_USER_DEPRECATED);

        if (!is_resource($stream)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException('Input stream must be a valid resource.');
        }

        $this->inputStream = $stream;
    }

    /**
     * Returns the helper's input stream.
     *
     * @deprecated since version 3.2, to be removed in 4.0. Use
     *             StreamableInputInterface::getStream() instead.
     *
     * @return resource
     */
    public function getInputStream()
    {
        if (0 === func_num_args() || func_get_arg(0)) {
            @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.2 and will be removed in 4.0. Use %s::getStream() instead.', __METHOD__, \PHPStanVendor\Symfony\Component\Console\Input\StreamableInputInterface::class), E_USER_DEPRECATED);
        }

        return $this->inputStream;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'question';
    }

    /**
     * Prevents usage of stty.
     */
    public static function disableStty()
    {
        self::$stty = false;
    }

    /**
     * Asks the question to the user.
     *
     * @return bool|mixed|null|string
     *
     * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
     */
    private function doAsk(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, \PHPStanVendor\Symfony\Component\Console\Question\Question $question)
    {
        $this->writePrompt($output, $question);

        $inputStream = $this->inputStream ?: STDIN;
        $autocomplete = $question->getAutocompleterValues();

        if (null === $autocomplete || !$this->hasSttyAvailable()) {
            $ret = false;
            if ($question->isHidden()) {
                try {
                    $ret = trim($this->getHiddenResponse($output, $inputStream));
                } catch (\PHPStanVendor\Symfony\Component\Console\Exception\RuntimeException $e) {
                    if (!$question->isHiddenFallback()) {
                        throw $e;
                    }
                }
            }

            if (false === $ret) {
                $ret = fgets($inputStream, 4096);
                if (false === $ret) {
                    throw new \PHPStanVendor\Symfony\Component\Console\Exception\RuntimeException('Aborted');
                }
                $ret = trim($ret);
            }
        } else {
            $ret = trim($this->autocomplete($output, $question, $inputStream, is_array($autocomplete) ? $autocomplete : iterator_to_array($autocomplete, false)));
        }

        $ret = strlen($ret) > 0 ? $ret : $question->getDefault();

        if ($normalizer = $question->getNormalizer()) {
            return $normalizer($ret);
        }

        return $ret;
    }

    /**
     * Outputs the question prompt.
     */
    protected function writePrompt(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, \PHPStanVendor\Symfony\Component\Console\Question\Question $question)
    {
        $message = $question->getQuestion();

        if ($question instanceof \PHPStanVendor\Symfony\Component\Console\Question\ChoiceQuestion) {
            $maxWidth = max(array_map(array($this, 'strlen'), array_keys($question->getChoices())));

            $messages = (array) $question->getQuestion();
            foreach ($question->getChoices() as $key => $value) {
                $width = $maxWidth - $this->strlen($key);
                $messages[] = '  [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
            }

            $output->writeln($messages);

            $message = $question->getPrompt();
        }

        $output->write($message);
    }

    /**
     * Outputs an error message.
     */
    protected function writeError(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, \Exception $error)
    {
        if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
            $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
        } else {
            $message = '<error>'.$error->getMessage().'</error>';
        }

        $output->writeln($message);
    }

    /**
     * Autocompletes a question.
     *
     * @param OutputInterface $output
     * @param Question        $question
     * @param resource        $inputStream
     * @param array           $autocomplete
     *
     * @return string
     */
    private function autocomplete(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, \PHPStanVendor\Symfony\Component\Console\Question\Question $question, $inputStream, array $autocomplete)
    {
        $ret = '';

        $i = 0;
        $ofs = -1;
        $matches = $autocomplete;
        $numMatches = count($matches);

        $sttyMode = shell_exec('stty -g');

        // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead)
        shell_exec('stty -icanon -echo');

        // Add highlighted text style
        $output->getFormatter()->setStyle('hl', new \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterStyle('black', 'white'));

        // Read a keypress
        while (!feof($inputStream)) {
            $c = fread($inputStream, 1);

            // Backspace Character
            if ("\177" === $c) {
                if (0 === $numMatches && 0 !== $i) {
                    --$i;
                    // Move cursor backwards
                    $output->write("\033[1D");
                }

                if (0 === $i) {
                    $ofs = -1;
                    $matches = $autocomplete;
                    $numMatches = count($matches);
                } else {
                    $numMatches = 0;
                }

                // Pop the last character off the end of our string
                $ret = substr($ret, 0, $i);
            } elseif ("\033" === $c) {
                // Did we read an escape sequence?
                $c .= fread($inputStream, 2);

                // A = Up Arrow. B = Down Arrow
                if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
                    if ('A' === $c[2] && -1 === $ofs) {
                        $ofs = 0;
                    }

                    if (0 === $numMatches) {
                        continue;
                    }

                    $ofs += ('A' === $c[2]) ? -1 : 1;
                    $ofs = ($numMatches + $ofs) % $numMatches;
                }
            } elseif (ord($c) < 32) {
                if ("\t" === $c || "\n" === $c) {
                    if ($numMatches > 0 && -1 !== $ofs) {
                        $ret = $matches[$ofs];
                        // Echo out remaining chars for current match
                        $output->write(substr($ret, $i));
                        $i = strlen($ret);
                    }

                    if ("\n" === $c) {
                        $output->write($c);
                        break;
                    }

                    $numMatches = 0;
                }

                continue;
            } else {
                $output->write($c);
                $ret .= $c;
                ++$i;

                $numMatches = 0;
                $ofs = 0;

                foreach ($autocomplete as $value) {
                    // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle)
                    if (0 === strpos($value, $ret) && $i !== strlen($value)) {
                        $matches[$numMatches++] = $value;
                    }
                }
            }

            // Erase characters from cursor to end of line
            $output->write("\033[K");

            if ($numMatches > 0 && -1 !== $ofs) {
                // Save cursor position
                $output->write("\0337");
                // Write highlighted text
                $output->write('<hl>'.\PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $i)).'</hl>');
                // Restore cursor position
                $output->write("\0338");
            }
        }

        // Reset stty so it behaves normally again
        shell_exec(sprintf('stty %s', $sttyMode));

        return $ret;
    }

    /**
     * Gets a hidden response from user.
     *
     * @param OutputInterface $output      An Output instance
     * @param resource        $inputStream The handler resource
     *
     * @return string The answer
     *
     * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
     */
    private function getHiddenResponse(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, $inputStream)
    {
        if ('\\' === DIRECTORY_SEPARATOR) {
            $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';

            // handle code running from a phar
            if ('phar:' === substr(__FILE__, 0, 5)) {
                $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
                copy($exe, $tmpExe);
                $exe = $tmpExe;
            }

            $value = rtrim(shell_exec($exe));
            $output->writeln('');

            if (isset($tmpExe)) {
                unlink($tmpExe);
            }

            return $value;
        }

        if ($this->hasSttyAvailable()) {
            $sttyMode = shell_exec('stty -g');

            shell_exec('stty -echo');
            $value = fgets($inputStream, 4096);
            shell_exec(sprintf('stty %s', $sttyMode));

            if (false === $value) {
                throw new \PHPStanVendor\Symfony\Component\Console\Exception\RuntimeException('Aborted');
            }

            $value = trim($value);
            $output->writeln('');

            return $value;
        }

        if (false !== $shell = $this->getShell()) {
            $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
            $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
            $value = rtrim(shell_exec($command));
            $output->writeln('');

            return $value;
        }

        throw new \PHPStanVendor\Symfony\Component\Console\Exception\RuntimeException('Unable to hide the response.');
    }

    /**
     * Validates an attempt.
     *
     * @param callable        $interviewer A callable that will ask for a question and return the result
     * @param OutputInterface $output      An Output instance
     * @param Question        $question    A Question instance
     *
     * @return mixed The validated response
     *
     * @throws \Exception In case the max number of attempts has been reached and no valid response has been given
     */
    private function validateAttempts(callable $interviewer, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, \PHPStanVendor\Symfony\Component\Console\Question\Question $question)
    {
        $error = null;
        $attempts = $question->getMaxAttempts();
        while (null === $attempts || $attempts--) {
            if (null !== $error) {
                $this->writeError($output, $error);
            }

            try {
                return call_user_func($question->getValidator(), $interviewer());
            } catch (\PHPStanVendor\Symfony\Component\Console\Exception\RuntimeException $e) {
                throw $e;
            } catch (\Exception $error) {
            }
        }

        throw $error;
    }

    /**
     * Returns a valid unix shell.
     *
     * @return string|bool The valid shell name, false in case no valid shell is found
     */
    private function getShell()
    {
        if (null !== self::$shell) {
            return self::$shell;
        }

        self::$shell = false;

        if (file_exists('/usr/bin/env')) {
            // handle other OSs with bash/zsh/ksh/csh if available to hide the answer
            $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
            foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
                if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
                    self::$shell = $sh;
                    break;
                }
            }
        }

        return self::$shell;
    }

    /**
     * Returns whether Stty is available or not.
     *
     * @return bool
     */
    private function hasSttyAvailable()
    {
        if (null !== self::$stty) {
            return self::$stty;
        }

        exec('stty 2>&1', $output, $exitcode);

        return self::$stty = 0 === $exitcode;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Helper;

/**
 * Symfony Style Guide compliant question helper.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class SymfonyQuestionHelper extends \PHPStanVendor\Symfony\Component\Console\Helper\QuestionHelper
{
    /**
     * {@inheritdoc}
     *
     * To be removed in 4.0
     */
    public function ask(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, \PHPStanVendor\Symfony\Component\Console\Question\Question $question)
    {
        $validator = $question->getValidator();
        $question->setValidator(function ($value) use ($validator) {
            if (null !== $validator) {
                $value = $validator($value);
            } else {
                // make required
                if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) {
                    @trigger_error('The default question validator is deprecated since Symfony 3.3 and will not be used anymore in version 4.0. Set a custom question validator if needed.', E_USER_DEPRECATED);

                    throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException('A value is required.');
                }
            }

            return $value;
        });

        return parent::ask($input, $output, $question);
    }

    /**
     * {@inheritdoc}
     */
    protected function writePrompt(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, \PHPStanVendor\Symfony\Component\Console\Question\Question $question)
    {
        $text = \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatter::escapeTrailingBackslash($question->getQuestion());
        $default = $question->getDefault();

        switch (true) {
            case null === $default:
                $text = sprintf(' <info>%s</info>:', $text);

                break;

            case $question instanceof \PHPStanVendor\Symfony\Component\Console\Question\ConfirmationQuestion:
                $text = sprintf(' <info>%s (yes/no)</info> [<comment>%s</comment>]:', $text, $default ? 'yes' : 'no');

                break;

            case $question instanceof \PHPStanVendor\Symfony\Component\Console\Question\ChoiceQuestion && $question->isMultiselect():
                $choices = $question->getChoices();
                $default = explode(',', $default);

                foreach ($default as $key => $value) {
                    $default[$key] = $choices[trim($value)];
                }

                $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatter::escape(implode(', ', $default)));

                break;

            case $question instanceof \PHPStanVendor\Symfony\Component\Console\Question\ChoiceQuestion:
                $choices = $question->getChoices();
                $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatter::escape($choices[$default]));

                break;

            default:
                $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatter::escape($default));
        }

        $output->writeln($text);

        if ($question instanceof \PHPStanVendor\Symfony\Component\Console\Question\ChoiceQuestion) {
            $width = max(array_map('strlen', array_keys($question->getChoices())));

            foreach ($question->getChoices() as $key => $value) {
                $output->writeln(sprintf("  [<comment>%-${width}s</comment>] %s", $key, $value));
            }
        }

        $output->write(' > ');
    }

    /**
     * {@inheritdoc}
     */
    protected function writeError(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, \Exception $error)
    {
        if ($output instanceof \PHPStanVendor\Symfony\Component\Console\Style\SymfonyStyle) {
            $output->newLine();
            $output->error($error->getMessage());

            return;
        }

        parent::writeError($output, $error);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Helper;

/**
 * Provides helpers to display a table.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Саша Стаменковић <umpirsky@gmail.com>
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 * @author Max Grigorian <maxakawizard@gmail.com>
 */
class Table
{
    /**
     * Table headers.
     */
    private $headers = array();

    /**
     * Table rows.
     */
    private $rows = array();

    /**
     * Column widths cache.
     */
    private $effectiveColumnWidths = array();

    /**
     * Number of columns cache.
     *
     * @var int
     */
    private $numberOfColumns;

    /**
     * @var OutputInterface
     */
    private $output;

    /**
     * @var TableStyle
     */
    private $style;

    /**
     * @var array
     */
    private $columnStyles = array();

    /**
     * User set column widths.
     *
     * @var array
     */
    private $columnWidths = array();

    private static $styles;

    public function __construct(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output)
    {
        $this->output = $output;

        if (!self::$styles) {
            self::$styles = self::initStyles();
        }

        $this->setStyle('default');
    }

    /**
     * Sets a style definition.
     *
     * @param string     $name  The style name
     * @param TableStyle $style A TableStyle instance
     */
    public static function setStyleDefinition($name, \PHPStanVendor\Symfony\Component\Console\Helper\TableStyle $style)
    {
        if (!self::$styles) {
            self::$styles = self::initStyles();
        }

        self::$styles[$name] = $style;
    }

    /**
     * Gets a style definition by name.
     *
     * @param string $name The style name
     *
     * @return TableStyle
     */
    public static function getStyleDefinition($name)
    {
        if (!self::$styles) {
            self::$styles = self::initStyles();
        }

        if (isset(self::$styles[$name])) {
            return self::$styles[$name];
        }

        throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
    }

    /**
     * Sets table style.
     *
     * @param TableStyle|string $name The style name or a TableStyle instance
     *
     * @return $this
     */
    public function setStyle($name)
    {
        $this->style = $this->resolveStyle($name);

        return $this;
    }

    /**
     * Gets the current table style.
     *
     * @return TableStyle
     */
    public function getStyle()
    {
        return $this->style;
    }

    /**
     * Sets table column style.
     *
     * @param int               $columnIndex Column index
     * @param TableStyle|string $name        The style name or a TableStyle instance
     *
     * @return $this
     */
    public function setColumnStyle($columnIndex, $name)
    {
        $columnIndex = (int) $columnIndex;

        $this->columnStyles[$columnIndex] = $this->resolveStyle($name);

        return $this;
    }

    /**
     * Gets the current style for a column.
     *
     * If style was not set, it returns the global table style.
     *
     * @param int $columnIndex Column index
     *
     * @return TableStyle
     */
    public function getColumnStyle($columnIndex)
    {
        if (isset($this->columnStyles[$columnIndex])) {
            return $this->columnStyles[$columnIndex];
        }

        return $this->getStyle();
    }

    /**
     * Sets the minimum width of a column.
     *
     * @param int $columnIndex Column index
     * @param int $width       Minimum column width in characters
     *
     * @return $this
     */
    public function setColumnWidth($columnIndex, $width)
    {
        $this->columnWidths[(int) $columnIndex] = (int) $width;

        return $this;
    }

    /**
     * Sets the minimum width of all columns.
     *
     * @param array $widths
     *
     * @return $this
     */
    public function setColumnWidths(array $widths)
    {
        $this->columnWidths = array();
        foreach ($widths as $index => $width) {
            $this->setColumnWidth($index, $width);
        }

        return $this;
    }

    public function setHeaders(array $headers)
    {
        $headers = array_values($headers);
        if (!empty($headers) && !is_array($headers[0])) {
            $headers = array($headers);
        }

        $this->headers = $headers;

        return $this;
    }

    public function setRows(array $rows)
    {
        $this->rows = array();

        return $this->addRows($rows);
    }

    public function addRows(array $rows)
    {
        foreach ($rows as $row) {
            $this->addRow($row);
        }

        return $this;
    }

    public function addRow($row)
    {
        if ($row instanceof \PHPStanVendor\Symfony\Component\Console\Helper\TableSeparator) {
            $this->rows[] = $row;

            return $this;
        }

        if (!is_array($row)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException('A row must be an array or a TableSeparator instance.');
        }

        $this->rows[] = array_values($row);

        return $this;
    }

    public function setRow($column, array $row)
    {
        $this->rows[$column] = $row;

        return $this;
    }

    /**
     * Renders table to output.
     *
     * Example:
     * <code>
     * +---------------+-----------------------+------------------+
     * | ISBN          | Title                 | Author           |
     * +---------------+-----------------------+------------------+
     * | 99921-58-10-7 | Divine Comedy         | Dante Alighieri  |
     * | 9971-5-0210-0 | A Tale of Two Cities  | Charles Dickens  |
     * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
     * +---------------+-----------------------+------------------+
     * </code>
     */
    public function render()
    {
        $this->calculateNumberOfColumns();
        $rows = $this->buildTableRows($this->rows);
        $headers = $this->buildTableRows($this->headers);

        $this->calculateColumnsWidth(array_merge($headers, $rows));

        $this->renderRowSeparator();
        if (!empty($headers)) {
            foreach ($headers as $header) {
                $this->renderRow($header, $this->style->getCellHeaderFormat());
                $this->renderRowSeparator();
            }
        }
        foreach ($rows as $row) {
            if ($row instanceof \PHPStanVendor\Symfony\Component\Console\Helper\TableSeparator) {
                $this->renderRowSeparator();
            } else {
                $this->renderRow($row, $this->style->getCellRowFormat());
            }
        }
        if (!empty($rows)) {
            $this->renderRowSeparator();
        }

        $this->cleanup();
    }

    /**
     * Renders horizontal header separator.
     *
     * Example: <code>+-----+-----------+-------+</code>
     */
    private function renderRowSeparator()
    {
        if (0 === $count = $this->numberOfColumns) {
            return;
        }

        if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) {
            return;
        }

        $markup = $this->style->getCrossingChar();
        for ($column = 0; $column < $count; ++$column) {
            $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->effectiveColumnWidths[$column]).$this->style->getCrossingChar();
        }

        $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
    }

    /**
     * Renders vertical column separator.
     */
    private function renderColumnSeparator()
    {
        return sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar());
    }

    /**
     * Renders table row.
     *
     * Example: <code>| 9971-5-0210-0 | A Tale of Two Cities  | Charles Dickens  |</code>
     *
     * @param array  $row
     * @param string $cellFormat
     */
    private function renderRow(array $row, $cellFormat)
    {
        if (empty($row)) {
            return;
        }

        $rowContent = $this->renderColumnSeparator();
        foreach ($this->getRowColumns($row) as $column) {
            $rowContent .= $this->renderCell($row, $column, $cellFormat);
            $rowContent .= $this->renderColumnSeparator();
        }
        $this->output->writeln($rowContent);
    }

    /**
     * Renders table cell with padding.
     *
     * @param array  $row
     * @param int    $column
     * @param string $cellFormat
     */
    private function renderCell(array $row, $column, $cellFormat)
    {
        $cell = isset($row[$column]) ? $row[$column] : '';
        $width = $this->effectiveColumnWidths[$column];
        if ($cell instanceof \PHPStanVendor\Symfony\Component\Console\Helper\TableCell && $cell->getColspan() > 1) {
            // add the width of the following columns(numbers of colspan).
            foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
                $width += $this->getColumnSeparatorWidth() + $this->effectiveColumnWidths[$nextColumn];
            }
        }

        // str_pad won't work properly with multi-byte strings, we need to fix the padding
        if (false !== $encoding = mb_detect_encoding($cell, null, true)) {
            $width += strlen($cell) - mb_strwidth($cell, $encoding);
        }

        $style = $this->getColumnStyle($column);

        if ($cell instanceof \PHPStanVendor\Symfony\Component\Console\Helper\TableSeparator) {
            return sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width));
        }

        $width += \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($cell) - \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
        $content = sprintf($style->getCellRowContentFormat(), $cell);

        return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()));
    }

    /**
     * Calculate number of columns for this table.
     */
    private function calculateNumberOfColumns()
    {
        if (null !== $this->numberOfColumns) {
            return;
        }

        $columns = array(0);
        foreach (array_merge($this->headers, $this->rows) as $row) {
            if ($row instanceof \PHPStanVendor\Symfony\Component\Console\Helper\TableSeparator) {
                continue;
            }

            $columns[] = $this->getNumberOfColumns($row);
        }

        $this->numberOfColumns = max($columns);
    }

    private function buildTableRows($rows)
    {
        $unmergedRows = array();
        for ($rowKey = 0; $rowKey < count($rows); ++$rowKey) {
            $rows = $this->fillNextRows($rows, $rowKey);

            // Remove any new line breaks and replace it with a new line
            foreach ($rows[$rowKey] as $column => $cell) {
                if (!strstr($cell, "\n")) {
                    continue;
                }
                $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
                foreach ($lines as $lineKey => $line) {
                    if ($cell instanceof \PHPStanVendor\Symfony\Component\Console\Helper\TableCell) {
                        $line = new \PHPStanVendor\Symfony\Component\Console\Helper\TableCell($line, array('colspan' => $cell->getColspan()));
                    }
                    if (0 === $lineKey) {
                        $rows[$rowKey][$column] = $line;
                    } else {
                        $unmergedRows[$rowKey][$lineKey][$column] = $line;
                    }
                }
            }
        }

        $tableRows = array();
        foreach ($rows as $rowKey => $row) {
            $tableRows[] = $this->fillCells($row);
            if (isset($unmergedRows[$rowKey])) {
                $tableRows = array_merge($tableRows, $unmergedRows[$rowKey]);
            }
        }

        return $tableRows;
    }

    /**
     * fill rows that contains rowspan > 1.
     *
     * @param array $rows
     * @param int   $line
     *
     * @return array
     */
    private function fillNextRows(array $rows, $line)
    {
        $unmergedRows = array();
        foreach ($rows[$line] as $column => $cell) {
            if ($cell instanceof \PHPStanVendor\Symfony\Component\Console\Helper\TableCell && $cell->getRowspan() > 1) {
                $nbLines = $cell->getRowspan() - 1;
                $lines = array($cell);
                if (strstr($cell, "\n")) {
                    $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
                    $nbLines = count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;

                    $rows[$line][$column] = new \PHPStanVendor\Symfony\Component\Console\Helper\TableCell($lines[0], array('colspan' => $cell->getColspan()));
                    unset($lines[0]);
                }

                // create a two dimensional array (rowspan x colspan)
                $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, array()), $unmergedRows);
                foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
                    $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : '';
                    $unmergedRows[$unmergedRowKey][$column] = new \PHPStanVendor\Symfony\Component\Console\Helper\TableCell($value, array('colspan' => $cell->getColspan()));
                    if ($nbLines === $unmergedRowKey - $line) {
                        break;
                    }
                }
            }
        }

        foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
            // we need to know if $unmergedRow will be merged or inserted into $rows
            if (isset($rows[$unmergedRowKey]) && is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) {
                foreach ($unmergedRow as $cellKey => $cell) {
                    // insert cell into row at cellKey position
                    array_splice($rows[$unmergedRowKey], $cellKey, 0, array($cell));
                }
            } else {
                $row = $this->copyRow($rows, $unmergedRowKey - 1);
                foreach ($unmergedRow as $column => $cell) {
                    if (!empty($cell)) {
                        $row[$column] = $unmergedRow[$column];
                    }
                }
                array_splice($rows, $unmergedRowKey, 0, array($row));
            }
        }

        return $rows;
    }

    /**
     * fill cells for a row that contains colspan > 1.
     *
     * @return array
     */
    private function fillCells($row)
    {
        $newRow = array();
        foreach ($row as $column => $cell) {
            $newRow[] = $cell;
            if ($cell instanceof \PHPStanVendor\Symfony\Component\Console\Helper\TableCell && $cell->getColspan() > 1) {
                foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) {
                    // insert empty value at column position
                    $newRow[] = '';
                }
            }
        }

        return $newRow ?: $row;
    }

    /**
     * @param array $rows
     * @param int   $line
     *
     * @return array
     */
    private function copyRow(array $rows, $line)
    {
        $row = $rows[$line];
        foreach ($row as $cellKey => $cellValue) {
            $row[$cellKey] = '';
            if ($cellValue instanceof \PHPStanVendor\Symfony\Component\Console\Helper\TableCell) {
                $row[$cellKey] = new \PHPStanVendor\Symfony\Component\Console\Helper\TableCell('', array('colspan' => $cellValue->getColspan()));
            }
        }

        return $row;
    }

    /**
     * Gets number of columns by row.
     *
     * @return int
     */
    private function getNumberOfColumns(array $row)
    {
        $columns = count($row);
        foreach ($row as $column) {
            $columns += $column instanceof \PHPStanVendor\Symfony\Component\Console\Helper\TableCell ? ($column->getColspan() - 1) : 0;
        }

        return $columns;
    }

    /**
     * Gets list of columns for the given row.
     *
     * @return array
     */
    private function getRowColumns(array $row)
    {
        $columns = range(0, $this->numberOfColumns - 1);
        foreach ($row as $cellKey => $cell) {
            if ($cell instanceof \PHPStanVendor\Symfony\Component\Console\Helper\TableCell && $cell->getColspan() > 1) {
                // exclude grouped columns.
                $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1));
            }
        }

        return $columns;
    }

    /**
     * Calculates columns widths.
     */
    private function calculateColumnsWidth(array $rows)
    {
        for ($column = 0; $column < $this->numberOfColumns; ++$column) {
            $lengths = array();
            foreach ($rows as $row) {
                if ($row instanceof \PHPStanVendor\Symfony\Component\Console\Helper\TableSeparator) {
                    continue;
                }

                foreach ($row as $i => $cell) {
                    if ($cell instanceof \PHPStanVendor\Symfony\Component\Console\Helper\TableCell) {
                        $textContent = \PHPStanVendor\Symfony\Component\Console\Helper\Helper::removeDecoration($this->output->getFormatter(), $cell);
                        $textLength = \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlen($textContent);
                        if ($textLength > 0) {
                            $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan()));
                            foreach ($contentColumns as $position => $content) {
                                $row[$i + $position] = $content;
                            }
                        }
                    }
                }

                $lengths[] = $this->getCellWidth($row, $column);
            }

            $this->effectiveColumnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2;
        }
    }

    /**
     * Gets column width.
     *
     * @return int
     */
    private function getColumnSeparatorWidth()
    {
        return strlen(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
    }

    /**
     * Gets cell width.
     *
     * @param array $row
     * @param int   $column
     *
     * @return int
     */
    private function getCellWidth(array $row, $column)
    {
        $cellWidth = 0;

        if (isset($row[$column])) {
            $cell = $row[$column];
            $cellWidth = \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
        }

        $columnWidth = isset($this->columnWidths[$column]) ? $this->columnWidths[$column] : 0;

        return max($cellWidth, $columnWidth);
    }

    /**
     * Called after rendering to cleanup cache data.
     */
    private function cleanup()
    {
        $this->effectiveColumnWidths = array();
        $this->numberOfColumns = null;
    }

    private static function initStyles()
    {
        $borderless = new \PHPStanVendor\Symfony\Component\Console\Helper\TableStyle();
        $borderless
            ->setHorizontalBorderChar('=')
            ->setVerticalBorderChar(' ')
            ->setCrossingChar(' ')
        ;

        $compact = new \PHPStanVendor\Symfony\Component\Console\Helper\TableStyle();
        $compact
            ->setHorizontalBorderChar('')
            ->setVerticalBorderChar(' ')
            ->setCrossingChar('')
            ->setCellRowContentFormat('%s')
        ;

        $styleGuide = new \PHPStanVendor\Symfony\Component\Console\Helper\TableStyle();
        $styleGuide
            ->setHorizontalBorderChar('-')
            ->setVerticalBorderChar(' ')
            ->setCrossingChar(' ')
            ->setCellHeaderFormat('%s')
        ;

        return array(
            'default' => new \PHPStanVendor\Symfony\Component\Console\Helper\TableStyle(),
            'borderless' => $borderless,
            'compact' => $compact,
            'symfony-style-guide' => $styleGuide,
        );
    }

    private function resolveStyle($name)
    {
        if ($name instanceof \PHPStanVendor\Symfony\Component\Console\Helper\TableStyle) {
            return $name;
        }

        if (isset(self::$styles[$name])) {
            return self::$styles[$name];
        }

        throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Helper;

/**
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 */
class TableCell
{
    private $value;
    private $options = array(
        'rowspan' => 1,
        'colspan' => 1,
    );

    /**
     * @param string $value
     * @param array  $options
     */
    public function __construct($value = '', array $options = array())
    {
        if (is_numeric($value) && !is_string($value)) {
            $value = (string) $value;
        }

        $this->value = $value;

        // check option names
        if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff)));
        }

        $this->options = array_merge($this->options, $options);
    }

    /**
     * Returns the cell value.
     *
     * @return string
     */
    public function __toString()
    {
        return $this->value;
    }

    /**
     * Gets number of colspan.
     *
     * @return int
     */
    public function getColspan()
    {
        return (int) $this->options['colspan'];
    }

    /**
     * Gets number of rowspan.
     *
     * @return int
     */
    public function getRowspan()
    {
        return (int) $this->options['rowspan'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Helper;

/**
 * Marks a row as being a separator.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TableSeparator extends \PHPStanVendor\Symfony\Component\Console\Helper\TableCell
{
    public function __construct(array $options = array())
    {
        parent::__construct('', $options);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Helper;

/**
 * Defines the styles for a Table.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Саша Стаменковић <umpirsky@gmail.com>
 */
class TableStyle
{
    private $paddingChar = ' ';
    private $horizontalBorderChar = '-';
    private $verticalBorderChar = '|';
    private $crossingChar = '+';
    private $cellHeaderFormat = '<info>%s</info>';
    private $cellRowFormat = '%s';
    private $cellRowContentFormat = ' %s ';
    private $borderFormat = '%s';
    private $padType = STR_PAD_RIGHT;

    /**
     * Sets padding character, used for cell padding.
     *
     * @param string $paddingChar
     *
     * @return $this
     */
    public function setPaddingChar($paddingChar)
    {
        if (!$paddingChar) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException('The padding char must not be empty');
        }

        $this->paddingChar = $paddingChar;

        return $this;
    }

    /**
     * Gets padding character, used for cell padding.
     *
     * @return string
     */
    public function getPaddingChar()
    {
        return $this->paddingChar;
    }

    /**
     * Sets horizontal border character.
     *
     * @param string $horizontalBorderChar
     *
     * @return $this
     */
    public function setHorizontalBorderChar($horizontalBorderChar)
    {
        $this->horizontalBorderChar = $horizontalBorderChar;

        return $this;
    }

    /**
     * Gets horizontal border character.
     *
     * @return string
     */
    public function getHorizontalBorderChar()
    {
        return $this->horizontalBorderChar;
    }

    /**
     * Sets vertical border character.
     *
     * @param string $verticalBorderChar
     *
     * @return $this
     */
    public function setVerticalBorderChar($verticalBorderChar)
    {
        $this->verticalBorderChar = $verticalBorderChar;

        return $this;
    }

    /**
     * Gets vertical border character.
     *
     * @return string
     */
    public function getVerticalBorderChar()
    {
        return $this->verticalBorderChar;
    }

    /**
     * Sets crossing character.
     *
     * @param string $crossingChar
     *
     * @return $this
     */
    public function setCrossingChar($crossingChar)
    {
        $this->crossingChar = $crossingChar;

        return $this;
    }

    /**
     * Gets crossing character.
     *
     * @return string $crossingChar
     */
    public function getCrossingChar()
    {
        return $this->crossingChar;
    }

    /**
     * Sets header cell format.
     *
     * @param string $cellHeaderFormat
     *
     * @return $this
     */
    public function setCellHeaderFormat($cellHeaderFormat)
    {
        $this->cellHeaderFormat = $cellHeaderFormat;

        return $this;
    }

    /**
     * Gets header cell format.
     *
     * @return string
     */
    public function getCellHeaderFormat()
    {
        return $this->cellHeaderFormat;
    }

    /**
     * Sets row cell format.
     *
     * @param string $cellRowFormat
     *
     * @return $this
     */
    public function setCellRowFormat($cellRowFormat)
    {
        $this->cellRowFormat = $cellRowFormat;

        return $this;
    }

    /**
     * Gets row cell format.
     *
     * @return string
     */
    public function getCellRowFormat()
    {
        return $this->cellRowFormat;
    }

    /**
     * Sets row cell content format.
     *
     * @param string $cellRowContentFormat
     *
     * @return $this
     */
    public function setCellRowContentFormat($cellRowContentFormat)
    {
        $this->cellRowContentFormat = $cellRowContentFormat;

        return $this;
    }

    /**
     * Gets row cell content format.
     *
     * @return string
     */
    public function getCellRowContentFormat()
    {
        return $this->cellRowContentFormat;
    }

    /**
     * Sets table border format.
     *
     * @param string $borderFormat
     *
     * @return $this
     */
    public function setBorderFormat($borderFormat)
    {
        $this->borderFormat = $borderFormat;

        return $this;
    }

    /**
     * Gets table border format.
     *
     * @return string
     */
    public function getBorderFormat()
    {
        return $this->borderFormat;
    }

    /**
     * Sets cell padding type.
     *
     * @param int $padType STR_PAD_*
     *
     * @return $this
     */
    public function setPadType($padType)
    {
        if (!in_array($padType, array(STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH), true)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).');
        }

        $this->padType = $padType;

        return $this;
    }

    /**
     * Gets cell padding type.
     *
     * @return int
     */
    public function getPadType()
    {
        return $this->padType;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Input;

/**
 * ArgvInput represents an input coming from the CLI arguments.
 *
 * Usage:
 *
 *     $input = new ArgvInput();
 *
 * By default, the `$_SERVER['argv']` array is used for the input values.
 *
 * This can be overridden by explicitly passing the input values in the constructor:
 *
 *     $input = new ArgvInput($_SERVER['argv']);
 *
 * If you pass it yourself, don't forget that the first element of the array
 * is the name of the running application.
 *
 * When passing an argument to the constructor, be sure that it respects
 * the same rules as the argv one. It's almost always better to use the
 * `StringInput` when you want to provide your own input.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
 * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02
 */
class ArgvInput extends \PHPStanVendor\Symfony\Component\Console\Input\Input
{
    private $tokens;
    private $parsed;

    /**
     * @param array|null           $argv       An array of parameters from the CLI (in the argv format)
     * @param InputDefinition|null $definition A InputDefinition instance
     */
    public function __construct(array $argv = null, \PHPStanVendor\Symfony\Component\Console\Input\InputDefinition $definition = null)
    {
        if (null === $argv) {
            $argv = $_SERVER['argv'];
        }

        // strip the application name
        array_shift($argv);

        $this->tokens = $argv;

        parent::__construct($definition);
    }

    protected function setTokens(array $tokens)
    {
        $this->tokens = $tokens;
    }

    /**
     * {@inheritdoc}
     */
    protected function parse()
    {
        $parseOptions = true;
        $this->parsed = $this->tokens;
        while (null !== $token = array_shift($this->parsed)) {
            if ($parseOptions && '' == $token) {
                $this->parseArgument($token);
            } elseif ($parseOptions && '--' == $token) {
                $parseOptions = false;
            } elseif ($parseOptions && 0 === strpos($token, '--')) {
                $this->parseLongOption($token);
            } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
                $this->parseShortOption($token);
            } else {
                $this->parseArgument($token);
            }
        }
    }

    /**
     * Parses a short option.
     *
     * @param string $token The current token
     */
    private function parseShortOption($token)
    {
        $name = substr($token, 1);

        if (strlen($name) > 1) {
            if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
                // an option with a value (with no space)
                $this->addShortOption($name[0], substr($name, 1));
            } else {
                $this->parseShortOptionSet($name);
            }
        } else {
            $this->addShortOption($name, null);
        }
    }

    /**
     * Parses a short option set.
     *
     * @param string $name The current token
     *
     * @throws RuntimeException When option given doesn't exist
     */
    private function parseShortOptionSet($name)
    {
        $len = strlen($name);
        for ($i = 0; $i < $len; ++$i) {
            if (!$this->definition->hasShortcut($name[$i])) {
                throw new \PHPStanVendor\Symfony\Component\Console\Exception\RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
            }

            $option = $this->definition->getOptionForShortcut($name[$i]);
            if ($option->acceptValue()) {
                $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));

                break;
            } else {
                $this->addLongOption($option->getName(), null);
            }
        }
    }

    /**
     * Parses a long option.
     *
     * @param string $token The current token
     */
    private function parseLongOption($token)
    {
        $name = substr($token, 2);

        if (false !== $pos = strpos($name, '=')) {
            if (0 === strlen($value = substr($name, $pos + 1))) {
                // if no value after "=" then substr() returns "" since php7 only, false before
                // see http://php.net/manual/fr/migration70.incompatible.php#119151
                if (\PHP_VERSION_ID < 70000 && false === $value) {
                    $value = '';
                }
                array_unshift($this->parsed, $value);
            }
            $this->addLongOption(substr($name, 0, $pos), $value);
        } else {
            $this->addLongOption($name, null);
        }
    }

    /**
     * Parses an argument.
     *
     * @param string $token The current token
     *
     * @throws RuntimeException When too many arguments are given
     */
    private function parseArgument($token)
    {
        $c = count($this->arguments);

        // if input is expecting another argument, add it
        if ($this->definition->hasArgument($c)) {
            $arg = $this->definition->getArgument($c);
            $this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token;

        // if last argument isArray(), append token to last argument
        } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
            $arg = $this->definition->getArgument($c - 1);
            $this->arguments[$arg->getName()][] = $token;

        // unexpected argument
        } else {
            $all = $this->definition->getArguments();
            if (count($all)) {
                throw new \PHPStanVendor\Symfony\Component\Console\Exception\RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))));
            }

            throw new \PHPStanVendor\Symfony\Component\Console\Exception\RuntimeException(sprintf('No arguments expected, got "%s".', $token));
        }
    }

    /**
     * Adds a short option value.
     *
     * @param string $shortcut The short option key
     * @param mixed  $value    The value for the option
     *
     * @throws RuntimeException When option given doesn't exist
     */
    private function addShortOption($shortcut, $value)
    {
        if (!$this->definition->hasShortcut($shortcut)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
        }

        $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
    }

    /**
     * Adds a long option value.
     *
     * @param string $name  The long option key
     * @param mixed  $value The value for the option
     *
     * @throws RuntimeException When option given doesn't exist
     */
    private function addLongOption($name, $value)
    {
        if (!$this->definition->hasOption($name)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\RuntimeException(sprintf('The "--%s" option does not exist.', $name));
        }

        $option = $this->definition->getOption($name);

        if (null !== $value && !$option->acceptValue()) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
        }

        if (in_array($value, array('', null), true) && $option->acceptValue() && count($this->parsed)) {
            // if option accepts an optional or mandatory argument
            // let's see if there is one provided
            $next = array_shift($this->parsed);
            if ((isset($next[0]) && '-' !== $next[0]) || in_array($next, array('', null), true)) {
                $value = $next;
            } else {
                array_unshift($this->parsed, $next);
            }
        }

        if (null === $value) {
            if ($option->isValueRequired()) {
                throw new \PHPStanVendor\Symfony\Component\Console\Exception\RuntimeException(sprintf('The "--%s" option requires a value.', $name));
            }

            if (!$option->isArray() && !$option->isValueOptional()) {
                $value = true;
            }
        }

        if ($option->isArray()) {
            $this->options[$name][] = $value;
        } else {
            $this->options[$name] = $value;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function getFirstArgument()
    {
        foreach ($this->tokens as $token) {
            if ($token && '-' === $token[0]) {
                continue;
            }

            return $token;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function hasParameterOption($values, $onlyParams = false)
    {
        $values = (array) $values;

        foreach ($this->tokens as $token) {
            if ($onlyParams && '--' === $token) {
                return false;
            }
            foreach ($values as $value) {
                if ($token === $value || 0 === strpos($token, $value.'=')) {
                    return true;
                }

                if (0 === strpos($token, '-') && 0 !== strpos($token, '--')) {
                    $noValue = explode('=', $token);
                    $token = $noValue[0];
                    $searchableToken = str_replace('-', '', $token);
                    $searchableValue = str_replace('-', '', $value);
                    if ('' !== $searchableToken && '' !== $searchableValue && false !== strpos($searchableToken, $searchableValue)) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function getParameterOption($values, $default = false, $onlyParams = false)
    {
        $values = (array) $values;
        $tokens = $this->tokens;

        while (0 < count($tokens)) {
            $token = array_shift($tokens);
            if ($onlyParams && '--' === $token) {
                return false;
            }

            foreach ($values as $value) {
                if ($token === $value || 0 === strpos($token, $value.'=')) {
                    if (false !== $pos = strpos($token, '=')) {
                        return substr($token, $pos + 1);
                    }

                    return array_shift($tokens);
                }
            }
        }

        return $default;
    }

    /**
     * Returns a stringified representation of the args passed to the command.
     *
     * @return string
     */
    public function __toString()
    {
        $tokens = array_map(function ($token) {
            if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
                return $match[1].$this->escapeToken($match[2]);
            }

            if ($token && '-' !== $token[0]) {
                return $this->escapeToken($token);
            }

            return $token;
        }, $this->tokens);

        return implode(' ', $tokens);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Input;

/**
 * ArrayInput represents an input provided as an array.
 *
 * Usage:
 *
 *     $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar'));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ArrayInput extends \PHPStanVendor\Symfony\Component\Console\Input\Input
{
    private $parameters;

    public function __construct(array $parameters, \PHPStanVendor\Symfony\Component\Console\Input\InputDefinition $definition = null)
    {
        $this->parameters = $parameters;

        parent::__construct($definition);
    }

    /**
     * {@inheritdoc}
     */
    public function getFirstArgument()
    {
        foreach ($this->parameters as $key => $value) {
            if ($key && '-' === $key[0]) {
                continue;
            }

            return $value;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function hasParameterOption($values, $onlyParams = false)
    {
        $values = (array) $values;

        foreach ($this->parameters as $k => $v) {
            if (!is_int($k)) {
                $v = $k;
            }

            if ($onlyParams && '--' === $v) {
                return false;
            }

            if (in_array($v, $values)) {
                return true;
            }
        }

        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function getParameterOption($values, $default = false, $onlyParams = false)
    {
        $values = (array) $values;

        foreach ($this->parameters as $k => $v) {
            if ($onlyParams && ('--' === $k || (is_int($k) && '--' === $v))) {
                return false;
            }

            if (is_int($k)) {
                if (in_array($v, $values)) {
                    return true;
                }
            } elseif (in_array($k, $values)) {
                return $v;
            }
        }

        return $default;
    }

    /**
     * Returns a stringified representation of the args passed to the command.
     *
     * @return string
     */
    public function __toString()
    {
        $params = array();
        foreach ($this->parameters as $param => $val) {
            if ($param && '-' === $param[0]) {
                if (is_array($val)) {
                    foreach ($val as $v) {
                        $params[] = $param.('' != $v ? '='.$this->escapeToken($v) : '');
                    }
                } else {
                    $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : '');
                }
            } else {
                $params[] = is_array($val) ? array_map(array($this, 'escapeToken'), $val) : $this->escapeToken($val);
            }
        }

        return implode(' ', $params);
    }

    /**
     * {@inheritdoc}
     */
    protected function parse()
    {
        foreach ($this->parameters as $key => $value) {
            if ('--' === $key) {
                return;
            }
            if (0 === strpos($key, '--')) {
                $this->addLongOption(substr($key, 2), $value);
            } elseif ('-' === $key[0]) {
                $this->addShortOption(substr($key, 1), $value);
            } else {
                $this->addArgument($key, $value);
            }
        }
    }

    /**
     * Adds a short option value.
     *
     * @param string $shortcut The short option key
     * @param mixed  $value    The value for the option
     *
     * @throws InvalidOptionException When option given doesn't exist
     */
    private function addShortOption($shortcut, $value)
    {
        if (!$this->definition->hasShortcut($shortcut)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut));
        }

        $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
    }

    /**
     * Adds a long option value.
     *
     * @param string $name  The long option key
     * @param mixed  $value The value for the option
     *
     * @throws InvalidOptionException When option given doesn't exist
     * @throws InvalidOptionException When a required value is missing
     */
    private function addLongOption($name, $value)
    {
        if (!$this->definition->hasOption($name)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidOptionException(sprintf('The "--%s" option does not exist.', $name));
        }

        $option = $this->definition->getOption($name);

        if (null === $value) {
            if ($option->isValueRequired()) {
                throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidOptionException(sprintf('The "--%s" option requires a value.', $name));
            }

            if (!$option->isValueOptional()) {
                $value = true;
            }
        }

        $this->options[$name] = $value;
    }

    /**
     * Adds an argument value.
     *
     * @param string $name  The argument name
     * @param mixed  $value The value for the argument
     *
     * @throws InvalidArgumentException When argument given doesn't exist
     */
    private function addArgument($name, $value)
    {
        if (!$this->definition->hasArgument($name)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
        }

        $this->arguments[$name] = $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Input;

/**
 * Input is the base class for all concrete Input classes.
 *
 * Three concrete classes are provided by default:
 *
 *  * `ArgvInput`: The input comes from the CLI arguments (argv)
 *  * `StringInput`: The input is provided as a string
 *  * `ArrayInput`: The input is provided as an array
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Input implements \PHPStanVendor\Symfony\Component\Console\Input\InputInterface, \PHPStanVendor\Symfony\Component\Console\Input\StreamableInputInterface
{
    protected $definition;
    protected $stream;
    protected $options = array();
    protected $arguments = array();
    protected $interactive = true;

    public function __construct(\PHPStanVendor\Symfony\Component\Console\Input\InputDefinition $definition = null)
    {
        if (null === $definition) {
            $this->definition = new \PHPStanVendor\Symfony\Component\Console\Input\InputDefinition();
        } else {
            $this->bind($definition);
            $this->validate();
        }
    }

    /**
     * {@inheritdoc}
     */
    public function bind(\PHPStanVendor\Symfony\Component\Console\Input\InputDefinition $definition)
    {
        $this->arguments = array();
        $this->options = array();
        $this->definition = $definition;

        $this->parse();
    }

    /**
     * Processes command line arguments.
     */
    abstract protected function parse();

    /**
     * {@inheritdoc}
     */
    public function validate()
    {
        $definition = $this->definition;
        $givenArguments = $this->arguments;

        $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) {
            return !array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
        });

        if (count($missingArguments) > 0) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments)));
        }
    }

    /**
     * {@inheritdoc}
     */
    public function isInteractive()
    {
        return $this->interactive;
    }

    /**
     * {@inheritdoc}
     */
    public function setInteractive($interactive)
    {
        $this->interactive = (bool) $interactive;
    }

    /**
     * {@inheritdoc}
     */
    public function getArguments()
    {
        return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
    }

    /**
     * {@inheritdoc}
     */
    public function getArgument($name)
    {
        if (!$this->definition->hasArgument($name)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
        }

        return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
    }

    /**
     * {@inheritdoc}
     */
    public function setArgument($name, $value)
    {
        if (!$this->definition->hasArgument($name)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
        }

        $this->arguments[$name] = $value;
    }

    /**
     * {@inheritdoc}
     */
    public function hasArgument($name)
    {
        return $this->definition->hasArgument($name);
    }

    /**
     * {@inheritdoc}
     */
    public function getOptions()
    {
        return array_merge($this->definition->getOptionDefaults(), $this->options);
    }

    /**
     * {@inheritdoc}
     */
    public function getOption($name)
    {
        if (!$this->definition->hasOption($name)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
        }

        return array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
    }

    /**
     * {@inheritdoc}
     */
    public function setOption($name, $value)
    {
        if (!$this->definition->hasOption($name)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
        }

        $this->options[$name] = $value;
    }

    /**
     * {@inheritdoc}
     */
    public function hasOption($name)
    {
        return $this->definition->hasOption($name);
    }

    /**
     * Escapes a token through escapeshellarg if it contains unsafe chars.
     *
     * @param string $token
     *
     * @return string
     */
    public function escapeToken($token)
    {
        return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
    }

    /**
     * {@inheritdoc}
     */
    public function setStream($stream)
    {
        $this->stream = $stream;
    }

    /**
     * {@inheritdoc}
     */
    public function getStream()
    {
        return $this->stream;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Input;

/**
 * Represents a command line argument.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InputArgument
{
    const REQUIRED = 1;
    const OPTIONAL = 2;
    const IS_ARRAY = 4;

    private $name;
    private $mode;
    private $default;
    private $description;

    /**
     * @param string $name        The argument name
     * @param int    $mode        The argument mode: self::REQUIRED or self::OPTIONAL
     * @param string $description A description text
     * @param mixed  $default     The default value (for self::OPTIONAL mode only)
     *
     * @throws InvalidArgumentException When argument mode is not valid
     */
    public function __construct($name, $mode = null, $description = '', $default = null)
    {
        if (null === $mode) {
            $mode = self::OPTIONAL;
        } elseif (!is_int($mode) || $mode > 7 || $mode < 1) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
        }

        $this->name = $name;
        $this->mode = $mode;
        $this->description = $description;

        $this->setDefault($default);
    }

    /**
     * Returns the argument name.
     *
     * @return string The argument name
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Returns true if the argument is required.
     *
     * @return bool true if parameter mode is self::REQUIRED, false otherwise
     */
    public function isRequired()
    {
        return self::REQUIRED === (self::REQUIRED & $this->mode);
    }

    /**
     * Returns true if the argument can take multiple values.
     *
     * @return bool true if mode is self::IS_ARRAY, false otherwise
     */
    public function isArray()
    {
        return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
    }

    /**
     * Sets the default value.
     *
     * @param mixed $default The default value
     *
     * @throws LogicException When incorrect default value is given
     */
    public function setDefault($default = null)
    {
        if (self::REQUIRED === $this->mode && null !== $default) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
        }

        if ($this->isArray()) {
            if (null === $default) {
                $default = array();
            } elseif (!is_array($default)) {
                throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException('A default value for an array argument must be an array.');
            }
        }

        $this->default = $default;
    }

    /**
     * Returns the default value.
     *
     * @return mixed The default value
     */
    public function getDefault()
    {
        return $this->default;
    }

    /**
     * Returns the description text.
     *
     * @return string The description text
     */
    public function getDescription()
    {
        return $this->description;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Input;

/**
 * InputAwareInterface should be implemented by classes that depends on the
 * Console Input.
 *
 * @author Wouter J <waldio.webdesign@gmail.com>
 */
interface InputAwareInterface
{
    /**
     * Sets the Console Input.
     *
     * @param InputInterface
     */
    public function setInput(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Input;

/**
 * A InputDefinition represents a set of valid command line arguments and options.
 *
 * Usage:
 *
 *     $definition = new InputDefinition(array(
 *       new InputArgument('name', InputArgument::REQUIRED),
 *       new InputOption('foo', 'f', InputOption::VALUE_REQUIRED),
 *     ));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InputDefinition
{
    private $arguments;
    private $requiredCount;
    private $hasAnArrayArgument = false;
    private $hasOptional;
    private $options;
    private $shortcuts;

    /**
     * @param array $definition An array of InputArgument and InputOption instance
     */
    public function __construct(array $definition = array())
    {
        $this->setDefinition($definition);
    }

    /**
     * Sets the definition of the input.
     */
    public function setDefinition(array $definition)
    {
        $arguments = array();
        $options = array();
        foreach ($definition as $item) {
            if ($item instanceof \PHPStanVendor\Symfony\Component\Console\Input\InputOption) {
                $options[] = $item;
            } else {
                $arguments[] = $item;
            }
        }

        $this->setArguments($arguments);
        $this->setOptions($options);
    }

    /**
     * Sets the InputArgument objects.
     *
     * @param InputArgument[] $arguments An array of InputArgument objects
     */
    public function setArguments($arguments = array())
    {
        $this->arguments = array();
        $this->requiredCount = 0;
        $this->hasOptional = false;
        $this->hasAnArrayArgument = false;
        $this->addArguments($arguments);
    }

    /**
     * Adds an array of InputArgument objects.
     *
     * @param InputArgument[] $arguments An array of InputArgument objects
     */
    public function addArguments($arguments = array())
    {
        if (null !== $arguments) {
            foreach ($arguments as $argument) {
                $this->addArgument($argument);
            }
        }
    }

    /**
     * @throws LogicException When incorrect argument is given
     */
    public function addArgument(\PHPStanVendor\Symfony\Component\Console\Input\InputArgument $argument)
    {
        if (isset($this->arguments[$argument->getName()])) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
        }

        if ($this->hasAnArrayArgument) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException('Cannot add an argument after an array argument.');
        }

        if ($argument->isRequired() && $this->hasOptional) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException('Cannot add a required argument after an optional one.');
        }

        if ($argument->isArray()) {
            $this->hasAnArrayArgument = true;
        }

        if ($argument->isRequired()) {
            ++$this->requiredCount;
        } else {
            $this->hasOptional = true;
        }

        $this->arguments[$argument->getName()] = $argument;
    }

    /**
     * Returns an InputArgument by name or by position.
     *
     * @param string|int $name The InputArgument name or position
     *
     * @return InputArgument An InputArgument object
     *
     * @throws InvalidArgumentException When argument given doesn't exist
     */
    public function getArgument($name)
    {
        if (!$this->hasArgument($name)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
        }

        $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;

        return $arguments[$name];
    }

    /**
     * Returns true if an InputArgument object exists by name or position.
     *
     * @param string|int $name The InputArgument name or position
     *
     * @return bool true if the InputArgument object exists, false otherwise
     */
    public function hasArgument($name)
    {
        $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;

        return isset($arguments[$name]);
    }

    /**
     * Gets the array of InputArgument objects.
     *
     * @return InputArgument[] An array of InputArgument objects
     */
    public function getArguments()
    {
        return $this->arguments;
    }

    /**
     * Returns the number of InputArguments.
     *
     * @return int The number of InputArguments
     */
    public function getArgumentCount()
    {
        return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
    }

    /**
     * Returns the number of required InputArguments.
     *
     * @return int The number of required InputArguments
     */
    public function getArgumentRequiredCount()
    {
        return $this->requiredCount;
    }

    /**
     * Gets the default values.
     *
     * @return array An array of default values
     */
    public function getArgumentDefaults()
    {
        $values = array();
        foreach ($this->arguments as $argument) {
            $values[$argument->getName()] = $argument->getDefault();
        }

        return $values;
    }

    /**
     * Sets the InputOption objects.
     *
     * @param InputOption[] $options An array of InputOption objects
     */
    public function setOptions($options = array())
    {
        $this->options = array();
        $this->shortcuts = array();
        $this->addOptions($options);
    }

    /**
     * Adds an array of InputOption objects.
     *
     * @param InputOption[] $options An array of InputOption objects
     */
    public function addOptions($options = array())
    {
        foreach ($options as $option) {
            $this->addOption($option);
        }
    }

    /**
     * @throws LogicException When option given already exist
     */
    public function addOption(\PHPStanVendor\Symfony\Component\Console\Input\InputOption $option)
    {
        if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
        }

        if ($option->getShortcut()) {
            foreach (explode('|', $option->getShortcut()) as $shortcut) {
                if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
                    throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
                }
            }
        }

        $this->options[$option->getName()] = $option;
        if ($option->getShortcut()) {
            foreach (explode('|', $option->getShortcut()) as $shortcut) {
                $this->shortcuts[$shortcut] = $option->getName();
            }
        }
    }

    /**
     * Returns an InputOption by name.
     *
     * @param string $name The InputOption name
     *
     * @return InputOption A InputOption object
     *
     * @throws InvalidArgumentException When option given doesn't exist
     */
    public function getOption($name)
    {
        if (!$this->hasOption($name)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
        }

        return $this->options[$name];
    }

    /**
     * Returns true if an InputOption object exists by name.
     *
     * This method can't be used to check if the user included the option when
     * executing the command (use getOption() instead).
     *
     * @param string $name The InputOption name
     *
     * @return bool true if the InputOption object exists, false otherwise
     */
    public function hasOption($name)
    {
        return isset($this->options[$name]);
    }

    /**
     * Gets the array of InputOption objects.
     *
     * @return InputOption[] An array of InputOption objects
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * Returns true if an InputOption object exists by shortcut.
     *
     * @param string $name The InputOption shortcut
     *
     * @return bool true if the InputOption object exists, false otherwise
     */
    public function hasShortcut($name)
    {
        return isset($this->shortcuts[$name]);
    }

    /**
     * Gets an InputOption by shortcut.
     *
     * @param string $shortcut The Shortcut name
     *
     * @return InputOption An InputOption object
     */
    public function getOptionForShortcut($shortcut)
    {
        return $this->getOption($this->shortcutToName($shortcut));
    }

    /**
     * Gets an array of default values.
     *
     * @return array An array of all default values
     */
    public function getOptionDefaults()
    {
        $values = array();
        foreach ($this->options as $option) {
            $values[$option->getName()] = $option->getDefault();
        }

        return $values;
    }

    /**
     * Returns the InputOption name given a shortcut.
     *
     * @param string $shortcut The shortcut
     *
     * @return string The InputOption name
     *
     * @throws InvalidArgumentException When option given does not exist
     */
    private function shortcutToName($shortcut)
    {
        if (!isset($this->shortcuts[$shortcut])) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
        }

        return $this->shortcuts[$shortcut];
    }

    /**
     * Gets the synopsis.
     *
     * @param bool $short Whether to return the short version (with options folded) or not
     *
     * @return string The synopsis
     */
    public function getSynopsis($short = false)
    {
        $elements = array();

        if ($short && $this->getOptions()) {
            $elements[] = '[options]';
        } elseif (!$short) {
            foreach ($this->getOptions() as $option) {
                $value = '';
                if ($option->acceptValue()) {
                    $value = sprintf(
                        ' %s%s%s',
                        $option->isValueOptional() ? '[' : '',
                        strtoupper($option->getName()),
                        $option->isValueOptional() ? ']' : ''
                    );
                }

                $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
                $elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value);
            }
        }

        if (count($elements) && $this->getArguments()) {
            $elements[] = '[--]';
        }

        foreach ($this->getArguments() as $argument) {
            $element = '<'.$argument->getName().'>';
            if (!$argument->isRequired()) {
                $element = '['.$element.']';
            } elseif ($argument->isArray()) {
                $element = $element.' ('.$element.')';
            }

            if ($argument->isArray()) {
                $element .= '...';
            }

            $elements[] = $element;
        }

        return implode(' ', $elements);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Input;

/**
 * InputInterface is the interface implemented by all input classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface InputInterface
{
    /**
     * Returns the first argument from the raw parameters (not parsed).
     *
     * @return string|null The value of the first argument or null otherwise
     */
    public function getFirstArgument();

    /**
     * Returns true if the raw parameters (not parsed) contain a value.
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     *
     * @param string|array $values     The values to look for in the raw parameters (can be an array)
     * @param bool         $onlyParams Only check real parameters, skip those following an end of options (--) signal
     *
     * @return bool true if the value is contained in the raw parameters
     */
    public function hasParameterOption($values, $onlyParams = false);

    /**
     * Returns the value of a raw option (not parsed).
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     *
     * @param string|array $values     The value(s) to look for in the raw parameters (can be an array)
     * @param mixed        $default    The default value to return if no result is found
     * @param bool         $onlyParams Only check real parameters, skip those following an end of options (--) signal
     *
     * @return mixed The option value
     */
    public function getParameterOption($values, $default = false, $onlyParams = false);

    /**
     * Binds the current Input instance with the given arguments and options.
     */
    public function bind(\PHPStanVendor\Symfony\Component\Console\Input\InputDefinition $definition);

    /**
     * Validates the input.
     *
     * @throws RuntimeException When not enough arguments are given
     */
    public function validate();

    /**
     * Returns all the given arguments merged with the default values.
     *
     * @return array
     */
    public function getArguments();

    /**
     * Returns the argument value for a given argument name.
     *
     * @param string $name The argument name
     *
     * @return mixed The argument value
     *
     * @throws InvalidArgumentException When argument given doesn't exist
     */
    public function getArgument($name);

    /**
     * Sets an argument value by name.
     *
     * @param string $name  The argument name
     * @param string $value The argument value
     *
     * @throws InvalidArgumentException When argument given doesn't exist
     */
    public function setArgument($name, $value);

    /**
     * Returns true if an InputArgument object exists by name or position.
     *
     * @param string|int $name The InputArgument name or position
     *
     * @return bool true if the InputArgument object exists, false otherwise
     */
    public function hasArgument($name);

    /**
     * Returns all the given options merged with the default values.
     *
     * @return array
     */
    public function getOptions();

    /**
     * Returns the option value for a given option name.
     *
     * @param string $name The option name
     *
     * @return mixed The option value
     *
     * @throws InvalidArgumentException When option given doesn't exist
     */
    public function getOption($name);

    /**
     * Sets an option value by name.
     *
     * @param string      $name  The option name
     * @param string|bool $value The option value
     *
     * @throws InvalidArgumentException When option given doesn't exist
     */
    public function setOption($name, $value);

    /**
     * Returns true if an InputOption object exists by name.
     *
     * @param string $name The InputOption name
     *
     * @return bool true if the InputOption object exists, false otherwise
     */
    public function hasOption($name);

    /**
     * Is this input means interactive?
     *
     * @return bool
     */
    public function isInteractive();

    /**
     * Sets the input interactivity.
     *
     * @param bool $interactive If the input should be interactive
     */
    public function setInteractive($interactive);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Input;

/**
 * Represents a command line option.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InputOption
{
    const VALUE_NONE = 1;
    const VALUE_REQUIRED = 2;
    const VALUE_OPTIONAL = 4;
    const VALUE_IS_ARRAY = 8;

    private $name;
    private $shortcut;
    private $mode;
    private $default;
    private $description;

    /**
     * @param string       $name        The option name
     * @param string|array $shortcut    The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
     * @param int          $mode        The option mode: One of the VALUE_* constants
     * @param string       $description A description text
     * @param mixed        $default     The default value (must be null for self::VALUE_NONE)
     *
     * @throws InvalidArgumentException If option mode is invalid or incompatible
     */
    public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
    {
        if (0 === strpos($name, '--')) {
            $name = substr($name, 2);
        }

        if (empty($name)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException('An option name cannot be empty.');
        }

        if (empty($shortcut)) {
            $shortcut = null;
        }

        if (null !== $shortcut) {
            if (is_array($shortcut)) {
                $shortcut = implode('|', $shortcut);
            }
            $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
            $shortcuts = array_filter($shortcuts);
            $shortcut = implode('|', $shortcuts);

            if (empty($shortcut)) {
                throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException('An option shortcut cannot be empty.');
            }
        }

        if (null === $mode) {
            $mode = self::VALUE_NONE;
        } elseif (!is_int($mode) || $mode > 15 || $mode < 1) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
        }

        $this->name = $name;
        $this->shortcut = $shortcut;
        $this->mode = $mode;
        $this->description = $description;

        if ($this->isArray() && !$this->acceptValue()) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
        }

        $this->setDefault($default);
    }

    /**
     * Returns the option shortcut.
     *
     * @return string The shortcut
     */
    public function getShortcut()
    {
        return $this->shortcut;
    }

    /**
     * Returns the option name.
     *
     * @return string The name
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Returns true if the option accepts a value.
     *
     * @return bool true if value mode is not self::VALUE_NONE, false otherwise
     */
    public function acceptValue()
    {
        return $this->isValueRequired() || $this->isValueOptional();
    }

    /**
     * Returns true if the option requires a value.
     *
     * @return bool true if value mode is self::VALUE_REQUIRED, false otherwise
     */
    public function isValueRequired()
    {
        return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
    }

    /**
     * Returns true if the option takes an optional value.
     *
     * @return bool true if value mode is self::VALUE_OPTIONAL, false otherwise
     */
    public function isValueOptional()
    {
        return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
    }

    /**
     * Returns true if the option can take multiple values.
     *
     * @return bool true if mode is self::VALUE_IS_ARRAY, false otherwise
     */
    public function isArray()
    {
        return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
    }

    /**
     * Sets the default value.
     *
     * @param mixed $default The default value
     *
     * @throws LogicException When incorrect default value is given
     */
    public function setDefault($default = null)
    {
        if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
        }

        if ($this->isArray()) {
            if (null === $default) {
                $default = array();
            } elseif (!is_array($default)) {
                throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException('A default value for an array option must be an array.');
            }
        }

        $this->default = $this->acceptValue() ? $default : false;
    }

    /**
     * Returns the default value.
     *
     * @return mixed The default value
     */
    public function getDefault()
    {
        return $this->default;
    }

    /**
     * Returns the description text.
     *
     * @return string The description text
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * Checks whether the given option equals this one.
     *
     * @return bool
     */
    public function equals(\PHPStanVendor\Symfony\Component\Console\Input\InputOption $option)
    {
        return $option->getName() === $this->getName()
            && $option->getShortcut() === $this->getShortcut()
            && $option->getDefault() === $this->getDefault()
            && $option->isArray() === $this->isArray()
            && $option->isValueRequired() === $this->isValueRequired()
            && $option->isValueOptional() === $this->isValueOptional()
        ;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Input;

/**
 * StreamableInputInterface is the interface implemented by all input classes
 * that have an input stream.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
interface StreamableInputInterface extends \PHPStanVendor\Symfony\Component\Console\Input\InputInterface
{
    /**
     * Sets the input stream to read from when interacting with the user.
     *
     * This is mainly useful for testing purpose.
     *
     * @param resource $stream The input stream
     */
    public function setStream($stream);

    /**
     * Returns the input stream.
     *
     * @return resource|null
     */
    public function getStream();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Input;

/**
 * StringInput represents an input provided as a string.
 *
 * Usage:
 *
 *     $input = new StringInput('foo --bar="foobar"');
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class StringInput extends \PHPStanVendor\Symfony\Component\Console\Input\ArgvInput
{
    const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
    const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';

    /**
     * @param string $input An array of parameters from the CLI (in the argv format)
     */
    public function __construct($input)
    {
        parent::__construct(array());

        $this->setTokens($this->tokenize($input));
    }

    /**
     * Tokenizes a string.
     *
     * @param string $input The input to tokenize
     *
     * @return array An array of tokens
     *
     * @throws InvalidArgumentException When unable to parse input (should never happen)
     */
    private function tokenize($input)
    {
        $tokens = array();
        $length = strlen($input);
        $cursor = 0;
        while ($cursor < $length) {
            if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
            } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
                $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2)));
            } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
                $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
            } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
                $tokens[] = stripcslashes($match[1]);
            } else {
                // should never happen
                throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
            }

            $cursor += strlen($match[0]);
        }

        return $tokens;
    }
}

Copyright (c) 2004-2018 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Logger;

/**
 * PSR-3 compliant console logger.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @see http://www.php-fig.org/psr/psr-3/
 */
class ConsoleLogger extends \Psr\Log\AbstractLogger
{
    const INFO = 'info';
    const ERROR = 'error';

    private $output;
    private $verbosityLevelMap = array(
        \Psr\Log\LogLevel::EMERGENCY => \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_NORMAL,
        \Psr\Log\LogLevel::ALERT => \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_NORMAL,
        \Psr\Log\LogLevel::CRITICAL => \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_NORMAL,
        \Psr\Log\LogLevel::ERROR => \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_NORMAL,
        \Psr\Log\LogLevel::WARNING => \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_NORMAL,
        \Psr\Log\LogLevel::NOTICE => \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE,
        \Psr\Log\LogLevel::INFO => \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERY_VERBOSE,
        \Psr\Log\LogLevel::DEBUG => \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_DEBUG,
    );
    private $formatLevelMap = array(
        \Psr\Log\LogLevel::EMERGENCY => self::ERROR,
        \Psr\Log\LogLevel::ALERT => self::ERROR,
        \Psr\Log\LogLevel::CRITICAL => self::ERROR,
        \Psr\Log\LogLevel::ERROR => self::ERROR,
        \Psr\Log\LogLevel::WARNING => self::INFO,
        \Psr\Log\LogLevel::NOTICE => self::INFO,
        \Psr\Log\LogLevel::INFO => self::INFO,
        \Psr\Log\LogLevel::DEBUG => self::INFO,
    );
    private $errored = false;

    public function __construct(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array())
    {
        $this->output = $output;
        $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
        $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
    }

    /**
     * {@inheritdoc}
     */
    public function log($level, $message, array $context = array())
    {
        if (!isset($this->verbosityLevelMap[$level])) {
            throw new \Psr\Log\InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level));
        }

        $output = $this->output;

        // Write to the error output if necessary and available
        if (self::ERROR === $this->formatLevelMap[$level]) {
            if ($this->output instanceof \PHPStanVendor\Symfony\Component\Console\Output\ConsoleOutputInterface) {
                $output = $output->getErrorOutput();
            }
            $this->errored = true;
        }

        // the if condition check isn't necessary -- it's the same one that $output will do internally anyway.
        // We only do it for efficiency here as the message formatting is relatively expensive.
        if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
            $output->writeln(sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)), $this->verbosityLevelMap[$level]);
        }
    }

    /**
     * Returns true when any messages have been logged at error levels.
     *
     * @return bool
     */
    public function hasErrored()
    {
        return $this->errored;
    }

    /**
     * Interpolates context values into the message placeholders.
     *
     * @author PHP Framework Interoperability Group
     *
     * @param string $message
     * @param array  $context
     *
     * @return string
     */
    private function interpolate($message, array $context)
    {
        if (false === strpos($message, '{')) {
            return $message;
        }

        $replacements = array();
        foreach ($context as $key => $val) {
            if (null === $val || is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) {
                $replacements["{{$key}}"] = $val;
            } elseif ($val instanceof \DateTimeInterface) {
                $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339);
            } elseif (\is_object($val)) {
                $replacements["{{$key}}"] = '[object '.\get_class($val).']';
            } else {
                $replacements["{{$key}}"] = '['.\gettype($val).']';
            }
        }

        return strtr($message, $replacements);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Output;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class BufferedOutput extends \PHPStanVendor\Symfony\Component\Console\Output\Output
{
    private $buffer = '';

    /**
     * Empties buffer and returns its content.
     *
     * @return string
     */
    public function fetch()
    {
        $content = $this->buffer;
        $this->buffer = '';

        return $content;
    }

    /**
     * {@inheritdoc}
     */
    protected function doWrite($message, $newline)
    {
        $this->buffer .= $message;

        if ($newline) {
            $this->buffer .= PHP_EOL;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Output;

/**
 * ConsoleOutput is the default class for all CLI output. It uses STDOUT and STDERR.
 *
 * This class is a convenient wrapper around `StreamOutput` for both STDOUT and STDERR.
 *
 *     $output = new ConsoleOutput();
 *
 * This is equivalent to:
 *
 *     $output = new StreamOutput(fopen('php://stdout', 'w'));
 *     $stdErr = new StreamOutput(fopen('php://stderr', 'w'));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ConsoleOutput extends \PHPStanVendor\Symfony\Component\Console\Output\StreamOutput implements \PHPStanVendor\Symfony\Component\Console\Output\ConsoleOutputInterface
{
    private $stderr;

    /**
     * @param int                           $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param bool|null                     $decorated Whether to decorate messages (null for auto-guessing)
     * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
     */
    public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter = null)
    {
        parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);

        $actualDecorated = $this->isDecorated();
        $this->stderr = new \PHPStanVendor\Symfony\Component\Console\Output\StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());

        if (null === $decorated) {
            $this->setDecorated($actualDecorated && $this->stderr->isDecorated());
        }
    }

    /**
     * {@inheritdoc}
     */
    public function setDecorated($decorated)
    {
        parent::setDecorated($decorated);
        $this->stderr->setDecorated($decorated);
    }

    /**
     * {@inheritdoc}
     */
    public function setFormatter(\PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter)
    {
        parent::setFormatter($formatter);
        $this->stderr->setFormatter($formatter);
    }

    /**
     * {@inheritdoc}
     */
    public function setVerbosity($level)
    {
        parent::setVerbosity($level);
        $this->stderr->setVerbosity($level);
    }

    /**
     * {@inheritdoc}
     */
    public function getErrorOutput()
    {
        return $this->stderr;
    }

    /**
     * {@inheritdoc}
     */
    public function setErrorOutput(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $error)
    {
        $this->stderr = $error;
    }

    /**
     * Returns true if current environment supports writing console output to
     * STDOUT.
     *
     * @return bool
     */
    protected function hasStdoutSupport()
    {
        return false === $this->isRunningOS400();
    }

    /**
     * Returns true if current environment supports writing console output to
     * STDERR.
     *
     * @return bool
     */
    protected function hasStderrSupport()
    {
        return false === $this->isRunningOS400();
    }

    /**
     * Checks if current executing environment is IBM iSeries (OS400), which
     * doesn't properly convert character-encodings between ASCII to EBCDIC.
     *
     * @return bool
     */
    private function isRunningOS400()
    {
        $checks = array(
            function_exists('php_uname') ? php_uname('s') : '',
            getenv('OSTYPE'),
            PHP_OS,
        );

        return false !== stripos(implode(';', $checks), 'OS400');
    }

    /**
     * @return resource
     */
    private function openOutputStream()
    {
        if (!$this->hasStdoutSupport()) {
            return fopen('php://output', 'w');
        }

        return @fopen('php://stdout', 'w') ?: fopen('php://output', 'w');
    }

    /**
     * @return resource
     */
    private function openErrorStream()
    {
        return fopen($this->hasStderrSupport() ? 'php://stderr' : 'php://output', 'w');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Output;

/**
 * ConsoleOutputInterface is the interface implemented by ConsoleOutput class.
 * This adds information about stderr output stream.
 *
 * @author Dariusz Górecki <darek.krk@gmail.com>
 */
interface ConsoleOutputInterface extends \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface
{
    /**
     * Gets the OutputInterface for errors.
     *
     * @return OutputInterface
     */
    public function getErrorOutput();

    public function setErrorOutput(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $error);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Output;

/**
 * NullOutput suppresses all output.
 *
 *     $output = new NullOutput();
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 */
class NullOutput implements \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface
{
    /**
     * {@inheritdoc}
     */
    public function setFormatter(\PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter)
    {
        // do nothing
    }

    /**
     * {@inheritdoc}
     */
    public function getFormatter()
    {
        // to comply with the interface we must return a OutputFormatterInterface
        return new \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatter();
    }

    /**
     * {@inheritdoc}
     */
    public function setDecorated($decorated)
    {
        // do nothing
    }

    /**
     * {@inheritdoc}
     */
    public function isDecorated()
    {
        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function setVerbosity($level)
    {
        // do nothing
    }

    /**
     * {@inheritdoc}
     */
    public function getVerbosity()
    {
        return self::VERBOSITY_QUIET;
    }

    /**
     * {@inheritdoc}
     */
    public function isQuiet()
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function isVerbose()
    {
        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function isVeryVerbose()
    {
        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function isDebug()
    {
        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function writeln($messages, $options = self::OUTPUT_NORMAL)
    {
        // do nothing
    }

    /**
     * {@inheritdoc}
     */
    public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
    {
        // do nothing
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Output;

/**
 * Base class for output classes.
 *
 * There are five levels of verbosity:
 *
 *  * normal: no option passed (normal output)
 *  * verbose: -v (more output)
 *  * very verbose: -vv (highly extended output)
 *  * debug: -vvv (all debug output)
 *  * quiet: -q (no output)
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Output implements \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface
{
    private $verbosity;
    private $formatter;

    /**
     * @param int                           $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param bool                          $decorated Whether to decorate messages
     * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
     */
    public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter = null)
    {
        $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
        $this->formatter = $formatter ?: new \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatter();
        $this->formatter->setDecorated($decorated);
    }

    /**
     * {@inheritdoc}
     */
    public function setFormatter(\PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter)
    {
        $this->formatter = $formatter;
    }

    /**
     * {@inheritdoc}
     */
    public function getFormatter()
    {
        return $this->formatter;
    }

    /**
     * {@inheritdoc}
     */
    public function setDecorated($decorated)
    {
        $this->formatter->setDecorated($decorated);
    }

    /**
     * {@inheritdoc}
     */
    public function isDecorated()
    {
        return $this->formatter->isDecorated();
    }

    /**
     * {@inheritdoc}
     */
    public function setVerbosity($level)
    {
        $this->verbosity = (int) $level;
    }

    /**
     * {@inheritdoc}
     */
    public function getVerbosity()
    {
        return $this->verbosity;
    }

    /**
     * {@inheritdoc}
     */
    public function isQuiet()
    {
        return self::VERBOSITY_QUIET === $this->verbosity;
    }

    /**
     * {@inheritdoc}
     */
    public function isVerbose()
    {
        return self::VERBOSITY_VERBOSE <= $this->verbosity;
    }

    /**
     * {@inheritdoc}
     */
    public function isVeryVerbose()
    {
        return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
    }

    /**
     * {@inheritdoc}
     */
    public function isDebug()
    {
        return self::VERBOSITY_DEBUG <= $this->verbosity;
    }

    /**
     * {@inheritdoc}
     */
    public function writeln($messages, $options = self::OUTPUT_NORMAL)
    {
        $this->write($messages, true, $options);
    }

    /**
     * {@inheritdoc}
     */
    public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
    {
        $messages = (array) $messages;

        $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN;
        $type = $types & $options ?: self::OUTPUT_NORMAL;

        $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG;
        $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL;

        if ($verbosity > $this->getVerbosity()) {
            return;
        }

        foreach ($messages as $message) {
            switch ($type) {
                case \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::OUTPUT_NORMAL:
                    $message = $this->formatter->format($message);
                    break;
                case \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::OUTPUT_RAW:
                    break;
                case \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface::OUTPUT_PLAIN:
                    $message = strip_tags($this->formatter->format($message));
                    break;
            }

            $this->doWrite($message, $newline);
        }
    }

    /**
     * Writes a message to the output.
     *
     * @param string $message A message to write to the output
     * @param bool   $newline Whether to add a newline or not
     */
    abstract protected function doWrite($message, $newline);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Output;

/**
 * OutputInterface is the interface implemented by all Output classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface OutputInterface
{
    const VERBOSITY_QUIET = 16;
    const VERBOSITY_NORMAL = 32;
    const VERBOSITY_VERBOSE = 64;
    const VERBOSITY_VERY_VERBOSE = 128;
    const VERBOSITY_DEBUG = 256;

    const OUTPUT_NORMAL = 1;
    const OUTPUT_RAW = 2;
    const OUTPUT_PLAIN = 4;

    /**
     * Writes a message to the output.
     *
     * @param string|array $messages The message as an array of lines or a single string
     * @param bool         $newline  Whether to add a newline
     * @param int          $options  A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL
     */
    public function write($messages, $newline = false, $options = 0);

    /**
     * Writes a message to the output and adds a newline at the end.
     *
     * @param string|array $messages The message as an array of lines of a single string
     * @param int          $options  A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL
     */
    public function writeln($messages, $options = 0);

    /**
     * Sets the verbosity of the output.
     *
     * @param int $level The level of verbosity (one of the VERBOSITY constants)
     */
    public function setVerbosity($level);

    /**
     * Gets the current verbosity of the output.
     *
     * @return int The current level of verbosity (one of the VERBOSITY constants)
     */
    public function getVerbosity();

    /**
     * Returns whether verbosity is quiet (-q).
     *
     * @return bool true if verbosity is set to VERBOSITY_QUIET, false otherwise
     */
    public function isQuiet();

    /**
     * Returns whether verbosity is verbose (-v).
     *
     * @return bool true if verbosity is set to VERBOSITY_VERBOSE, false otherwise
     */
    public function isVerbose();

    /**
     * Returns whether verbosity is very verbose (-vv).
     *
     * @return bool true if verbosity is set to VERBOSITY_VERY_VERBOSE, false otherwise
     */
    public function isVeryVerbose();

    /**
     * Returns whether verbosity is debug (-vvv).
     *
     * @return bool true if verbosity is set to VERBOSITY_DEBUG, false otherwise
     */
    public function isDebug();

    /**
     * Sets the decorated flag.
     *
     * @param bool $decorated Whether to decorate the messages
     */
    public function setDecorated($decorated);

    /**
     * Gets the decorated flag.
     *
     * @return bool true if the output will decorate messages, false otherwise
     */
    public function isDecorated();

    public function setFormatter(\PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter);

    /**
     * Returns current output formatter instance.
     *
     * @return OutputFormatterInterface
     */
    public function getFormatter();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Output;

/**
 * StreamOutput writes the output to a given stream.
 *
 * Usage:
 *
 * $output = new StreamOutput(fopen('php://stdout', 'w'));
 *
 * As `StreamOutput` can use any stream, you can also use a file:
 *
 * $output = new StreamOutput(fopen('/path/to/output.log', 'a', false));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class StreamOutput extends \PHPStanVendor\Symfony\Component\Console\Output\Output
{
    private $stream;

    /**
     * @param resource                      $stream    A stream resource
     * @param int                           $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param bool|null                     $decorated Whether to decorate messages (null for auto-guessing)
     * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
     *
     * @throws InvalidArgumentException When first argument is not a real stream
     */
    public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter = null)
    {
        if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
        }

        $this->stream = $stream;

        if (null === $decorated) {
            $decorated = $this->hasColorSupport();
        }

        parent::__construct($verbosity, $decorated, $formatter);
    }

    /**
     * Gets the stream attached to this StreamOutput instance.
     *
     * @return resource A stream resource
     */
    public function getStream()
    {
        return $this->stream;
    }

    /**
     * {@inheritdoc}
     */
    protected function doWrite($message, $newline)
    {
        if (false === @fwrite($this->stream, $message) || ($newline && (false === @fwrite($this->stream, PHP_EOL)))) {
            // should never happen
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\RuntimeException('Unable to write output.');
        }

        fflush($this->stream);
    }

    /**
     * Returns true if the stream supports colorization.
     *
     * Colorization is disabled if not supported by the stream:
     *
     *  -  Windows != 10.0.10586 without Ansicon, ConEmu or Mintty
     *  -  non tty consoles
     *
     * @return bool true if the stream supports colorization, false otherwise
     */
    protected function hasColorSupport()
    {
        if (DIRECTORY_SEPARATOR === '\\') {
            return
                '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD
                || false !== getenv('ANSICON')
                || 'ON' === getenv('ConEmuANSI')
                || 'xterm' === getenv('TERM');
        }

        return function_exists('posix_isatty') && @posix_isatty($this->stream);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Question;

/**
 * Represents a choice question.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ChoiceQuestion extends \PHPStanVendor\Symfony\Component\Console\Question\Question
{
    private $choices;
    private $multiselect = false;
    private $prompt = ' > ';
    private $errorMessage = 'Value "%s" is invalid';

    /**
     * @param string $question The question to ask to the user
     * @param array  $choices  The list of available choices
     * @param mixed  $default  The default answer to return
     */
    public function __construct($question, array $choices, $default = null)
    {
        if (!$choices) {
            throw new \LogicException('Choice question must have at least 1 choice available.');
        }

        parent::__construct($question, $default);

        $this->choices = $choices;
        $this->setValidator($this->getDefaultValidator());
        $this->setAutocompleterValues($choices);
    }

    /**
     * Returns available choices.
     *
     * @return array
     */
    public function getChoices()
    {
        return $this->choices;
    }

    /**
     * Sets multiselect option.
     *
     * When multiselect is set to true, multiple choices can be answered.
     *
     * @param bool $multiselect
     *
     * @return $this
     */
    public function setMultiselect($multiselect)
    {
        $this->multiselect = $multiselect;
        $this->setValidator($this->getDefaultValidator());

        return $this;
    }

    /**
     * Returns whether the choices are multiselect.
     *
     * @return bool
     */
    public function isMultiselect()
    {
        return $this->multiselect;
    }

    /**
     * Gets the prompt for choices.
     *
     * @return string
     */
    public function getPrompt()
    {
        return $this->prompt;
    }

    /**
     * Sets the prompt for choices.
     *
     * @param string $prompt
     *
     * @return $this
     */
    public function setPrompt($prompt)
    {
        $this->prompt = $prompt;

        return $this;
    }

    /**
     * Sets the error message for invalid values.
     *
     * The error message has a string placeholder (%s) for the invalid value.
     *
     * @param string $errorMessage
     *
     * @return $this
     */
    public function setErrorMessage($errorMessage)
    {
        $this->errorMessage = $errorMessage;
        $this->setValidator($this->getDefaultValidator());

        return $this;
    }

    /**
     * Returns the default answer validator.
     *
     * @return callable
     */
    private function getDefaultValidator()
    {
        $choices = $this->choices;
        $errorMessage = $this->errorMessage;
        $multiselect = $this->multiselect;
        $isAssoc = $this->isAssoc($choices);

        return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
            // Collapse all spaces.
            $selectedChoices = str_replace(' ', '', $selected);

            if ($multiselect) {
                // Check for a separated comma values
                if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selectedChoices, $matches)) {
                    throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf($errorMessage, $selected));
                }
                $selectedChoices = explode(',', $selectedChoices);
            } else {
                $selectedChoices = array($selected);
            }

            $multiselectChoices = array();
            foreach ($selectedChoices as $value) {
                $results = array();
                foreach ($choices as $key => $choice) {
                    if ($choice === $value) {
                        $results[] = $key;
                    }
                }

                if (count($results) > 1) {
                    throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results)));
                }

                $result = array_search($value, $choices);

                if (!$isAssoc) {
                    if (false !== $result) {
                        $result = $choices[$result];
                    } elseif (isset($choices[$value])) {
                        $result = $choices[$value];
                    }
                } elseif (false === $result && isset($choices[$value])) {
                    $result = $value;
                }

                if (false === $result) {
                    throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException(sprintf($errorMessage, $value));
                }

                $multiselectChoices[] = (string) $result;
            }

            if ($multiselect) {
                return $multiselectChoices;
            }

            return current($multiselectChoices);
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Question;

/**
 * Represents a yes/no question.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ConfirmationQuestion extends \PHPStanVendor\Symfony\Component\Console\Question\Question
{
    private $trueAnswerRegex;

    /**
     * @param string $question        The question to ask to the user
     * @param bool   $default         The default answer to return, true or false
     * @param string $trueAnswerRegex A regex to match the "yes" answer
     */
    public function __construct($question, $default = true, $trueAnswerRegex = '/^y/i')
    {
        parent::__construct($question, (bool) $default);

        $this->trueAnswerRegex = $trueAnswerRegex;
        $this->setNormalizer($this->getDefaultNormalizer());
    }

    /**
     * Returns the default answer normalizer.
     *
     * @return callable
     */
    private function getDefaultNormalizer()
    {
        $default = $this->getDefault();
        $regex = $this->trueAnswerRegex;

        return function ($answer) use ($default, $regex) {
            if (is_bool($answer)) {
                return $answer;
            }

            $answerIsTrue = (bool) preg_match($regex, $answer);
            if (false === $default) {
                return $answer && $answerIsTrue;
            }

            return !$answer || $answerIsTrue;
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Question;

/**
 * Represents a Question.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Question
{
    private $question;
    private $attempts;
    private $hidden = false;
    private $hiddenFallback = true;
    private $autocompleterValues;
    private $validator;
    private $default;
    private $normalizer;

    /**
     * @param string $question The question to ask to the user
     * @param mixed  $default  The default answer to return if the user enters nothing
     */
    public function __construct($question, $default = null)
    {
        $this->question = $question;
        $this->default = $default;
    }

    /**
     * Returns the question.
     *
     * @return string
     */
    public function getQuestion()
    {
        return $this->question;
    }

    /**
     * Returns the default answer.
     *
     * @return mixed
     */
    public function getDefault()
    {
        return $this->default;
    }

    /**
     * Returns whether the user response must be hidden.
     *
     * @return bool
     */
    public function isHidden()
    {
        return $this->hidden;
    }

    /**
     * Sets whether the user response must be hidden or not.
     *
     * @param bool $hidden
     *
     * @return $this
     *
     * @throws LogicException In case the autocompleter is also used
     */
    public function setHidden($hidden)
    {
        if ($this->autocompleterValues) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException('A hidden question cannot use the autocompleter.');
        }

        $this->hidden = (bool) $hidden;

        return $this;
    }

    /**
     * In case the response can not be hidden, whether to fallback on non-hidden question or not.
     *
     * @return bool
     */
    public function isHiddenFallback()
    {
        return $this->hiddenFallback;
    }

    /**
     * Sets whether to fallback on non-hidden question if the response can not be hidden.
     *
     * @param bool $fallback
     *
     * @return $this
     */
    public function setHiddenFallback($fallback)
    {
        $this->hiddenFallback = (bool) $fallback;

        return $this;
    }

    /**
     * Gets values for the autocompleter.
     *
     * @return null|iterable
     */
    public function getAutocompleterValues()
    {
        return $this->autocompleterValues;
    }

    /**
     * Sets values for the autocompleter.
     *
     * @param null|iterable $values
     *
     * @return $this
     *
     * @throws InvalidArgumentException
     * @throws LogicException
     */
    public function setAutocompleterValues($values)
    {
        if (is_array($values)) {
            $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);
        }

        if (null !== $values && !is_array($values) && !$values instanceof \Traversable) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException('Autocompleter values can be either an array, `null` or a `Traversable` object.');
        }

        if ($this->hidden) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\LogicException('A hidden question cannot use the autocompleter.');
        }

        $this->autocompleterValues = $values;

        return $this;
    }

    /**
     * Sets a validator for the question.
     *
     * @param null|callable $validator
     *
     * @return $this
     */
    public function setValidator(callable $validator = null)
    {
        $this->validator = $validator;

        return $this;
    }

    /**
     * Gets the validator for the question.
     *
     * @return null|callable
     */
    public function getValidator()
    {
        return $this->validator;
    }

    /**
     * Sets the maximum number of attempts.
     *
     * Null means an unlimited number of attempts.
     *
     * @param null|int $attempts
     *
     * @return $this
     *
     * @throws InvalidArgumentException in case the number of attempts is invalid
     */
    public function setMaxAttempts($attempts)
    {
        if (null !== $attempts && $attempts < 1) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\InvalidArgumentException('Maximum number of attempts must be a positive value.');
        }

        $this->attempts = $attempts;

        return $this;
    }

    /**
     * Gets the maximum number of attempts.
     *
     * Null means an unlimited number of attempts.
     *
     * @return null|int
     */
    public function getMaxAttempts()
    {
        return $this->attempts;
    }

    /**
     * Sets a normalizer for the response.
     *
     * The normalizer can be a callable (a string), a closure or a class implementing __invoke.
     *
     * @param callable $normalizer
     *
     * @return $this
     */
    public function setNormalizer(callable $normalizer)
    {
        $this->normalizer = $normalizer;

        return $this;
    }

    /**
     * Gets the normalizer for the response.
     *
     * The normalizer can ba a callable (a string), a closure or a class implementing __invoke.
     *
     * @return callable
     */
    public function getNormalizer()
    {
        return $this->normalizer;
    }

    protected function isAssoc($array)
    {
        return (bool) count(array_filter(array_keys($array), 'is_string'));
    }
}
Console Component
=================

The Console component eases the creation of beautiful and testable command line
interfaces.

Resources
---------

  * [Documentation](https://symfony.com/doc/current/components/console/index.html)
  * [Contributing](https://symfony.com/doc/current/contributing/index.html)
  * [Report issues](https://github.com/symfony/symfony/issues) and
    [send Pull Requests](https://github.com/symfony/symfony/pulls)
    in the [main Symfony repository](https://github.com/symfony/symfony)

Credits
-------

`Resources/bin/hiddeninput.exe` is a third party binary provided within this
component. Find sources and license at https://github.com/Seldaek/hidden-input.
MZ����@���	�!�L�!This program cannot be run in DOS mode.

$�,�;�B�;�B�;�B�2�מ:�B�2��-�B�2�ƞ9�B�2�ў?�B�a9�8�B�;�C��B�2�Ȟ:�B�2�֞:�B�2�Ӟ:�B�Rich;�B�PEL�MoO�	
8 @`?�@��"P@ Pp!8!@ �.text	
 `.rdata�	 
@@.data�0@�.rsrc @@@.reloc�P"@Bj$��@�xj�� @�e���E�PV� @�EЃ�PV� @�M�X @�e��E�P�5H @�L @YY�5\ @�E�P�5` @�D @YY��P @�M���M�T @3��H�;
0@u���h�@��l3@�$40@�5h3@�40@h$0@h(0@h 0@�� @���00@��}j�Y�jh"@�3ۉ]�d��p�]俀3@SVW�0 @;�t;�u3�F�u��h��4 @��3�F�|3@;�u
j�\Y�;�|3@��u,�5|3@h� @h� @�YY��t�E����������5<0@�|3@;�uh� @h� @�lYY�|3@9]�uSW�8 @9�3@th�3@�Y��t
SjS��3@�$0@�
� @��5$0@�5(0@�5 0@�������80@9,0@u7P�� @�E��	�M�PQ�YYËe�E�80@3�9,0@uP�h @9<0@u�� @�E������80@�øMZf9@t3��M�<@��@�8PEu��H��t��uՃ��v�3�9����xtv�3�9������j�,0@�p @j��l @YY��3@��3@�� @�
t3@��� @�
p3@��� @��x3@�V��=0@uh�@�� @Y�g�=0@�u	j��� @Y3���{�����U���(�H1@�
D1@�@1@�<1@�581@�=41@f�`1@f�
T1@f�01@f�,1@f�%(1@f�-$1@��X1@�E�L1@�E�P1@�E�\1@������0@�P1@�L0@�@0@	��D0@�0@������0@������ @��0@j�?Yj�  @h!@�$ @�=�0@uj�Yh	��( @P�, @�Ë�U��E��8csm�u*�xu$�@= �t=!�t="�t=@�u��3�]�hH@�  @3��%� @jh("@�b�5�3@�5� @��Y�E��u�u�� @Y�gj�Y�e��5�3@�։E�5�3@��YY�E�E�P�E�P�u�5l @��YP�U�E�u�֣�3@�u�փ���3@�E������	�E���j�YË�U��u�N��������YH]Ë�V��!@��!@W��;�s���t�Ѓ�;�r�_^Ë�V�"@�"@W��;�s���t�Ѓ�;�r�_^�%� @���̋�U��M�MZf9t3�]ËA<��8PEu�3ҹf9H�‹�]�����������̋�U��E�H<��ASV�q3�W�D��v�}�H;�r	�X�;�r
B��(;�r�3�_^[]������������̋�U��j�hH"@he@d�P��SVW�0@1E�3�P�E�d��e��E�h@�*�������tU�E-@Ph@�P�������t;�@$���Ѓ��E������M�d�
Y_^[��]ËE��3�=��‹�Ëe��E�����3��M�d�
Y_^[��]��%� @�%� @��he@d�5�D$�l$�l$+�SVW�0@1E�3�P�e�u��E��E������E��E�d�ËM�d�
Y__^[��]Q�U��u�u�u�uh�@h0@����]�Vhh3�V������t
VVVVV����^�3��U����0@�e��e�SW�N�@����;�t
��t	�У0@�`V�E�P�< @�u�3u�� @3� @3� @3�E�P� @�E�3E�3�;�u�O�@����u����50@�։50@^_[��%t @�%x @�%| @�%� @�%� @�%� @�%� @�%� @�%� @Pd�5�D$+d$SVW�(��0@3�P�E�u��E������E�d�ËM�d�
Y__^[��]QËM�3���������M�%T @�T$�B�J�3�����J�3�����l"@�s����#�#�#�)r)b)H)4))�(�(�(�(�(�(�)�#�$%�%&d&�&�$('�'�'�'�'(((6(�'H(Z(t(�('''�'�'l'^'R'F'>'>(0'�'�)�@W@�@�MoOl�!�@0@�0@bad allocationH0@�!@RSDSь���J�!���LZc:\users\seld\documents\visual studio 2010\Projects\hiddeninp\Release\hiddeninp.pdbe������������@@�����������:@������������@�@�����@"�d"@�"�# $#�&D H#(h �#�#�#�)r)b)H)4))�(�(�(�(�(�(�)�#�$%�%&d&�&�$('�'�'�'�'(((6(�'H(Z(t(�('''�'�'l'^'R'F'>'>(0'�'�)�GetConsoleMode�SetConsoleMode;GetStdHandleKERNEL32.dll??$?6DU?$char_traits@D@std@@V?$allocator@D@1@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z�?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@AJ?cin@std@@3V?$basic_istream@DU?$char_traits@D@std@@@1@A�??$getline@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@YAAAV?$basic_istream@DU?$char_traits@D@std@@@0@AAV10@AAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z_??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ{??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ�?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@ZMSVCP90.dll_amsg_exit�__getmainargs,_cexit|_exitf_XcptFilter�exit�__initenv_initterm_initterm_e<_configthreadlocale�__setusermatherr_adjust_fdiv�__p__commode�__p__fmodej_encode_pointer�__set_app_typeK_crt_debugger_hookC?terminate@@YAXXZMSVCR90.dll�_unlock�__dllonexitv_lock_onexit`_decode_pointers_except_handler4_common_invoke_watson?_controlfp_s�InterlockedExchange!Sleep�InterlockedCompareExchange-TerminateProcess�GetCurrentProcess>UnhandledExceptionFilterSetUnhandledExceptionFilter�IsDebuggerPresentTQueryPerformanceCounterfGetTickCount�GetCurrentThreadId�GetCurrentProcessIdOGetSystemTimeAsFileTimes__CxxFrameHandler3N�@���D������������$!@ �8�P�h�	�	��@(��CV�(4VS_VERSION_INFO���StringFileInfob040904b0�QFileDescriptionReads from stdin without leaking info to the terminal and outputs back to stdout6FileVersion1, 0, 0, 08InternalNamehiddeninputPLegalCopyrightJordi Boggiano - 2012HOriginalFilenamehiddeninput.exe:
ProductNameHidden Input:ProductVersion1, 0, 0, 0DVarFileInfo$Translation	�<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
      </requestedPrivileges>
    </security>
  </trustInfo>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
</assembly>PAPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDING@00!0/080F0L0T0^0d0n0{0�0�0�0�0�0�0�0�0�0�0�0�0�01#1-1@1J1O1T1v1{1�1�1�1�1�1�1�1�1�1�1�1�1�1�12"2*23292A2M2_2j2p2�2�2�2�2�2�2�2�2�2�2�2333%303N3T3Z3`3f3l3s3z3�3�3�3�3�3�3�3�3�3�3�3�3�3�3�3�34444%4;4B4�4�4�4�4�4�4�4�4�4�45!5^5c5�5�5�5H6M6_6}6�6�677
7*7w7|7�7�7�7�78
88=8E8P8V8\8b8h8n8t8z8�8�8�89 $�0�0�01 1t1x12 2@2\2`2h2t200<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Style;

/**
 * Decorates output to add console style guide helpers.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
abstract class OutputStyle implements \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface, \PHPStanVendor\Symfony\Component\Console\Style\StyleInterface
{
    private $output;

    public function __construct(\PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output)
    {
        $this->output = $output;
    }

    /**
     * {@inheritdoc}
     */
    public function newLine($count = 1)
    {
        $this->output->write(str_repeat(PHP_EOL, $count));
    }

    /**
     * @param int $max
     *
     * @return ProgressBar
     */
    public function createProgressBar($max = 0)
    {
        return new \PHPStanVendor\Symfony\Component\Console\Helper\ProgressBar($this->output, $max);
    }

    /**
     * {@inheritdoc}
     */
    public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
    {
        $this->output->write($messages, $newline, $type);
    }

    /**
     * {@inheritdoc}
     */
    public function writeln($messages, $type = self::OUTPUT_NORMAL)
    {
        $this->output->writeln($messages, $type);
    }

    /**
     * {@inheritdoc}
     */
    public function setVerbosity($level)
    {
        $this->output->setVerbosity($level);
    }

    /**
     * {@inheritdoc}
     */
    public function getVerbosity()
    {
        return $this->output->getVerbosity();
    }

    /**
     * {@inheritdoc}
     */
    public function setDecorated($decorated)
    {
        $this->output->setDecorated($decorated);
    }

    /**
     * {@inheritdoc}
     */
    public function isDecorated()
    {
        return $this->output->isDecorated();
    }

    /**
     * {@inheritdoc}
     */
    public function setFormatter(\PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter)
    {
        $this->output->setFormatter($formatter);
    }

    /**
     * {@inheritdoc}
     */
    public function getFormatter()
    {
        return $this->output->getFormatter();
    }

    /**
     * {@inheritdoc}
     */
    public function isQuiet()
    {
        return $this->output->isQuiet();
    }

    /**
     * {@inheritdoc}
     */
    public function isVerbose()
    {
        return $this->output->isVerbose();
    }

    /**
     * {@inheritdoc}
     */
    public function isVeryVerbose()
    {
        return $this->output->isVeryVerbose();
    }

    /**
     * {@inheritdoc}
     */
    public function isDebug()
    {
        return $this->output->isDebug();
    }

    protected function getErrorOutput()
    {
        if (!$this->output instanceof \PHPStanVendor\Symfony\Component\Console\Output\ConsoleOutputInterface) {
            return $this->output;
        }

        return $this->output->getErrorOutput();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Style;

/**
 * Output style helpers.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
interface StyleInterface
{
    /**
     * Formats a command title.
     *
     * @param string $message
     */
    public function title($message);

    /**
     * Formats a section title.
     *
     * @param string $message
     */
    public function section($message);

    /**
     * Formats a list.
     */
    public function listing(array $elements);

    /**
     * Formats informational text.
     *
     * @param string|array $message
     */
    public function text($message);

    /**
     * Formats a success result bar.
     *
     * @param string|array $message
     */
    public function success($message);

    /**
     * Formats an error result bar.
     *
     * @param string|array $message
     */
    public function error($message);

    /**
     * Formats an warning result bar.
     *
     * @param string|array $message
     */
    public function warning($message);

    /**
     * Formats a note admonition.
     *
     * @param string|array $message
     */
    public function note($message);

    /**
     * Formats a caution admonition.
     *
     * @param string|array $message
     */
    public function caution($message);

    /**
     * Formats a table.
     */
    public function table(array $headers, array $rows);

    /**
     * Asks a question.
     *
     * @param string        $question
     * @param string|null   $default
     * @param callable|null $validator
     *
     * @return string
     */
    public function ask($question, $default = null, $validator = null);

    /**
     * Asks a question with the user input hidden.
     *
     * @param string        $question
     * @param callable|null $validator
     *
     * @return string
     */
    public function askHidden($question, $validator = null);

    /**
     * Asks for confirmation.
     *
     * @param string $question
     * @param bool   $default
     *
     * @return bool
     */
    public function confirm($question, $default = true);

    /**
     * Asks a choice question.
     *
     * @param string          $question
     * @param array           $choices
     * @param string|int|null $default
     *
     * @return string
     */
    public function choice($question, array $choices, $default = null);

    /**
     * Add newline(s).
     *
     * @param int $count The number of newlines
     */
    public function newLine($count = 1);

    /**
     * Starts the progress output.
     *
     * @param int $max Maximum steps (0 if unknown)
     */
    public function progressStart($max = 0);

    /**
     * Advances the progress output X steps.
     *
     * @param int $step Number of steps to advance
     */
    public function progressAdvance($step = 1);

    /**
     * Finishes the progress output.
     */
    public function progressFinish();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Style;

/**
 * Output decorator helpers for the Symfony Style Guide.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class SymfonyStyle extends \PHPStanVendor\Symfony\Component\Console\Style\OutputStyle
{
    const MAX_LINE_LENGTH = 120;

    private $input;
    private $questionHelper;
    private $progressBar;
    private $lineLength;
    private $bufferedOutput;

    public function __construct(\PHPStanVendor\Symfony\Component\Console\Input\InputInterface $input, \PHPStanVendor\Symfony\Component\Console\Output\OutputInterface $output)
    {
        $this->input = $input;
        $this->bufferedOutput = new \PHPStanVendor\Symfony\Component\Console\Output\BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter());
        // Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not.
        $width = (new \PHPStanVendor\Symfony\Component\Console\Terminal())->getWidth() ?: self::MAX_LINE_LENGTH;
        $this->lineLength = min($width - (int) (DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);

        parent::__construct($output);
    }

    /**
     * Formats a message as a block of text.
     *
     * @param string|array $messages The message to write in the block
     * @param string|null  $type     The block type (added in [] on first line)
     * @param string|null  $style    The style to apply to the whole block
     * @param string       $prefix   The prefix for the block
     * @param bool         $padding  Whether to add vertical padding
     * @param bool         $escape   Whether to escape the message
     */
    public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = true)
    {
        $messages = is_array($messages) ? array_values($messages) : array($messages);

        $this->autoPrependBlock();
        $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, $escape));
        $this->newLine();
    }

    /**
     * {@inheritdoc}
     */
    public function title($message)
    {
        $this->autoPrependBlock();
        $this->writeln(array(
            sprintf('<comment>%s</>', \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatter::escapeTrailingBackslash($message)),
            sprintf('<comment>%s</>', str_repeat('=', \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
        ));
        $this->newLine();
    }

    /**
     * {@inheritdoc}
     */
    public function section($message)
    {
        $this->autoPrependBlock();
        $this->writeln(array(
            sprintf('<comment>%s</>', \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatter::escapeTrailingBackslash($message)),
            sprintf('<comment>%s</>', str_repeat('-', \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
        ));
        $this->newLine();
    }

    /**
     * {@inheritdoc}
     */
    public function listing(array $elements)
    {
        $this->autoPrependText();
        $elements = array_map(function ($element) {
            return sprintf(' * %s', $element);
        }, $elements);

        $this->writeln($elements);
        $this->newLine();
    }

    /**
     * {@inheritdoc}
     */
    public function text($message)
    {
        $this->autoPrependText();

        $messages = is_array($message) ? array_values($message) : array($message);
        foreach ($messages as $message) {
            $this->writeln(sprintf(' %s', $message));
        }
    }

    /**
     * Formats a command comment.
     *
     * @param string|array $message
     */
    public function comment($message)
    {
        $this->block($message, null, null, '<fg=default;bg=default> // </>', false, false);
    }

    /**
     * {@inheritdoc}
     */
    public function success($message)
    {
        $this->block($message, 'OK', 'fg=black;bg=green', ' ', true);
    }

    /**
     * {@inheritdoc}
     */
    public function error($message)
    {
        $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true);
    }

    /**
     * {@inheritdoc}
     */
    public function warning($message)
    {
        $this->block($message, 'WARNING', 'fg=white;bg=red', ' ', true);
    }

    /**
     * {@inheritdoc}
     */
    public function note($message)
    {
        $this->block($message, 'NOTE', 'fg=yellow', ' ! ');
    }

    /**
     * {@inheritdoc}
     */
    public function caution($message)
    {
        $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true);
    }

    /**
     * {@inheritdoc}
     */
    public function table(array $headers, array $rows)
    {
        $style = clone \PHPStanVendor\Symfony\Component\Console\Helper\Table::getStyleDefinition('symfony-style-guide');
        $style->setCellHeaderFormat('<info>%s</info>');

        $table = new \PHPStanVendor\Symfony\Component\Console\Helper\Table($this);
        $table->setHeaders($headers);
        $table->setRows($rows);
        $table->setStyle($style);

        $table->render();
        $this->newLine();
    }

    /**
     * {@inheritdoc}
     */
    public function ask($question, $default = null, $validator = null)
    {
        $question = new \PHPStanVendor\Symfony\Component\Console\Question\Question($question, $default);
        $question->setValidator($validator);

        return $this->askQuestion($question);
    }

    /**
     * {@inheritdoc}
     */
    public function askHidden($question, $validator = null)
    {
        $question = new \PHPStanVendor\Symfony\Component\Console\Question\Question($question);

        $question->setHidden(true);
        $question->setValidator($validator);

        return $this->askQuestion($question);
    }

    /**
     * {@inheritdoc}
     */
    public function confirm($question, $default = true)
    {
        return $this->askQuestion(new \PHPStanVendor\Symfony\Component\Console\Question\ConfirmationQuestion($question, $default));
    }

    /**
     * {@inheritdoc}
     */
    public function choice($question, array $choices, $default = null)
    {
        if (null !== $default) {
            $values = array_flip($choices);
            $default = $values[$default];
        }

        return $this->askQuestion(new \PHPStanVendor\Symfony\Component\Console\Question\ChoiceQuestion($question, $choices, $default));
    }

    /**
     * {@inheritdoc}
     */
    public function progressStart($max = 0)
    {
        $this->progressBar = $this->createProgressBar($max);
        $this->progressBar->start();
    }

    /**
     * {@inheritdoc}
     */
    public function progressAdvance($step = 1)
    {
        $this->getProgressBar()->advance($step);
    }

    /**
     * {@inheritdoc}
     */
    public function progressFinish()
    {
        $this->getProgressBar()->finish();
        $this->newLine(2);
        $this->progressBar = null;
    }

    /**
     * {@inheritdoc}
     */
    public function createProgressBar($max = 0)
    {
        $progressBar = parent::createProgressBar($max);

        if ('\\' !== DIRECTORY_SEPARATOR) {
            $progressBar->setEmptyBarCharacter('░'); // light shade character \u2591
            $progressBar->setProgressCharacter('');
            $progressBar->setBarCharacter('▓'); // dark shade character \u2593
        }

        return $progressBar;
    }

    /**
     * @return string
     */
    public function askQuestion(\PHPStanVendor\Symfony\Component\Console\Question\Question $question)
    {
        if ($this->input->isInteractive()) {
            $this->autoPrependBlock();
        }

        if (!$this->questionHelper) {
            $this->questionHelper = new \PHPStanVendor\Symfony\Component\Console\Helper\SymfonyQuestionHelper();
        }

        $answer = $this->questionHelper->ask($this->input, $this, $question);

        if ($this->input->isInteractive()) {
            $this->newLine();
            $this->bufferedOutput->write("\n");
        }

        return $answer;
    }

    /**
     * {@inheritdoc}
     */
    public function writeln($messages, $type = self::OUTPUT_NORMAL)
    {
        parent::writeln($messages, $type);
        $this->bufferedOutput->writeln($this->reduceBuffer($messages), $type);
    }

    /**
     * {@inheritdoc}
     */
    public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
    {
        parent::write($messages, $newline, $type);
        $this->bufferedOutput->write($this->reduceBuffer($messages), $newline, $type);
    }

    /**
     * {@inheritdoc}
     */
    public function newLine($count = 1)
    {
        parent::newLine($count);
        $this->bufferedOutput->write(str_repeat("\n", $count));
    }

    /**
     * Returns a new instance which makes use of stderr if available.
     *
     * @return self
     */
    public function getErrorStyle()
    {
        return new self($this->input, $this->getErrorOutput());
    }

    /**
     * @return ProgressBar
     */
    private function getProgressBar()
    {
        if (!$this->progressBar) {
            throw new \PHPStanVendor\Symfony\Component\Console\Exception\RuntimeException('The ProgressBar is not started.');
        }

        return $this->progressBar;
    }

    private function autoPrependBlock()
    {
        $chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);

        if (!isset($chars[0])) {
            return $this->newLine(); //empty history, so we should start with a new line.
        }
        //Prepend new line for each non LF chars (This means no blank line was output before)
        $this->newLine(2 - substr_count($chars, "\n"));
    }

    private function autoPrependText()
    {
        $fetched = $this->bufferedOutput->fetch();
        //Prepend new line if last char isn't EOL:
        if ("\n" !== substr($fetched, -1)) {
            $this->newLine();
        }
    }

    private function reduceBuffer($messages)
    {
        // We need to know if the two last chars are PHP_EOL
        // Preserve the last 4 chars inserted (PHP_EOL on windows is two chars) in the history buffer
        return array_map(function ($value) {
            return substr($value, -4);
        }, array_merge(array($this->bufferedOutput->fetch()), (array) $messages));
    }

    private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false)
    {
        $indentLength = 0;
        $prefixLength = \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($this->getFormatter(), $prefix);
        $lines = array();

        if (null !== $type) {
            $type = sprintf('[%s] ', $type);
            $indentLength = strlen($type);
            $lineIndentation = str_repeat(' ', $indentLength);
        }

        // wrap and add newlines for each element
        foreach ($messages as $key => $message) {
            if ($escape) {
                $message = \PHPStanVendor\Symfony\Component\Console\Formatter\OutputFormatter::escape($message);
            }

            $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true)));

            if (count($messages) > 1 && $key < count($messages) - 1) {
                $lines[] = '';
            }
        }

        $firstLineIndex = 0;
        if ($padding && $this->isDecorated()) {
            $firstLineIndex = 1;
            array_unshift($lines, '');
            $lines[] = '';
        }

        foreach ($lines as $i => &$line) {
            if (null !== $type) {
                $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line;
            }

            $line = $prefix.$line;
            $line .= str_repeat(' ', $this->lineLength - \PHPStanVendor\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($this->getFormatter(), $line));

            if ($style) {
                $line = sprintf('<%s>%s</>', $style, $line);
            }
        }

        return $lines;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console;

class Terminal
{
    private static $width;
    private static $height;

    /**
     * Gets the terminal width.
     *
     * @return int
     */
    public function getWidth()
    {
        $width = getenv('COLUMNS');
        if (false !== $width) {
            return (int) trim($width);
        }

        if (null === self::$width) {
            self::initDimensions();
        }

        return self::$width ?: 80;
    }

    /**
     * Gets the terminal height.
     *
     * @return int
     */
    public function getHeight()
    {
        $height = getenv('LINES');
        if (false !== $height) {
            return (int) trim($height);
        }

        if (null === self::$height) {
            self::initDimensions();
        }

        return self::$height ?: 50;
    }

    private static function initDimensions()
    {
        if ('\\' === DIRECTORY_SEPARATOR) {
            if (preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim(getenv('ANSICON')), $matches)) {
                // extract [w, H] from "wxh (WxH)"
                // or [w, h] from "wxh"
                self::$width = (int) $matches[1];
                self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2];
            } elseif (null !== $dimensions = self::getConsoleMode()) {
                // extract [w, h] from "wxh"
                self::$width = (int) $dimensions[0];
                self::$height = (int) $dimensions[1];
            }
        } elseif ($sttyString = self::getSttyColumns()) {
            if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
                // extract [w, h] from "rows h; columns w;"
                self::$width = (int) $matches[2];
                self::$height = (int) $matches[1];
            } elseif (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
                // extract [w, h] from "; h rows; w columns"
                self::$width = (int) $matches[2];
                self::$height = (int) $matches[1];
            }
        }
    }

    /**
     * Runs and parses mode CON if it's available, suppressing any error output.
     *
     * @return int[]|null An array composed of the width and the height or null if it could not be parsed
     */
    private static function getConsoleMode()
    {
        if (!function_exists('proc_open')) {
            return;
        }

        $descriptorspec = array(
            1 => array('pipe', 'w'),
            2 => array('pipe', 'w'),
        );
        $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
        if (is_resource($process)) {
            $info = stream_get_contents($pipes[1]);
            fclose($pipes[1]);
            fclose($pipes[2]);
            proc_close($process);

            if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
                return array((int) $matches[2], (int) $matches[1]);
            }
        }
    }

    /**
     * Runs and parses stty -a if it's available, suppressing any error output.
     *
     * @return string|null
     */
    private static function getSttyColumns()
    {
        if (!function_exists('proc_open')) {
            return;
        }

        $descriptorspec = array(
            1 => array('pipe', 'w'),
            2 => array('pipe', 'w'),
        );

        $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
        if (is_resource($process)) {
            $info = stream_get_contents($pipes[1]);
            fclose($pipes[1]);
            fclose($pipes[2]);
            proc_close($process);

            return $info;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Tester;

/**
 * Eases the testing of console applications.
 *
 * When testing an application, don't forget to disable the auto exit flag:
 *
 *     $application = new Application();
 *     $application->setAutoExit(false);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ApplicationTester
{
    private $application;
    private $input;
    private $statusCode;
    /**
     * @var OutputInterface
     */
    private $output;
    private $captureStreamsIndependently = false;

    public function __construct(\PHPStanVendor\Symfony\Component\Console\Application $application)
    {
        $this->application = $application;
    }

    /**
     * Executes the application.
     *
     * Available options:
     *
     *  * interactive:               Sets the input interactive flag
     *  * decorated:                 Sets the output decorated flag
     *  * verbosity:                 Sets the output verbosity flag
     *  * capture_stderr_separately: Make output of stdOut and stdErr separately available
     *
     * @param array $input   An array of arguments and options
     * @param array $options An array of options
     *
     * @return int The command exit code
     */
    public function run(array $input, $options = array())
    {
        $this->input = new \PHPStanVendor\Symfony\Component\Console\Input\ArrayInput($input);
        if (isset($options['interactive'])) {
            $this->input->setInteractive($options['interactive']);
        }

        $this->captureStreamsIndependently = array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately'];
        if (!$this->captureStreamsIndependently) {
            $this->output = new \PHPStanVendor\Symfony\Component\Console\Output\StreamOutput(fopen('php://memory', 'w', false));
            if (isset($options['decorated'])) {
                $this->output->setDecorated($options['decorated']);
            }
            if (isset($options['verbosity'])) {
                $this->output->setVerbosity($options['verbosity']);
            }
        } else {
            $this->output = new \PHPStanVendor\Symfony\Component\Console\Output\ConsoleOutput(
                isset($options['verbosity']) ? $options['verbosity'] : \PHPStanVendor\Symfony\Component\Console\Output\ConsoleOutput::VERBOSITY_NORMAL,
                isset($options['decorated']) ? $options['decorated'] : null
            );

            $errorOutput = new \PHPStanVendor\Symfony\Component\Console\Output\StreamOutput(fopen('php://memory', 'w', false));
            $errorOutput->setFormatter($this->output->getFormatter());
            $errorOutput->setVerbosity($this->output->getVerbosity());
            $errorOutput->setDecorated($this->output->isDecorated());

            $reflectedOutput = new \ReflectionObject($this->output);
            $strErrProperty = $reflectedOutput->getProperty('stderr');
            $strErrProperty->setAccessible(true);
            $strErrProperty->setValue($this->output, $errorOutput);

            $reflectedParent = $reflectedOutput->getParentClass();
            $streamProperty = $reflectedParent->getProperty('stream');
            $streamProperty->setAccessible(true);
            $streamProperty->setValue($this->output, fopen('php://memory', 'w', false));
        }

        return $this->statusCode = $this->application->run($this->input, $this->output);
    }

    /**
     * Gets the display returned by the last execution of the application.
     *
     * @param bool $normalize Whether to normalize end of lines to \n or not
     *
     * @return string The display
     */
    public function getDisplay($normalize = false)
    {
        rewind($this->output->getStream());

        $display = stream_get_contents($this->output->getStream());

        if ($normalize) {
            $display = str_replace(PHP_EOL, "\n", $display);
        }

        return $display;
    }

    /**
     * Gets the output written to STDERR by the application.
     *
     * @param bool $normalize Whether to normalize end of lines to \n or not
     *
     * @return string
     */
    public function getErrorOutput($normalize = false)
    {
        if (!$this->captureStreamsIndependently) {
            throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.');
        }

        rewind($this->output->getErrorOutput()->getStream());

        $display = stream_get_contents($this->output->getErrorOutput()->getStream());

        if ($normalize) {
            $display = str_replace(PHP_EOL, "\n", $display);
        }

        return $display;
    }

    /**
     * Gets the input instance used by the last execution of the application.
     *
     * @return InputInterface The current input instance
     */
    public function getInput()
    {
        return $this->input;
    }

    /**
     * Gets the output instance used by the last execution of the application.
     *
     * @return OutputInterface The current output instance
     */
    public function getOutput()
    {
        return $this->output;
    }

    /**
     * Gets the status code returned by the last execution of the application.
     *
     * @return int The status code
     */
    public function getStatusCode()
    {
        return $this->statusCode;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Console\Tester;

/**
 * Eases the testing of console commands.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
class CommandTester
{
    private $command;
    private $input;
    private $output;
    private $inputs = array();
    private $statusCode;

    public function __construct(\PHPStanVendor\Symfony\Component\Console\Command\Command $command)
    {
        $this->command = $command;
    }

    /**
     * Executes the command.
     *
     * Available execution options:
     *
     *  * interactive: Sets the input interactive flag
     *  * decorated:   Sets the output decorated flag
     *  * verbosity:   Sets the output verbosity flag
     *
     * @param array $input   An array of command arguments and options
     * @param array $options An array of execution options
     *
     * @return int The command exit code
     */
    public function execute(array $input, array $options = array())
    {
        // set the command name automatically if the application requires
        // this argument and no command name was passed
        if (!isset($input['command'])
            && (null !== $application = $this->command->getApplication())
            && $application->getDefinition()->hasArgument('command')
        ) {
            $input = array_merge(array('command' => $this->command->getName()), $input);
        }

        $this->input = new \PHPStanVendor\Symfony\Component\Console\Input\ArrayInput($input);
        if ($this->inputs) {
            $this->input->setStream(self::createStream($this->inputs));
        }

        if (isset($options['interactive'])) {
            $this->input->setInteractive($options['interactive']);
        }

        $this->output = new \PHPStanVendor\Symfony\Component\Console\Output\StreamOutput(fopen('php://memory', 'w', false));
        $this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false);
        if (isset($options['verbosity'])) {
            $this->output->setVerbosity($options['verbosity']);
        }

        return $this->statusCode = $this->command->run($this->input, $this->output);
    }

    /**
     * Gets the display returned by the last execution of the command.
     *
     * @param bool $normalize Whether to normalize end of lines to \n or not
     *
     * @return string The display
     */
    public function getDisplay($normalize = false)
    {
        rewind($this->output->getStream());

        $display = stream_get_contents($this->output->getStream());

        if ($normalize) {
            $display = str_replace(PHP_EOL, "\n", $display);
        }

        return $display;
    }

    /**
     * Gets the input instance used by the last execution of the command.
     *
     * @return InputInterface The current input instance
     */
    public function getInput()
    {
        return $this->input;
    }

    /**
     * Gets the output instance used by the last execution of the command.
     *
     * @return OutputInterface The current output instance
     */
    public function getOutput()
    {
        return $this->output;
    }

    /**
     * Gets the status code returned by the last execution of the application.
     *
     * @return int The status code
     */
    public function getStatusCode()
    {
        return $this->statusCode;
    }

    /**
     * Sets the user inputs.
     *
     * @param array $inputs An array of strings representing each input
     *                      passed to the command input stream
     *
     * @return CommandTester
     */
    public function setInputs(array $inputs)
    {
        $this->inputs = $inputs;

        return $this;
    }

    private static function createStream(array $inputs)
    {
        $stream = fopen('php://memory', 'r+', false);

        fwrite($stream, implode(PHP_EOL, $inputs));
        rewind($stream);

        return $stream;
    }
}
{
    "name": "symfony/console",
    "type": "library",
    "description": "Symfony Console Component",
    "keywords": [],
    "homepage": "https://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https://symfony.com/contributors"
        }
    ],
    "require": {
        "php": "^5.5.9|>=7.0.8",
        "symfony/polyfill-mbstring": "~1.0",
        "symfony/debug": "~2.8|~3.0|~4.0"
    },
    "require-dev": {
        "symfony/config": "~3.3|~4.0",
        "symfony/event-dispatcher": "~2.8|~3.0|~4.0",
        "symfony/dependency-injection": "~3.4|~4.0",
        "symfony/lock": "~3.4|~4.0",
        "symfony/process": "~3.3|~4.0",
        "psr/log": "~1.0"
    },
    "suggest": {
        "symfony/event-dispatcher": "",
        "symfony/lock": "",
        "symfony/process": "",
        "psr/log": "For using the console logger"
    },
    "conflict": {
        "symfony/dependency-injection": "<3.4",
        "symfony/process": "<3.3"
    },
    "autoload": {
        "psr-4": { "Symfony\\Component\\Console\\": "" },
        "exclude-from-classmap": [
            "/Tests/"
        ]
    },
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-master": "3.4-dev"
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>

<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
         backupGlobals="false"
         colors="true"
         bootstrap="vendor/autoload.php"
         failOnRisky="true"
         failOnWarning="true"
>
    <php>
        <ini name="error_reporting" value="-1" />
    </php>

    <testsuites>
        <testsuite name="Symfony Console Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>

    <listeners>
        <listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener">
            <arguments>
                <array>
                    <element key="time-sensitive"><string>Symfony\Component\Console</string></element>
                </array>
            </arguments>
        </listener>
    </listeners>
</phpunit>
CHANGELOG
=========

3.4.0
-----

 * deprecated `Symfony\Component\Finder\Iterator\FilterIterator`
 * added Finder::hasResults() method to check if any results were found

3.3.0
-----

 * added double-star matching to Glob::toRegex()

3.0.0
-----

 * removed deprecated classes

2.8.0
-----

 * deprecated adapters and related classes

2.5.0
-----
 * added support for GLOB_BRACE in the paths passed to Finder::in()

2.3.0
-----

 * added a way to ignore unreadable directories (via Finder::ignoreUnreadableDirs())
 * unified the way subfolders that are not executable are handled by always throwing an AccessDeniedException exception

2.2.0
-----

 * added Finder::path() and Finder::notPath() methods
 * added finder adapters to improve performance on specific platforms
 * added support for wildcard characters (glob patterns) in the paths passed
   to Finder::in()

2.1.0
-----

 * added Finder::sortByAccessedTime(), Finder::sortByChangedTime(), and
   Finder::sortByModifiedTime()
 * added Countable to Finder
 * added support for an array of directories as an argument to
   Finder::exclude()
 * added searching based on the file content via Finder::contains() and
   Finder::notContains()
 * added support for the != operator in the Comparator
 * [BC BREAK] filter expressions (used for file name and content) are no more
   considered as regexps but glob patterns when they are enclosed in '*' or '?'
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Comparator;

/**
 * Comparator.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Comparator
{
    private $target;
    private $operator = '==';

    /**
     * Gets the target value.
     *
     * @return string The target value
     */
    public function getTarget()
    {
        return $this->target;
    }

    /**
     * Sets the target value.
     *
     * @param string $target The target value
     */
    public function setTarget($target)
    {
        $this->target = $target;
    }

    /**
     * Gets the comparison operator.
     *
     * @return string The operator
     */
    public function getOperator()
    {
        return $this->operator;
    }

    /**
     * Sets the comparison operator.
     *
     * @param string $operator A valid operator
     *
     * @throws \InvalidArgumentException
     */
    public function setOperator($operator)
    {
        if (!$operator) {
            $operator = '==';
        }

        if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) {
            throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
        }

        $this->operator = $operator;
    }

    /**
     * Tests against the target.
     *
     * @param mixed $test A test value
     *
     * @return bool
     */
    public function test($test)
    {
        switch ($this->operator) {
            case '>':
                return $test > $this->target;
            case '>=':
                return $test >= $this->target;
            case '<':
                return $test < $this->target;
            case '<=':
                return $test <= $this->target;
            case '!=':
                return $test != $this->target;
        }

        return $test == $this->target;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Comparator;

/**
 * DateCompare compiles date comparisons.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DateComparator extends \PHPStanVendor\Symfony\Component\Finder\Comparator\Comparator
{
    /**
     * @param string $test A comparison string
     *
     * @throws \InvalidArgumentException If the test is not understood
     */
    public function __construct($test)
    {
        if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
            throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
        }

        try {
            $date = new \DateTime($matches[2]);
            $target = $date->format('U');
        } catch (\Exception $e) {
            throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
        }

        $operator = isset($matches[1]) ? $matches[1] : '==';
        if ('since' === $operator || 'after' === $operator) {
            $operator = '>';
        }

        if ('until' === $operator || 'before' === $operator) {
            $operator = '<';
        }

        $this->setOperator($operator);
        $this->setTarget($target);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Comparator;

/**
 * NumberComparator compiles a simple comparison to an anonymous
 * subroutine, which you can call with a value to be tested again.
 *
 * Now this would be very pointless, if NumberCompare didn't understand
 * magnitudes.
 *
 * The target value may use magnitudes of kilobytes (k, ki),
 * megabytes (m, mi), or gigabytes (g, gi).  Those suffixed
 * with an i use the appropriate 2**n version in accordance with the
 * IEC standard: http://physics.nist.gov/cuu/Units/binary.html
 *
 * Based on the Perl Number::Compare module.
 *
 * @author    Fabien Potencier <fabien@symfony.com> PHP port
 * @author    Richard Clamp <richardc@unixbeard.net> Perl version
 * @copyright 2004-2005 Fabien Potencier <fabien@symfony.com>
 * @copyright 2002 Richard Clamp <richardc@unixbeard.net>
 *
 * @see http://physics.nist.gov/cuu/Units/binary.html
 */
class NumberComparator extends \PHPStanVendor\Symfony\Component\Finder\Comparator\Comparator
{
    /**
     * @param string|int $test A comparison string or an integer
     *
     * @throws \InvalidArgumentException If the test is not understood
     */
    public function __construct($test)
    {
        if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
            throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
        }

        $target = $matches[2];
        if (!is_numeric($target)) {
            throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target));
        }
        if (isset($matches[3])) {
            // magnitude
            switch (strtolower($matches[3])) {
                case 'k':
                    $target *= 1000;
                    break;
                case 'ki':
                    $target *= 1024;
                    break;
                case 'm':
                    $target *= 1000000;
                    break;
                case 'mi':
                    $target *= 1024 * 1024;
                    break;
                case 'g':
                    $target *= 1000000000;
                    break;
                case 'gi':
                    $target *= 1024 * 1024 * 1024;
                    break;
            }
        }

        $this->setTarget($target);
        $this->setOperator(isset($matches[1]) ? $matches[1] : '==');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Exception;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class AccessDeniedException extends \UnexpectedValueException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Exception;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 *
 * @deprecated since 3.3, to be removed in 4.0.
 */
interface ExceptionInterface
{
    /**
     * @return \Symfony\Component\Finder\Adapter\AdapterInterface
     */
    public function getAdapter();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder;

/**
 * Finder allows to build rules to find files and directories.
 *
 * It is a thin wrapper around several specialized iterator classes.
 *
 * All rules may be invoked several times.
 *
 * All methods return the current Finder object to allow easy chaining:
 *
 * $finder = Finder::create()->files()->name('*.php')->in(__DIR__);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Finder implements \IteratorAggregate, \Countable
{
    const IGNORE_VCS_FILES = 1;
    const IGNORE_DOT_FILES = 2;

    private $mode = 0;
    private $names = array();
    private $notNames = array();
    private $exclude = array();
    private $filters = array();
    private $depths = array();
    private $sizes = array();
    private $followLinks = false;
    private $sort = false;
    private $ignore = 0;
    private $dirs = array();
    private $dates = array();
    private $iterators = array();
    private $contains = array();
    private $notContains = array();
    private $paths = array();
    private $notPaths = array();
    private $ignoreUnreadableDirs = false;

    private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');

    public function __construct()
    {
        $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
    }

    /**
     * Creates a new Finder.
     *
     * @return static
     */
    public static function create()
    {
        return new static();
    }

    /**
     * Restricts the matching to directories only.
     *
     * @return $this
     */
    public function directories()
    {
        $this->mode = \PHPStanVendor\Symfony\Component\Finder\Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;

        return $this;
    }

    /**
     * Restricts the matching to files only.
     *
     * @return $this
     */
    public function files()
    {
        $this->mode = \PHPStanVendor\Symfony\Component\Finder\Iterator\FileTypeFilterIterator::ONLY_FILES;

        return $this;
    }

    /**
     * Adds tests for the directory depth.
     *
     * Usage:
     *
     *   $finder->depth('> 1') // the Finder will start matching at level 1.
     *   $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point.
     *
     * @param string|int $level The depth level expression
     *
     * @return $this
     *
     * @see DepthRangeFilterIterator
     * @see NumberComparator
     */
    public function depth($level)
    {
        $this->depths[] = new \PHPStanVendor\Symfony\Component\Finder\Comparator\NumberComparator($level);

        return $this;
    }

    /**
     * Adds tests for file dates (last modified).
     *
     * The date must be something that strtotime() is able to parse:
     *
     *   $finder->date('since yesterday');
     *   $finder->date('until 2 days ago');
     *   $finder->date('> now - 2 hours');
     *   $finder->date('>= 2005-10-15');
     *
     * @param string $date A date range string
     *
     * @return $this
     *
     * @see strtotime
     * @see DateRangeFilterIterator
     * @see DateComparator
     */
    public function date($date)
    {
        $this->dates[] = new \PHPStanVendor\Symfony\Component\Finder\Comparator\DateComparator($date);

        return $this;
    }

    /**
     * Adds rules that files must match.
     *
     * You can use patterns (delimited with / sign), globs or simple strings.
     *
     * $finder->name('*.php')
     * $finder->name('/\.php$/') // same as above
     * $finder->name('test.php')
     *
     * @param string $pattern A pattern (a regexp, a glob, or a string)
     *
     * @return $this
     *
     * @see FilenameFilterIterator
     */
    public function name($pattern)
    {
        $this->names[] = $pattern;

        return $this;
    }

    /**
     * Adds rules that files must not match.
     *
     * @param string $pattern A pattern (a regexp, a glob, or a string)
     *
     * @return $this
     *
     * @see FilenameFilterIterator
     */
    public function notName($pattern)
    {
        $this->notNames[] = $pattern;

        return $this;
    }

    /**
     * Adds tests that file contents must match.
     *
     * Strings or PCRE patterns can be used:
     *
     * $finder->contains('Lorem ipsum')
     * $finder->contains('/Lorem ipsum/i')
     *
     * @param string $pattern A pattern (string or regexp)
     *
     * @return $this
     *
     * @see FilecontentFilterIterator
     */
    public function contains($pattern)
    {
        $this->contains[] = $pattern;

        return $this;
    }

    /**
     * Adds tests that file contents must not match.
     *
     * Strings or PCRE patterns can be used:
     *
     * $finder->notContains('Lorem ipsum')
     * $finder->notContains('/Lorem ipsum/i')
     *
     * @param string $pattern A pattern (string or regexp)
     *
     * @return $this
     *
     * @see FilecontentFilterIterator
     */
    public function notContains($pattern)
    {
        $this->notContains[] = $pattern;

        return $this;
    }

    /**
     * Adds rules that filenames must match.
     *
     * You can use patterns (delimited with / sign) or simple strings.
     *
     * $finder->path('some/special/dir')
     * $finder->path('/some\/special\/dir/') // same as above
     *
     * Use only / as dirname separator.
     *
     * @param string $pattern A pattern (a regexp or a string)
     *
     * @return $this
     *
     * @see FilenameFilterIterator
     */
    public function path($pattern)
    {
        $this->paths[] = $pattern;

        return $this;
    }

    /**
     * Adds rules that filenames must not match.
     *
     * You can use patterns (delimited with / sign) or simple strings.
     *
     * $finder->notPath('some/special/dir')
     * $finder->notPath('/some\/special\/dir/') // same as above
     *
     * Use only / as dirname separator.
     *
     * @param string $pattern A pattern (a regexp or a string)
     *
     * @return $this
     *
     * @see FilenameFilterIterator
     */
    public function notPath($pattern)
    {
        $this->notPaths[] = $pattern;

        return $this;
    }

    /**
     * Adds tests for file sizes.
     *
     * $finder->size('> 10K');
     * $finder->size('<= 1Ki');
     * $finder->size(4);
     *
     * @param string|int $size A size range string or an integer
     *
     * @return $this
     *
     * @see SizeRangeFilterIterator
     * @see NumberComparator
     */
    public function size($size)
    {
        $this->sizes[] = new \PHPStanVendor\Symfony\Component\Finder\Comparator\NumberComparator($size);

        return $this;
    }

    /**
     * Excludes directories.
     *
     * @param string|array $dirs A directory path or an array of directories
     *
     * @return $this
     *
     * @see ExcludeDirectoryFilterIterator
     */
    public function exclude($dirs)
    {
        $this->exclude = array_merge($this->exclude, (array) $dirs);

        return $this;
    }

    /**
     * Excludes "hidden" directories and files (starting with a dot).
     *
     * @param bool $ignoreDotFiles Whether to exclude "hidden" files or not
     *
     * @return $this
     *
     * @see ExcludeDirectoryFilterIterator
     */
    public function ignoreDotFiles($ignoreDotFiles)
    {
        if ($ignoreDotFiles) {
            $this->ignore |= static::IGNORE_DOT_FILES;
        } else {
            $this->ignore &= ~static::IGNORE_DOT_FILES;
        }

        return $this;
    }

    /**
     * Forces the finder to ignore version control directories.
     *
     * @param bool $ignoreVCS Whether to exclude VCS files or not
     *
     * @return $this
     *
     * @see ExcludeDirectoryFilterIterator
     */
    public function ignoreVCS($ignoreVCS)
    {
        if ($ignoreVCS) {
            $this->ignore |= static::IGNORE_VCS_FILES;
        } else {
            $this->ignore &= ~static::IGNORE_VCS_FILES;
        }

        return $this;
    }

    /**
     * Adds VCS patterns.
     *
     * @see ignoreVCS()
     *
     * @param string|string[] $pattern VCS patterns to ignore
     */
    public static function addVCSPattern($pattern)
    {
        foreach ((array) $pattern as $p) {
            self::$vcsPatterns[] = $p;
        }

        self::$vcsPatterns = array_unique(self::$vcsPatterns);
    }

    /**
     * Sorts files and directories by an anonymous function.
     *
     * The anonymous function receives two \SplFileInfo instances to compare.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sort(\Closure $closure)
    {
        $this->sort = $closure;

        return $this;
    }

    /**
     * Sorts files and directories by name.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByName()
    {
        $this->sort = \PHPStanVendor\Symfony\Component\Finder\Iterator\SortableIterator::SORT_BY_NAME;

        return $this;
    }

    /**
     * Sorts files and directories by type (directories before files), then by name.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByType()
    {
        $this->sort = \PHPStanVendor\Symfony\Component\Finder\Iterator\SortableIterator::SORT_BY_TYPE;

        return $this;
    }

    /**
     * Sorts files and directories by the last accessed time.
     *
     * This is the time that the file was last accessed, read or written to.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByAccessedTime()
    {
        $this->sort = \PHPStanVendor\Symfony\Component\Finder\Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;

        return $this;
    }

    /**
     * Sorts files and directories by the last inode changed time.
     *
     * This is the time that the inode information was last modified (permissions, owner, group or other metadata).
     *
     * On Windows, since inode is not available, changed time is actually the file creation time.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByChangedTime()
    {
        $this->sort = \PHPStanVendor\Symfony\Component\Finder\Iterator\SortableIterator::SORT_BY_CHANGED_TIME;

        return $this;
    }

    /**
     * Sorts files and directories by the last modified time.
     *
     * This is the last time the actual contents of the file were last modified.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByModifiedTime()
    {
        $this->sort = \PHPStanVendor\Symfony\Component\Finder\Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;

        return $this;
    }

    /**
     * Filters the iterator with an anonymous function.
     *
     * The anonymous function receives a \SplFileInfo and must return false
     * to remove files.
     *
     * @return $this
     *
     * @see CustomFilterIterator
     */
    public function filter(\Closure $closure)
    {
        $this->filters[] = $closure;

        return $this;
    }

    /**
     * Forces the following of symlinks.
     *
     * @return $this
     */
    public function followLinks()
    {
        $this->followLinks = true;

        return $this;
    }

    /**
     * Tells finder to ignore unreadable directories.
     *
     * By default, scanning unreadable directories content throws an AccessDeniedException.
     *
     * @param bool $ignore
     *
     * @return $this
     */
    public function ignoreUnreadableDirs($ignore = true)
    {
        $this->ignoreUnreadableDirs = (bool) $ignore;

        return $this;
    }

    /**
     * Searches files and directories which match defined rules.
     *
     * @param string|array $dirs A directory path or an array of directories
     *
     * @return $this
     *
     * @throws \InvalidArgumentException if one of the directories does not exist
     */
    public function in($dirs)
    {
        $resolvedDirs = array();

        foreach ((array) $dirs as $dir) {
            if (is_dir($dir)) {
                $resolvedDirs[] = $dir;
            } elseif ($glob = glob($dir, (defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) {
                $resolvedDirs = array_merge($resolvedDirs, $glob);
            } else {
                throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
            }
        }

        $this->dirs = array_merge($this->dirs, $resolvedDirs);

        return $this;
    }

    /**
     * Returns an Iterator for the current Finder configuration.
     *
     * This method implements the IteratorAggregate interface.
     *
     * @return \Iterator|SplFileInfo[] An iterator
     *
     * @throws \LogicException if the in() method has not been called
     */
    public function getIterator()
    {
        if (0 === count($this->dirs) && 0 === count($this->iterators)) {
            throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
        }

        if (1 === count($this->dirs) && 0 === count($this->iterators)) {
            return $this->searchInDirectory($this->dirs[0]);
        }

        $iterator = new \AppendIterator();
        foreach ($this->dirs as $dir) {
            $iterator->append($this->searchInDirectory($dir));
        }

        foreach ($this->iterators as $it) {
            $iterator->append($it);
        }

        return $iterator;
    }

    /**
     * Appends an existing set of files/directories to the finder.
     *
     * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array.
     *
     * @param mixed $iterator
     *
     * @return $this
     *
     * @throws \InvalidArgumentException when the given argument is not iterable
     */
    public function append($iterator)
    {
        if ($iterator instanceof \IteratorAggregate) {
            $this->iterators[] = $iterator->getIterator();
        } elseif ($iterator instanceof \Iterator) {
            $this->iterators[] = $iterator;
        } elseif ($iterator instanceof \Traversable || is_array($iterator)) {
            $it = new \ArrayIterator();
            foreach ($iterator as $file) {
                $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
            }
            $this->iterators[] = $it;
        } else {
            throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
        }

        return $this;
    }

    /**
     * Check if the any results were found.
     *
     * @return bool
     */
    public function hasResults()
    {
        foreach ($this->getIterator() as $_) {
            return true;
        }

        return false;
    }

    /**
     * Counts all the results collected by the iterators.
     *
     * @return int
     */
    public function count()
    {
        return iterator_count($this->getIterator());
    }

    /**
     * @param $dir
     *
     * @return \Iterator
     */
    private function searchInDirectory($dir)
    {
        if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
            $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
        }

        if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
            $this->notPaths[] = '#(^|/)\..+(/|$)#';
        }

        $minDepth = 0;
        $maxDepth = PHP_INT_MAX;

        foreach ($this->depths as $comparator) {
            switch ($comparator->getOperator()) {
                case '>':
                    $minDepth = $comparator->getTarget() + 1;
                    break;
                case '>=':
                    $minDepth = $comparator->getTarget();
                    break;
                case '<':
                    $maxDepth = $comparator->getTarget() - 1;
                    break;
                case '<=':
                    $maxDepth = $comparator->getTarget();
                    break;
                default:
                    $minDepth = $maxDepth = $comparator->getTarget();
            }
        }

        $flags = \RecursiveDirectoryIterator::SKIP_DOTS;

        if ($this->followLinks) {
            $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
        }

        $iterator = new \PHPStanVendor\Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);

        if ($this->exclude) {
            $iterator = new \PHPStanVendor\Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
        }

        $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);

        if ($minDepth > 0 || $maxDepth < PHP_INT_MAX) {
            $iterator = new \PHPStanVendor\Symfony\Component\Finder\Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth);
        }

        if ($this->mode) {
            $iterator = new \PHPStanVendor\Symfony\Component\Finder\Iterator\FileTypeFilterIterator($iterator, $this->mode);
        }

        if ($this->names || $this->notNames) {
            $iterator = new \PHPStanVendor\Symfony\Component\Finder\Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
        }

        if ($this->contains || $this->notContains) {
            $iterator = new \PHPStanVendor\Symfony\Component\Finder\Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
        }

        if ($this->sizes) {
            $iterator = new \PHPStanVendor\Symfony\Component\Finder\Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
        }

        if ($this->dates) {
            $iterator = new \PHPStanVendor\Symfony\Component\Finder\Iterator\DateRangeFilterIterator($iterator, $this->dates);
        }

        if ($this->filters) {
            $iterator = new \PHPStanVendor\Symfony\Component\Finder\Iterator\CustomFilterIterator($iterator, $this->filters);
        }

        if ($this->paths || $this->notPaths) {
            $iterator = new \PHPStanVendor\Symfony\Component\Finder\Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
        }

        if ($this->sort) {
            $iteratorAggregate = new \PHPStanVendor\Symfony\Component\Finder\Iterator\SortableIterator($iterator, $this->sort);
            $iterator = $iteratorAggregate->getIterator();
        }

        return $iterator;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder;

/**
 * Glob matches globbing patterns against text.
 *
 *   if match_glob("foo.*", "foo.bar") echo "matched\n";
 *
 * // prints foo.bar and foo.baz
 * $regex = glob_to_regex("foo.*");
 * for (array('foo.bar', 'foo.baz', 'foo', 'bar') as $t)
 * {
 *   if (/$regex/) echo "matched: $car\n";
 * }
 *
 * Glob implements glob(3) style matching that can be used to match
 * against text, rather than fetching names from a filesystem.
 *
 * Based on the Perl Text::Glob module.
 *
 * @author Fabien Potencier <fabien@symfony.com> PHP port
 * @author     Richard Clamp <richardc@unixbeard.net> Perl version
 * @copyright  2004-2005 Fabien Potencier <fabien@symfony.com>
 * @copyright  2002 Richard Clamp <richardc@unixbeard.net>
 */
class Glob
{
    /**
     * Returns a regexp which is the equivalent of the glob pattern.
     *
     * @param string $glob                The glob pattern
     * @param bool   $strictLeadingDot
     * @param bool   $strictWildcardSlash
     * @param string $delimiter           Optional delimiter
     *
     * @return string regex The regexp
     */
    public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true, $delimiter = '#')
    {
        $firstByte = true;
        $escaping = false;
        $inCurlies = 0;
        $regex = '';
        $sizeGlob = strlen($glob);
        for ($i = 0; $i < $sizeGlob; ++$i) {
            $car = $glob[$i];
            if ($firstByte && $strictLeadingDot && '.' !== $car) {
                $regex .= '(?=[^\.])';
            }

            $firstByte = '/' === $car;

            if ($firstByte && $strictWildcardSlash && isset($glob[$i + 2]) && '**' === $glob[$i + 1].$glob[$i + 2] && (!isset($glob[$i + 3]) || '/' === $glob[$i + 3])) {
                $car = '[^/]++/';
                if (!isset($glob[$i + 3])) {
                    $car .= '?';
                }

                if ($strictLeadingDot) {
                    $car = '(?=[^\.])'.$car;
                }

                $car = '/(?:'.$car.')*';
                $i += 2 + isset($glob[$i + 3]);

                if ('/' === $delimiter) {
                    $car = str_replace('/', '\\/', $car);
                }
            }

            if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
                $regex .= "\\$car";
            } elseif ('*' === $car) {
                $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
            } elseif ('?' === $car) {
                $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
            } elseif ('{' === $car) {
                $regex .= $escaping ? '\\{' : '(';
                if (!$escaping) {
                    ++$inCurlies;
                }
            } elseif ('}' === $car && $inCurlies) {
                $regex .= $escaping ? '}' : ')';
                if (!$escaping) {
                    --$inCurlies;
                }
            } elseif (',' === $car && $inCurlies) {
                $regex .= $escaping ? ',' : '|';
            } elseif ('\\' === $car) {
                if ($escaping) {
                    $regex .= '\\\\';
                    $escaping = false;
                } else {
                    $escaping = true;
                }

                continue;
            } else {
                $regex .= $car;
            }
            $escaping = false;
        }

        return $delimiter.'^'.$regex.'$'.$delimiter;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Iterator;

/**
 * CustomFilterIterator filters files by applying anonymous functions.
 *
 * The anonymous function receives a \SplFileInfo and must return false
 * to remove files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class CustomFilterIterator extends \PHPStanVendor\Symfony\Component\Finder\Iterator\FilterIterator
{
    private $filters = array();

    /**
     * @param \Iterator  $iterator The Iterator to filter
     * @param callable[] $filters  An array of PHP callbacks
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(\Iterator $iterator, array $filters)
    {
        foreach ($filters as $filter) {
            if (!is_callable($filter)) {
                throw new \InvalidArgumentException('Invalid PHP callback.');
            }
        }
        $this->filters = $filters;

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return bool true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $fileinfo = $this->current();

        foreach ($this->filters as $filter) {
            if (false === call_user_func($filter, $fileinfo)) {
                return false;
            }
        }

        return true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Iterator;

/**
 * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DateRangeFilterIterator extends \PHPStanVendor\Symfony\Component\Finder\Iterator\FilterIterator
{
    private $comparators = array();

    /**
     * @param \Iterator        $iterator    The Iterator to filter
     * @param DateComparator[] $comparators An array of DateComparator instances
     */
    public function __construct(\Iterator $iterator, array $comparators)
    {
        $this->comparators = $comparators;

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return bool true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $fileinfo = $this->current();

        if (!file_exists($fileinfo->getPathname())) {
            return false;
        }

        $filedate = $fileinfo->getMTime();
        foreach ($this->comparators as $compare) {
            if (!$compare->test($filedate)) {
                return false;
            }
        }

        return true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Iterator;

/**
 * DepthRangeFilterIterator limits the directory depth.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DepthRangeFilterIterator extends \PHPStanVendor\Symfony\Component\Finder\Iterator\FilterIterator
{
    private $minDepth = 0;

    /**
     * @param \RecursiveIteratorIterator $iterator The Iterator to filter
     * @param int                        $minDepth The min depth
     * @param int                        $maxDepth The max depth
     */
    public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX)
    {
        $this->minDepth = $minDepth;
        $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return bool true if the value should be kept, false otherwise
     */
    public function accept()
    {
        return $this->getInnerIterator()->getDepth() >= $this->minDepth;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Iterator;

/**
 * ExcludeDirectoryFilterIterator filters out directories.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ExcludeDirectoryFilterIterator extends \PHPStanVendor\Symfony\Component\Finder\Iterator\FilterIterator implements \RecursiveIterator
{
    private $iterator;
    private $isRecursive;
    private $excludedDirs = array();
    private $excludedPattern;

    /**
     * @param \Iterator $iterator    The Iterator to filter
     * @param array     $directories An array of directories to exclude
     */
    public function __construct(\Iterator $iterator, array $directories)
    {
        $this->iterator = $iterator;
        $this->isRecursive = $iterator instanceof \RecursiveIterator;
        $patterns = array();
        foreach ($directories as $directory) {
            $directory = rtrim($directory, '/');
            if (!$this->isRecursive || false !== strpos($directory, '/')) {
                $patterns[] = preg_quote($directory, '#');
            } else {
                $this->excludedDirs[$directory] = true;
            }
        }
        if ($patterns) {
            $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#';
        }

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return bool True if the value should be kept, false otherwise
     */
    public function accept()
    {
        if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) {
            return false;
        }

        if ($this->excludedPattern) {
            $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
            $path = str_replace('\\', '/', $path);

            return !preg_match($this->excludedPattern, $path);
        }

        return true;
    }

    public function hasChildren()
    {
        return $this->isRecursive && $this->iterator->hasChildren();
    }

    public function getChildren()
    {
        $children = new self($this->iterator->getChildren(), array());
        $children->excludedDirs = $this->excludedDirs;
        $children->excludedPattern = $this->excludedPattern;

        return $children;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Iterator;

/**
 * FileTypeFilterIterator only keeps files, directories, or both.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FileTypeFilterIterator extends \PHPStanVendor\Symfony\Component\Finder\Iterator\FilterIterator
{
    const ONLY_FILES = 1;
    const ONLY_DIRECTORIES = 2;

    private $mode;

    /**
     * @param \Iterator $iterator The Iterator to filter
     * @param int       $mode     The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES)
     */
    public function __construct(\Iterator $iterator, $mode)
    {
        $this->mode = $mode;

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return bool true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $fileinfo = $this->current();
        if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
            return false;
        } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
            return false;
        }

        return true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Iterator;

/**
 * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings).
 *
 * @author Fabien Potencier  <fabien@symfony.com>
 * @author Włodzimierz Gajda <gajdaw@gajdaw.pl>
 */
class FilecontentFilterIterator extends \PHPStanVendor\Symfony\Component\Finder\Iterator\MultiplePcreFilterIterator
{
    /**
     * Filters the iterator values.
     *
     * @return bool true if the value should be kept, false otherwise
     */
    public function accept()
    {
        if (!$this->matchRegexps && !$this->noMatchRegexps) {
            return true;
        }

        $fileinfo = $this->current();

        if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
            return false;
        }

        $content = $fileinfo->getContents();
        if (!$content) {
            return false;
        }

        return $this->isAccepted($content);
    }

    /**
     * Converts string to regexp if necessary.
     *
     * @param string $str Pattern: string or regexp
     *
     * @return string regexp corresponding to a given string or regexp
     */
    protected function toRegex($str)
    {
        return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Iterator;

/**
 * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FilenameFilterIterator extends \PHPStanVendor\Symfony\Component\Finder\Iterator\MultiplePcreFilterIterator
{
    /**
     * Filters the iterator values.
     *
     * @return bool true if the value should be kept, false otherwise
     */
    public function accept()
    {
        return $this->isAccepted($this->current()->getFilename());
    }

    /**
     * Converts glob to regexp.
     *
     * PCRE patterns are left unchanged.
     * Glob strings are transformed with Glob::toRegex().
     *
     * @param string $str Pattern: glob or regexp
     *
     * @return string regexp corresponding to a given glob or regexp
     */
    protected function toRegex($str)
    {
        return $this->isRegex($str) ? $str : \PHPStanVendor\Symfony\Component\Finder\Glob::toRegex($str);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Iterator;

/**
 * This iterator just overrides the rewind method in order to correct a PHP bug,
 * which existed before version 5.5.23/5.6.7.
 *
 * @see https://bugs.php.net/68557
 *
 * @author Alex Bogomazov
 *
 * @deprecated since 3.4, to be removed in 4.0.
 */
abstract class FilterIterator extends \FilterIterator
{
    /**
     * This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after
     * rewind in some cases.
     *
     * @see FilterIterator::rewind()
     */
    public function rewind()
    {
        if (\PHP_VERSION_ID > 50607 || (\PHP_VERSION_ID > 50523 && \PHP_VERSION_ID < 50600)) {
            parent::rewind();

            return;
        }

        $iterator = $this;
        while ($iterator instanceof \OuterIterator) {
            $innerIterator = $iterator->getInnerIterator();

            if ($innerIterator instanceof \PHPStanVendor\Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator) {
                // this condition is necessary for iterators to work properly with non-local filesystems like ftp
                if ($innerIterator->isRewindable()) {
                    $innerIterator->next();
                    $innerIterator->rewind();
                }
            } elseif ($innerIterator instanceof \FilesystemIterator) {
                $innerIterator->next();
                $innerIterator->rewind();
            }

            $iterator = $innerIterator;
        }

        parent::rewind();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Iterator;

/**
 * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class MultiplePcreFilterIterator extends \PHPStanVendor\Symfony\Component\Finder\Iterator\FilterIterator
{
    protected $matchRegexps = array();
    protected $noMatchRegexps = array();

    /**
     * @param \Iterator $iterator        The Iterator to filter
     * @param array     $matchPatterns   An array of patterns that need to match
     * @param array     $noMatchPatterns An array of patterns that need to not match
     */
    public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
    {
        foreach ($matchPatterns as $pattern) {
            $this->matchRegexps[] = $this->toRegex($pattern);
        }

        foreach ($noMatchPatterns as $pattern) {
            $this->noMatchRegexps[] = $this->toRegex($pattern);
        }

        parent::__construct($iterator);
    }

    /**
     * Checks whether the string is accepted by the regex filters.
     *
     * If there is no regexps defined in the class, this method will accept the string.
     * Such case can be handled by child classes before calling the method if they want to
     * apply a different behavior.
     *
     * @param string $string The string to be matched against filters
     *
     * @return bool
     */
    protected function isAccepted($string)
    {
        // should at least not match one rule to exclude
        foreach ($this->noMatchRegexps as $regex) {
            if (preg_match($regex, $string)) {
                return false;
            }
        }

        // should at least match one rule
        if ($this->matchRegexps) {
            foreach ($this->matchRegexps as $regex) {
                if (preg_match($regex, $string)) {
                    return true;
                }
            }

            return false;
        }

        // If there is no match rules, the file is accepted
        return true;
    }

    /**
     * Checks whether the string is a regex.
     *
     * @param string $str
     *
     * @return bool Whether the given string is a regex
     */
    protected function isRegex($str)
    {
        if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) {
            $start = substr($m[1], 0, 1);
            $end = substr($m[1], -1);

            if ($start === $end) {
                return !preg_match('/[*?[:alnum:] \\\\]/', $start);
            }

            foreach (array(array('{', '}'), array('(', ')'), array('[', ']'), array('<', '>')) as $delimiters) {
                if ($start === $delimiters[0] && $end === $delimiters[1]) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Converts string into regexp.
     *
     * @param string $str Pattern
     *
     * @return string regexp corresponding to a given string
     */
    abstract protected function toRegex($str);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Iterator;

/**
 * PathFilterIterator filters files by path patterns (e.g. some/special/dir).
 *
 * @author Fabien Potencier  <fabien@symfony.com>
 * @author Włodzimierz Gajda <gajdaw@gajdaw.pl>
 */
class PathFilterIterator extends \PHPStanVendor\Symfony\Component\Finder\Iterator\MultiplePcreFilterIterator
{
    /**
     * Filters the iterator values.
     *
     * @return bool true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $filename = $this->current()->getRelativePathname();

        if ('\\' === DIRECTORY_SEPARATOR) {
            $filename = str_replace('\\', '/', $filename);
        }

        return $this->isAccepted($filename);
    }

    /**
     * Converts strings to regexp.
     *
     * PCRE patterns are left unchanged.
     *
     * Default conversion:
     *     'lorem/ipsum/dolor' ==>  'lorem\/ipsum\/dolor/'
     *
     * Use only / as directory separator (on Windows also).
     *
     * @param string $str Pattern: regexp or dirname
     *
     * @return string regexp corresponding to a given string or regexp
     */
    protected function toRegex($str)
    {
        return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Iterator;

/**
 * Extends the \RecursiveDirectoryIterator to support relative paths.
 *
 * @author Victor Berchet <victor@suumit.com>
 */
class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
{
    /**
     * @var bool
     */
    private $ignoreUnreadableDirs;

    /**
     * @var bool
     */
    private $rewindable;

    // these 3 properties take part of the performance optimization to avoid redoing the same work in all iterations
    private $rootPath;
    private $subPath;
    private $directorySeparator = '/';

    /**
     * @param string $path
     * @param int    $flags
     * @param bool   $ignoreUnreadableDirs
     *
     * @throws \RuntimeException
     */
    public function __construct($path, $flags, $ignoreUnreadableDirs = false)
    {
        if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
            throw new \RuntimeException('This iterator only support returning current as fileinfo.');
        }

        parent::__construct($path, $flags);
        $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
        $this->rootPath = $path;
        if ('/' !== DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) {
            $this->directorySeparator = DIRECTORY_SEPARATOR;
        }
    }

    /**
     * Return an instance of SplFileInfo with support for relative paths.
     *
     * @return SplFileInfo File information
     */
    public function current()
    {
        // the logic here avoids redoing the same work in all iterations

        if (null === $subPathname = $this->subPath) {
            $subPathname = $this->subPath = (string) $this->getSubPath();
        }
        if ('' !== $subPathname) {
            $subPathname .= $this->directorySeparator;
        }
        $subPathname .= $this->getFilename();

        return new \PHPStanVendor\Symfony\Component\Finder\SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname);
    }

    /**
     * @return \RecursiveIterator
     *
     * @throws AccessDeniedException
     */
    public function getChildren()
    {
        try {
            $children = parent::getChildren();

            if ($children instanceof self) {
                // parent method will call the constructor with default arguments, so unreadable dirs won't be ignored anymore
                $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;

                // performance optimization to avoid redoing the same work in all children
                $children->rewindable = &$this->rewindable;
                $children->rootPath = $this->rootPath;
            }

            return $children;
        } catch (\UnexpectedValueException $e) {
            if ($this->ignoreUnreadableDirs) {
                // If directory is unreadable and finder is set to ignore it, a fake empty content is returned.
                return new \RecursiveArrayIterator(array());
            } else {
                throw new \PHPStanVendor\Symfony\Component\Finder\Exception\AccessDeniedException($e->getMessage(), $e->getCode(), $e);
            }
        }
    }

    /**
     * Do nothing for non rewindable stream.
     */
    public function rewind()
    {
        if (false === $this->isRewindable()) {
            return;
        }

        // @see https://bugs.php.net/68557
        if (\PHP_VERSION_ID < 50523 || \PHP_VERSION_ID >= 50600 && \PHP_VERSION_ID < 50607) {
            parent::next();
        }

        parent::rewind();
    }

    /**
     * Checks if the stream is rewindable.
     *
     * @return bool true when the stream is rewindable, false otherwise
     */
    public function isRewindable()
    {
        if (null !== $this->rewindable) {
            return $this->rewindable;
        }

        // workaround for an HHVM bug, should be removed when https://github.com/facebook/hhvm/issues/7281 is fixed
        if ('' === $this->getPath()) {
            return $this->rewindable = false;
        }

        if (false !== $stream = @opendir($this->getPath())) {
            $infos = stream_get_meta_data($stream);
            closedir($stream);

            if ($infos['seekable']) {
                return $this->rewindable = true;
            }
        }

        return $this->rewindable = false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Iterator;

/**
 * SizeRangeFilterIterator filters out files that are not in the given size range.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SizeRangeFilterIterator extends \PHPStanVendor\Symfony\Component\Finder\Iterator\FilterIterator
{
    private $comparators = array();

    /**
     * @param \Iterator          $iterator    The Iterator to filter
     * @param NumberComparator[] $comparators An array of NumberComparator instances
     */
    public function __construct(\Iterator $iterator, array $comparators)
    {
        $this->comparators = $comparators;

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return bool true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $fileinfo = $this->current();
        if (!$fileinfo->isFile()) {
            return true;
        }

        $filesize = $fileinfo->getSize();
        foreach ($this->comparators as $compare) {
            if (!$compare->test($filesize)) {
                return false;
            }
        }

        return true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder\Iterator;

/**
 * SortableIterator applies a sort on a given Iterator.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SortableIterator implements \IteratorAggregate
{
    const SORT_BY_NAME = 1;
    const SORT_BY_TYPE = 2;
    const SORT_BY_ACCESSED_TIME = 3;
    const SORT_BY_CHANGED_TIME = 4;
    const SORT_BY_MODIFIED_TIME = 5;

    private $iterator;
    private $sort;

    /**
     * @param \Traversable $iterator The Iterator to filter
     * @param int|callable $sort     The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback)
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(\Traversable $iterator, $sort)
    {
        $this->iterator = $iterator;

        if (self::SORT_BY_NAME === $sort) {
            $this->sort = function ($a, $b) {
                return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
            };
        } elseif (self::SORT_BY_TYPE === $sort) {
            $this->sort = function ($a, $b) {
                if ($a->isDir() && $b->isFile()) {
                    return -1;
                } elseif ($a->isFile() && $b->isDir()) {
                    return 1;
                }

                return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
            };
        } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
            $this->sort = function ($a, $b) {
                return $a->getATime() - $b->getATime();
            };
        } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
            $this->sort = function ($a, $b) {
                return $a->getCTime() - $b->getCTime();
            };
        } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
            $this->sort = function ($a, $b) {
                return $a->getMTime() - $b->getMTime();
            };
        } elseif (is_callable($sort)) {
            $this->sort = $sort;
        } else {
            throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
        }
    }

    public function getIterator()
    {
        $array = iterator_to_array($this->iterator, true);
        uasort($array, $this->sort);

        return new \ArrayIterator($array);
    }
}

Copyright (c) 2004-2018 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

Finder Component
================

The Finder component finds files and directories via an intuitive fluent
interface.

Resources
---------

  * [Documentation](https://symfony.com/doc/current/components/finder.html)
  * [Contributing](https://symfony.com/doc/current/contributing/index.html)
  * [Report issues](https://github.com/symfony/symfony/issues) and
    [send Pull Requests](https://github.com/symfony/symfony/pulls)
    in the [main Symfony repository](https://github.com/symfony/symfony)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Component\Finder;

/**
 * Extends \SplFileInfo to support relative paths.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SplFileInfo extends \SplFileInfo
{
    private $relativePath;
    private $relativePathname;

    /**
     * @param string $file             The file name
     * @param string $relativePath     The relative path
     * @param string $relativePathname The relative path name
     */
    public function __construct($file, $relativePath, $relativePathname)
    {
        parent::__construct($file);
        $this->relativePath = $relativePath;
        $this->relativePathname = $relativePathname;
    }

    /**
     * Returns the relative path.
     *
     * This path does not contain the file name.
     *
     * @return string the relative path
     */
    public function getRelativePath()
    {
        return $this->relativePath;
    }

    /**
     * Returns the relative path name.
     *
     * This path contains the file name.
     *
     * @return string the relative path name
     */
    public function getRelativePathname()
    {
        return $this->relativePathname;
    }

    /**
     * Returns the contents of the file.
     *
     * @return string the contents of the file
     *
     * @throws \RuntimeException
     */
    public function getContents()
    {
        $level = error_reporting(0);
        $content = file_get_contents($this->getPathname());
        error_reporting($level);
        if (false === $content) {
            $error = error_get_last();
            throw new \RuntimeException($error['message']);
        }

        return $content;
    }
}
{
    "name": "symfony/finder",
    "type": "library",
    "description": "Symfony Finder Component",
    "keywords": [],
    "homepage": "https://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https://symfony.com/contributors"
        }
    ],
    "require": {
        "php": "^5.5.9|>=7.0.8"
    },
    "autoload": {
        "psr-4": { "Symfony\\Component\\Finder\\": "" },
        "exclude-from-classmap": [
            "/Tests/"
        ]
    },
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-master": "3.4-dev"
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>

<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
         backupGlobals="false"
         colors="true"
         bootstrap="vendor/autoload.php"
         failOnRisky="true"
         failOnWarning="true"
>
    <php>
        <ini name="error_reporting" value="-1" />
    </php>

    <testsuites>
        <testsuite name="Symfony Finder Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>

Copyright (c) 2014-2016 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace PHPStanVendor\Symfony\Polyfill\Mbstring;

/**
 * Partial mbstring implementation in PHP, iconv based, UTF-8 centric.
 *
 * Implemented:
 * - mb_chr                  - Returns a specific character from its Unicode code point
 * - mb_convert_encoding     - Convert character encoding
 * - mb_convert_variables    - Convert character code in variable(s)
 * - mb_decode_mimeheader    - Decode string in MIME header field
 * - mb_encode_mimeheader    - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED
 * - mb_convert_case         - Perform case folding on a string
 * - mb_get_info             - Get internal settings of mbstring
 * - mb_http_input           - Detect HTTP input character encoding
 * - mb_http_output          - Set/Get HTTP output character encoding
 * - mb_internal_encoding    - Set/Get internal character encoding
 * - mb_list_encodings       - Returns an array of all supported encodings
 * - mb_ord                  - Returns the Unicode code point of a character
 * - mb_output_handler       - Callback function converts character encoding in output buffer
 * - mb_scrub                - Replaces ill-formed byte sequences with substitute characters
 * - mb_strlen               - Get string length
 * - mb_strpos               - Find position of first occurrence of string in a string
 * - mb_strrpos              - Find position of last occurrence of a string in a string
 * - mb_strtolower           - Make a string lowercase
 * - mb_strtoupper           - Make a string uppercase
 * - mb_substitute_character - Set/Get substitution character
 * - mb_substr               - Get part of string
 * - mb_stripos              - Finds position of first occurrence of a string within another, case insensitive
 * - mb_stristr              - Finds first occurrence of a string within another, case insensitive
 * - mb_strrchr              - Finds the last occurrence of a character in a string within another
 * - mb_strrichr             - Finds the last occurrence of a character in a string within another, case insensitive
 * - mb_strripos             - Finds position of last occurrence of a string within another, case insensitive
 * - mb_strstr               - Finds first occurrence of a string within anothers
 * - mb_strwidth             - Return width of string
 * - mb_substr_count         - Count the number of substring occurrences
 *
 * Not implemented:
 * - mb_convert_kana         - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
 * - mb_decode_numericentity - Decode HTML numeric string reference to character
 * - mb_encode_numericentity - Encode character to HTML numeric string reference
 * - mb_ereg_*               - Regular expression with multibyte support
 * - mb_parse_str            - Parse GET/POST/COOKIE data and set global variable
 * - mb_preferred_mime_name  - Get MIME charset string
 * - mb_regex_encoding       - Returns current encoding for multibyte regex as string
 * - mb_regex_set_options    - Set/Get the default options for mbregex functions
 * - mb_send_mail            - Send encoded mail
 * - mb_split                - Split multibyte string using regular expression
 * - mb_strcut               - Get part of string
 * - mb_strimwidth           - Get truncated string with specified width
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
final class Mbstring
{
    const MB_CASE_FOLD = PHP_INT_MAX;

    private static $encodingList = array('ASCII', 'UTF-8');
    private static $language = 'neutral';
    private static $internalEncoding = 'UTF-8';
    private static $caseFold = array(
        array('µ','ſ',"\xCD\x85",'ς',"\xCF\x90","\xCF\x91","\xCF\x95","\xCF\x96","\xCF\xB0","\xCF\xB1","\xCF\xB5","\xE1\xBA\x9B","\xE1\xBE\xBE"),
        array('μ','s','ι',       'σ','β',       'θ',       'φ',       'π',       'κ',       'ρ',       'ε',       "\xE1\xB9\xA1",'ι'),
    );

    public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
    {
        if (is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
            $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
        } else {
            $fromEncoding = self::getEncoding($fromEncoding);
        }

        $toEncoding = self::getEncoding($toEncoding);

        if ('BASE64' === $fromEncoding) {
            $s = base64_decode($s);
            $fromEncoding = $toEncoding;
        }

        if ('BASE64' === $toEncoding) {
            return base64_encode($s);
        }

        if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
            if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
                $fromEncoding = 'Windows-1252';
            }
            if ('UTF-8' !== $fromEncoding) {
                $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
            }

            return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s);
        }

        if ('HTML-ENTITIES' === $fromEncoding) {
            $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8');
            $fromEncoding = 'UTF-8';
        }

        return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
    }

    public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null)
    {
        $vars = array(&$a, &$b, &$c, &$d, &$e, &$f);

        $ok = true;
        array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
            if (false === $v = \PHPStanVendor\Symfony\Polyfill\Mbstring\Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
                $ok = false;
            }
        });

        return $ok ? $fromEncoding : false;
    }

    public static function mb_decode_mimeheader($s)
    {
        return iconv_mime_decode($s, 2, self::$internalEncoding);
    }

    public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
    {
        trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING);
    }

    public static function mb_convert_case($s, $mode, $encoding = null)
    {
        if ('' === $s .= '') {
            return '';
        }

        $encoding = self::getEncoding($encoding);

        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $s)) {
                $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
            }
        } else {
            $s = iconv($encoding, 'UTF-8//IGNORE', $s);
        }

        if (MB_CASE_TITLE == $mode) {
            $s = preg_replace_callback('/\b\p{Ll}/u', array(__CLASS__, 'title_case_upper'), $s);
            $s = preg_replace_callback('/\B[\p{Lu}\p{Lt}]+/u', array(__CLASS__, 'title_case_lower'), $s);
        } else {
            if (MB_CASE_UPPER == $mode) {
                static $upper = null;
                if (null === $upper) {
                    $upper = self::getData('upperCase');
                }
                $map = $upper;
            } else {
                if (self::MB_CASE_FOLD === $mode) {
                    $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s);
                }

                static $lower = null;
                if (null === $lower) {
                    $lower = self::getData('lowerCase');
                }
                $map = $lower;
            }

            static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);

            $i = 0;
            $len = strlen($s);

            while ($i < $len) {
                $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
                $uchr = substr($s, $i, $ulen);
                $i += $ulen;

                if (isset($map[$uchr])) {
                    $uchr = $map[$uchr];
                    $nlen = strlen($uchr);

                    if ($nlen == $ulen) {
                        $nlen = $i;
                        do {
                            $s[--$nlen] = $uchr[--$ulen];
                        } while ($ulen);
                    } else {
                        $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
                        $len += $nlen - $ulen;
                        $i   += $nlen - $ulen;
                    }
                }
            }
        }

        if (null === $encoding) {
            return $s;
        }

        return iconv('UTF-8', $encoding.'//IGNORE', $s);
    }

    public static function mb_internal_encoding($encoding = null)
    {
        if (null === $encoding) {
            return self::$internalEncoding;
        }

        $encoding = self::getEncoding($encoding);

        if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) {
            self::$internalEncoding = $encoding;

            return true;
        }

        return false;
    }

    public static function mb_language($lang = null)
    {
        if (null === $lang) {
            return self::$language;
        }

        switch ($lang = strtolower($lang)) {
            case 'uni':
            case 'neutral':
                self::$language = $lang;

                return true;
        }

        return false;
    }

    public static function mb_list_encodings()
    {
        return array('UTF-8');
    }

    public static function mb_encoding_aliases($encoding)
    {
        switch (strtoupper($encoding)) {
            case 'UTF8':
            case 'UTF-8':
                return array('utf8');
        }

        return false;
    }

    public static function mb_check_encoding($var = null, $encoding = null)
    {
        if (null === $encoding) {
            if (null === $var) {
                return false;
            }
            $encoding = self::$internalEncoding;
        }

        return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var);
    }

    public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
    {
        if (null === $encodingList) {
            $encodingList = self::$encodingList;
        } else {
            if (!is_array($encodingList)) {
                $encodingList = array_map('trim', explode(',', $encodingList));
            }
            $encodingList = array_map('strtoupper', $encodingList);
        }

        foreach ($encodingList as $enc) {
            switch ($enc) {
                case 'ASCII':
                    if (!preg_match('/[\x80-\xFF]/', $str)) {
                        return $enc;
                    }
                    break;

                case 'UTF8':
                case 'UTF-8':
                    if (preg_match('//u', $str)) {
                        return 'UTF-8';
                    }
                    break;

                default:
                    if (0 === strncmp($enc, 'ISO-8859-', 9)) {
                        return $enc;
                    }
            }
        }

        return false;
    }

    public static function mb_detect_order($encodingList = null)
    {
        if (null === $encodingList) {
            return self::$encodingList;
        }

        if (!is_array($encodingList)) {
            $encodingList = array_map('trim', explode(',', $encodingList));
        }
        $encodingList = array_map('strtoupper', $encodingList);

        foreach ($encodingList as $enc) {
            switch ($enc) {
                default:
                    if (strncmp($enc, 'ISO-8859-', 9)) {
                        return false;
                    }
                case 'ASCII':
                case 'UTF8':
                case 'UTF-8':
            }
        }

        self::$encodingList = $encodingList;

        return true;
    }

    public static function mb_strlen($s, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return strlen($s);
        }

        return @iconv_strlen($s, $encoding);
    }

    public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return strpos($haystack, $needle, $offset);
        }

        if ('' === $needle .= '') {
            trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING);

            return false;
        }

        return iconv_strpos($haystack, $needle, $offset, $encoding);
    }

    public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return strrpos($haystack, $needle, $offset);
        }

        if ($offset != (int) $offset) {
            $offset = 0;
        } elseif ($offset = (int) $offset) {
            if ($offset < 0) {
                $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
                $offset = 0;
            } else {
                $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
            }
        }

        $pos = iconv_strrpos($haystack, $needle, $encoding);

        return false !== $pos ? $offset + $pos : false;
    }

    public static function mb_strtolower($s, $encoding = null)
    {
        return self::mb_convert_case($s, MB_CASE_LOWER, $encoding);
    }

    public static function mb_strtoupper($s, $encoding = null)
    {
        return self::mb_convert_case($s, MB_CASE_UPPER, $encoding);
    }

    public static function mb_substitute_character($c = null)
    {
        if (0 === strcasecmp($c, 'none')) {
            return true;
        }

        return null !== $c ? false : 'none';
    }

    public static function mb_substr($s, $start, $length = null, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return substr($s, $start, null === $length ? 2147483647 : $length);
        }

        if ($start < 0) {
            $start = iconv_strlen($s, $encoding) + $start;
            if ($start < 0) {
                $start = 0;
            }
        }

        if (null === $length) {
            $length = 2147483647;
        } elseif ($length < 0) {
            $length = iconv_strlen($s, $encoding) + $length - $start;
            if ($length < 0) {
                return '';
            }
        }

        return iconv_substr($s, $start, $length, $encoding).'';
    }

    public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
        $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);

        return self::mb_strpos($haystack, $needle, $offset, $encoding);
    }

    public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
    {
        $pos = self::mb_stripos($haystack, $needle, 0, $encoding);

        return self::getSubpart($pos, $part, $haystack, $encoding);
    }

    public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return strrchr($haystack, $needle, $part);
        }
        $needle = self::mb_substr($needle, 0, 1, $encoding);
        $pos = iconv_strrpos($haystack, $needle, $encoding);

        return self::getSubpart($pos, $part, $haystack, $encoding);
    }

    public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
    {
        $needle = self::mb_substr($needle, 0, 1, $encoding);
        $pos = self::mb_strripos($haystack, $needle, $encoding);

        return self::getSubpart($pos, $part, $haystack, $encoding);
    }

    public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
        $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);

        return self::mb_strrpos($haystack, $needle, $offset, $encoding);
    }

    public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
    {
        $pos = strpos($haystack, $needle);
        if (false === $pos) {
            return false;
        }
        if ($part) {
            return substr($haystack, 0, $pos);
        }

        return substr($haystack, $pos);
    }

    public static function mb_get_info($type = 'all')
    {
        $info = array(
            'internal_encoding' => self::$internalEncoding,
            'http_output' => 'pass',
            'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
            'func_overload' => 0,
            'func_overload_list' => 'no overload',
            'mail_charset' => 'UTF-8',
            'mail_header_encoding' => 'BASE64',
            'mail_body_encoding' => 'BASE64',
            'illegal_chars' => 0,
            'encoding_translation' => 'Off',
            'language' => self::$language,
            'detect_order' => self::$encodingList,
            'substitute_character' => 'none',
            'strict_detection' => 'Off',
        );

        if ('all' === $type) {
            return $info;
        }
        if (isset($info[$type])) {
            return $info[$type];
        }

        return false;
    }

    public static function mb_http_input($type = '')
    {
        return false;
    }

    public static function mb_http_output($encoding = null)
    {
        return null !== $encoding ? 'pass' === $encoding : 'pass';
    }

    public static function mb_strwidth($s, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);

        if ('UTF-8' !== $encoding) {
            $s = iconv($encoding, 'UTF-8//IGNORE', $s);
        }

        $s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide);

        return ($wide << 1) + iconv_strlen($s, 'UTF-8');
    }

    public static function mb_substr_count($haystack, $needle, $encoding = null)
    {
        return substr_count($haystack, $needle);
    }

    public static function mb_output_handler($contents, $status)
    {
        return $contents;
    }

    public static function mb_chr($code, $encoding = null)
    {
        if (0x80 > $code %= 0x200000) {
            $s = chr($code);
        } elseif (0x800 > $code) {
            $s = chr(0xC0 | $code >> 6).chr(0x80 | $code & 0x3F);
        } elseif (0x10000 > $code) {
            $s = chr(0xE0 | $code >> 12).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F);
        } else {
            $s = chr(0xF0 | $code >> 18).chr(0x80 | $code >> 12 & 0x3F).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F);
        }

        if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
            $s = mb_convert_encoding($s, $encoding, 'UTF-8');
        }

        return $s;
    }

    public static function mb_ord($s, $encoding = null)
    {
        if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
            $s = mb_convert_encoding($s, 'UTF-8', $encoding);
        }

        $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
        if (0xF0 <= $code) {
            return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
        }
        if (0xE0 <= $code) {
            return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
        }
        if (0xC0 <= $code) {
            return (($code - 0xC0) << 6) + $s[2] - 0x80;
        }

        return $code;
    }

    private static function getSubpart($pos, $part, $haystack, $encoding)
    {
        if (false === $pos) {
            return false;
        }
        if ($part) {
            return self::mb_substr($haystack, 0, $pos, $encoding);
        }

        return self::mb_substr($haystack, $pos, null, $encoding);
    }

    private static function html_encoding_callback($m)
    {
        $i = 1;
        $entities = '';
        $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8'));

        while (isset($m[$i])) {
            if (0x80 > $m[$i]) {
                $entities .= chr($m[$i++]);
                continue;
            }
            if (0xF0 <= $m[$i]) {
                $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
            } elseif (0xE0 <= $m[$i]) {
                $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
            } else {
                $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
            }

            $entities .= '&#'.$c.';';
        }

        return $entities;
    }

    private static function title_case_lower($s)
    {
        return self::mb_convert_case($s[0], MB_CASE_LOWER, 'UTF-8');
    }

    private static function title_case_upper($s)
    {
        return self::mb_convert_case($s[0], MB_CASE_UPPER, 'UTF-8');
    }

    private static function getData($file)
    {
        if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
            return require $file;
        }

        return false;
    }

    private static function getEncoding($encoding)
    {
        if (null === $encoding) {
            return self::$internalEncoding;
        }

        $encoding = strtoupper($encoding);

        if ('8BIT' === $encoding || 'BINARY' === $encoding) {
            return 'CP850';
        }
        if ('UTF8' === $encoding) {
            return 'UTF-8';
        }

        return $encoding;
    }
}
Symfony Polyfill / Mbstring
===========================

This component provides a partial, native PHP implementation for the
[Mbstring](http://php.net/mbstring) extension.

More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).

License
=======

This library is released under the [MIT license](LICENSE).
<?php

static $data = array (
  'A' => 'a',
  'B' => 'b',
  'C' => 'c',
  'D' => 'd',
  'E' => 'e',
  'F' => 'f',
  'G' => 'g',
  'H' => 'h',
  'I' => 'i',
  'J' => 'j',
  'K' => 'k',
  'L' => 'l',
  'M' => 'm',
  'N' => 'n',
  'O' => 'o',
  'P' => 'p',
  'Q' => 'q',
  'R' => 'r',
  'S' => 's',
  'T' => 't',
  'U' => 'u',
  'V' => 'v',
  'W' => 'w',
  'X' => 'x',
  'Y' => 'y',
  'Z' => 'z',
  'À' => 'à',
  'Á' => 'á',
  'Â' => 'â',
  'Ã' => 'ã',
  'Ä' => 'ä',
  'Å' => 'å',
  'Æ' => 'æ',
  'Ç' => 'ç',
  'È' => 'è',
  'É' => 'é',
  'Ê' => 'ê',
  'Ë' => 'ë',
  'Ì' => 'ì',
  'Í' => 'í',
  'Î' => 'î',
  'Ï' => 'ï',
  'Ð' => 'ð',
  'Ñ' => 'ñ',
  'Ò' => 'ò',
  'Ó' => 'ó',
  'Ô' => 'ô',
  'Õ' => 'õ',
  'Ö' => 'ö',
  'Ø' => 'ø',
  'Ù' => 'ù',
  'Ú' => 'ú',
  'Û' => 'û',
  'Ü' => 'ü',
  'Ý' => 'ý',
  'Þ' => 'þ',
  'Ā' => 'ā',
  'Ă' => 'ă',
  'Ą' => 'ą',
  'Ć' => 'ć',
  'Ĉ' => 'ĉ',
  'Ċ' => 'ċ',
  'Č' => 'č',
  'Ď' => 'ď',
  'Đ' => 'đ',
  'Ē' => 'ē',
  'Ĕ' => 'ĕ',
  'Ė' => 'ė',
  'Ę' => 'ę',
  'Ě' => 'ě',
  'Ĝ' => 'ĝ',
  'Ğ' => 'ğ',
  'Ġ' => 'ġ',
  'Ģ' => 'ģ',
  'Ĥ' => 'ĥ',
  'Ħ' => 'ħ',
  'Ĩ' => 'ĩ',
  'Ī' => 'ī',
  'Ĭ' => 'ĭ',
  'Į' => 'į',
  'İ' => 'i',
  'IJ' => 'ij',
  'Ĵ' => 'ĵ',
  'Ķ' => 'ķ',
  'Ĺ' => 'ĺ',
  'Ļ' => 'ļ',
  'Ľ' => 'ľ',
  'Ŀ' => 'ŀ',
  'Ł' => 'ł',
  'Ń' => 'ń',
  'Ņ' => 'ņ',
  'Ň' => 'ň',
  'Ŋ' => 'ŋ',
  'Ō' => 'ō',
  'Ŏ' => 'ŏ',
  'Ő' => 'ő',
  'Œ' => 'œ',
  'Ŕ' => 'ŕ',
  'Ŗ' => 'ŗ',
  'Ř' => 'ř',
  'Ś' => 'ś',
  'Ŝ' => 'ŝ',
  'Ş' => 'ş',
  'Š' => 'š',
  'Ţ' => 'ţ',
  'Ť' => 'ť',
  'Ŧ' => 'ŧ',
  'Ũ' => 'ũ',
  'Ū' => 'ū',
  'Ŭ' => 'ŭ',
  'Ů' => 'ů',
  'Ű' => 'ű',
  'Ų' => 'ų',
  'Ŵ' => 'ŵ',
  'Ŷ' => 'ŷ',
  'Ÿ' => 'ÿ',
  'Ź' => 'ź',
  'Ż' => 'ż',
  'Ž' => 'ž',
  'Ɓ' => 'ɓ',
  'Ƃ' => 'ƃ',
  'Ƅ' => 'ƅ',
  'Ɔ' => 'ɔ',
  'Ƈ' => 'ƈ',
  'Ɖ' => 'ɖ',
  'Ɗ' => 'ɗ',
  'Ƌ' => 'ƌ',
  'Ǝ' => 'ǝ',
  'Ə' => 'ə',
  'Ɛ' => 'ɛ',
  'Ƒ' => 'ƒ',
  'Ɠ' => 'ɠ',
  'Ɣ' => 'ɣ',
  'Ɩ' => 'ɩ',
  'Ɨ' => 'ɨ',
  'Ƙ' => 'ƙ',
  'Ɯ' => 'ɯ',
  'Ɲ' => 'ɲ',
  'Ɵ' => 'ɵ',
  'Ơ' => 'ơ',
  'Ƣ' => 'ƣ',
  'Ƥ' => 'ƥ',
  'Ʀ' => 'ʀ',
  'Ƨ' => 'ƨ',
  'Ʃ' => 'ʃ',
  'Ƭ' => 'ƭ',
  'Ʈ' => 'ʈ',
  'Ư' => 'ư',
  'Ʊ' => 'ʊ',
  'Ʋ' => 'ʋ',
  'Ƴ' => 'ƴ',
  'Ƶ' => 'ƶ',
  'Ʒ' => 'ʒ',
  'Ƹ' => 'ƹ',
  'Ƽ' => 'ƽ',
  'DŽ' => 'dž',
  'Dž' => 'dž',
  'LJ' => 'lj',
  'Lj' => 'lj',
  'NJ' => 'nj',
  'Nj' => 'nj',
  'Ǎ' => 'ǎ',
  'Ǐ' => 'ǐ',
  'Ǒ' => 'ǒ',
  'Ǔ' => 'ǔ',
  'Ǖ' => 'ǖ',
  'Ǘ' => 'ǘ',
  'Ǚ' => 'ǚ',
  'Ǜ' => 'ǜ',
  'Ǟ' => 'ǟ',
  'Ǡ' => 'ǡ',
  'Ǣ' => 'ǣ',
  'Ǥ' => 'ǥ',
  'Ǧ' => 'ǧ',
  'Ǩ' => 'ǩ',
  'Ǫ' => 'ǫ',
  'Ǭ' => 'ǭ',
  'Ǯ' => 'ǯ',
  'DZ' => 'dz',
  'Dz' => 'dz',
  'Ǵ' => 'ǵ',
  'Ƕ' => 'ƕ',
  'Ƿ' => 'ƿ',
  'Ǹ' => 'ǹ',
  'Ǻ' => 'ǻ',
  'Ǽ' => 'ǽ',
  'Ǿ' => 'ǿ',
  'Ȁ' => 'ȁ',
  'Ȃ' => 'ȃ',
  'Ȅ' => 'ȅ',
  'Ȇ' => 'ȇ',
  'Ȉ' => 'ȉ',
  'Ȋ' => 'ȋ',
  'Ȍ' => 'ȍ',
  'Ȏ' => 'ȏ',
  'Ȑ' => 'ȑ',
  'Ȓ' => 'ȓ',
  'Ȕ' => 'ȕ',
  'Ȗ' => 'ȗ',
  'Ș' => 'ș',
  'Ț' => 'ț',
  'Ȝ' => 'ȝ',
  'Ȟ' => 'ȟ',
  'Ƞ' => 'ƞ',
  'Ȣ' => 'ȣ',
  'Ȥ' => 'ȥ',
  'Ȧ' => 'ȧ',
  'Ȩ' => 'ȩ',
  'Ȫ' => 'ȫ',
  'Ȭ' => 'ȭ',
  'Ȯ' => 'ȯ',
  'Ȱ' => 'ȱ',
  'Ȳ' => 'ȳ',
  'Ⱥ' => 'ⱥ',
  'Ȼ' => 'ȼ',
  'Ƚ' => 'ƚ',
  'Ⱦ' => 'ⱦ',
  'Ɂ' => 'ɂ',
  'Ƀ' => 'ƀ',
  'Ʉ' => 'ʉ',
  'Ʌ' => 'ʌ',
  'Ɇ' => 'ɇ',
  'Ɉ' => 'ɉ',
  'Ɋ' => 'ɋ',
  'Ɍ' => 'ɍ',
  'Ɏ' => 'ɏ',
  'Ͱ' => 'ͱ',
  'Ͳ' => 'ͳ',
  'Ͷ' => 'ͷ',
  'Ϳ' => 'ϳ',
  'Ά' => 'ά',
  'Έ' => 'έ',
  'Ή' => 'ή',
  'Ί' => 'ί',
  'Ό' => 'ό',
  'Ύ' => 'ύ',
  'Ώ' => 'ώ',
  'Α' => 'α',
  'Β' => 'β',
  'Γ' => 'γ',
  'Δ' => 'δ',
  'Ε' => 'ε',
  'Ζ' => 'ζ',
  'Η' => 'η',
  'Θ' => 'θ',
  'Ι' => 'ι',
  'Κ' => 'κ',
  'Λ' => 'λ',
  'Μ' => 'μ',
  'Ν' => 'ν',
  'Ξ' => 'ξ',
  'Ο' => 'ο',
  'Π' => 'π',
  'Ρ' => 'ρ',
  'Σ' => 'σ',
  'Τ' => 'τ',
  'Υ' => 'υ',
  'Φ' => 'φ',
  'Χ' => 'χ',
  'Ψ' => 'ψ',
  'Ω' => 'ω',
  'Ϊ' => 'ϊ',
  'Ϋ' => 'ϋ',
  'Ϗ' => 'ϗ',
  'Ϙ' => 'ϙ',
  'Ϛ' => 'ϛ',
  'Ϝ' => 'ϝ',
  'Ϟ' => 'ϟ',
  'Ϡ' => 'ϡ',
  'Ϣ' => 'ϣ',
  'Ϥ' => 'ϥ',
  'Ϧ' => 'ϧ',
  'Ϩ' => 'ϩ',
  'Ϫ' => 'ϫ',
  'Ϭ' => 'ϭ',
  'Ϯ' => 'ϯ',
  'ϴ' => 'θ',
  'Ϸ' => 'ϸ',
  'Ϲ' => 'ϲ',
  'Ϻ' => 'ϻ',
  'Ͻ' => 'ͻ',
  'Ͼ' => 'ͼ',
  'Ͽ' => 'ͽ',
  'Ѐ' => 'ѐ',
  'Ё' => 'ё',
  'Ђ' => 'ђ',
  'Ѓ' => 'ѓ',
  'Є' => 'є',
  'Ѕ' => 'ѕ',
  'І' => 'і',
  'Ї' => 'ї',
  'Ј' => 'ј',
  'Љ' => 'љ',
  'Њ' => 'њ',
  'Ћ' => 'ћ',
  'Ќ' => 'ќ',
  'Ѝ' => 'ѝ',
  'Ў' => 'ў',
  'Џ' => 'џ',
  'А' => 'а',
  'Б' => 'б',
  'В' => 'в',
  'Г' => 'г',
  'Д' => 'д',
  'Е' => 'е',
  'Ж' => 'ж',
  'З' => 'з',
  'И' => 'и',
  'Й' => 'й',
  'К' => 'к',
  'Л' => 'л',
  'М' => 'м',
  'Н' => 'н',
  'О' => 'о',
  'П' => 'п',
  'Р' => 'р',
  'С' => 'с',
  'Т' => 'т',
  'У' => 'у',
  'Ф' => 'ф',
  'Х' => 'х',
  'Ц' => 'ц',
  'Ч' => 'ч',
  'Ш' => 'ш',
  'Щ' => 'щ',
  'Ъ' => 'ъ',
  'Ы' => 'ы',
  'Ь' => 'ь',
  'Э' => 'э',
  'Ю' => 'ю',
  'Я' => 'я',
  'Ѡ' => 'ѡ',
  'Ѣ' => 'ѣ',
  'Ѥ' => 'ѥ',
  'Ѧ' => 'ѧ',
  'Ѩ' => 'ѩ',
  'Ѫ' => 'ѫ',
  'Ѭ' => 'ѭ',
  'Ѯ' => 'ѯ',
  'Ѱ' => 'ѱ',
  'Ѳ' => 'ѳ',
  'Ѵ' => 'ѵ',
  'Ѷ' => 'ѷ',
  'Ѹ' => 'ѹ',
  'Ѻ' => 'ѻ',
  'Ѽ' => 'ѽ',
  'Ѿ' => 'ѿ',
  'Ҁ' => 'ҁ',
  'Ҋ' => 'ҋ',
  'Ҍ' => 'ҍ',
  'Ҏ' => 'ҏ',
  'Ґ' => 'ґ',
  'Ғ' => 'ғ',
  'Ҕ' => 'ҕ',
  'Җ' => 'җ',
  'Ҙ' => 'ҙ',
  'Қ' => 'қ',
  'Ҝ' => 'ҝ',
  'Ҟ' => 'ҟ',
  'Ҡ' => 'ҡ',
  'Ң' => 'ң',
  'Ҥ' => 'ҥ',
  'Ҧ' => 'ҧ',
  'Ҩ' => 'ҩ',
  'Ҫ' => 'ҫ',
  'Ҭ' => 'ҭ',
  'Ү' => 'ү',
  'Ұ' => 'ұ',
  'Ҳ' => 'ҳ',
  'Ҵ' => 'ҵ',
  'Ҷ' => 'ҷ',
  'Ҹ' => 'ҹ',
  'Һ' => 'һ',
  'Ҽ' => 'ҽ',
  'Ҿ' => 'ҿ',
  'Ӏ' => 'ӏ',
  'Ӂ' => 'ӂ',
  'Ӄ' => 'ӄ',
  'Ӆ' => 'ӆ',
  'Ӈ' => 'ӈ',
  'Ӊ' => 'ӊ',
  'Ӌ' => 'ӌ',
  'Ӎ' => 'ӎ',
  'Ӑ' => 'ӑ',
  'Ӓ' => 'ӓ',
  'Ӕ' => 'ӕ',
  'Ӗ' => 'ӗ',
  'Ә' => 'ә',
  'Ӛ' => 'ӛ',
  'Ӝ' => 'ӝ',
  'Ӟ' => 'ӟ',
  'Ӡ' => 'ӡ',
  'Ӣ' => 'ӣ',
  'Ӥ' => 'ӥ',
  'Ӧ' => 'ӧ',
  'Ө' => 'ө',
  'Ӫ' => 'ӫ',
  'Ӭ' => 'ӭ',
  'Ӯ' => 'ӯ',
  'Ӱ' => 'ӱ',
  'Ӳ' => 'ӳ',
  'Ӵ' => 'ӵ',
  'Ӷ' => 'ӷ',
  'Ӹ' => 'ӹ',
  'Ӻ' => 'ӻ',
  'Ӽ' => 'ӽ',
  'Ӿ' => 'ӿ',
  'Ԁ' => 'ԁ',
  'Ԃ' => 'ԃ',
  'Ԅ' => 'ԅ',
  'Ԇ' => 'ԇ',
  'Ԉ' => 'ԉ',
  'Ԋ' => 'ԋ',
  'Ԍ' => 'ԍ',
  'Ԏ' => 'ԏ',
  'Ԑ' => 'ԑ',
  'Ԓ' => 'ԓ',
  'Ԕ' => 'ԕ',
  'Ԗ' => 'ԗ',
  'Ԙ' => 'ԙ',
  'Ԛ' => 'ԛ',
  'Ԝ' => 'ԝ',
  'Ԟ' => 'ԟ',
  'Ԡ' => 'ԡ',
  'Ԣ' => 'ԣ',
  'Ԥ' => 'ԥ',
  'Ԧ' => 'ԧ',
  'Ԩ' => 'ԩ',
  'Ԫ' => 'ԫ',
  'Ԭ' => 'ԭ',
  'Ԯ' => 'ԯ',
  'Ա' => 'ա',
  'Բ' => 'բ',
  'Գ' => 'գ',
  'Դ' => 'դ',
  'Ե' => 'ե',
  'Զ' => 'զ',
  'Է' => 'է',
  'Ը' => 'ը',
  'Թ' => 'թ',
  'Ժ' => 'ժ',
  'Ի' => 'ի',
  'Լ' => 'լ',
  'Խ' => 'խ',
  'Ծ' => 'ծ',
  'Կ' => 'կ',
  'Հ' => 'հ',
  'Ձ' => 'ձ',
  'Ղ' => 'ղ',
  'Ճ' => 'ճ',
  'Մ' => 'մ',
  'Յ' => 'յ',
  'Ն' => 'ն',
  'Շ' => 'շ',
  'Ո' => 'ո',
  'Չ' => 'չ',
  'Պ' => 'պ',
  'Ջ' => 'ջ',
  'Ռ' => 'ռ',
  'Ս' => 'ս',
  'Վ' => 'վ',
  'Տ' => 'տ',
  'Ր' => 'ր',
  'Ց' => 'ց',
  'Ւ' => 'ւ',
  'Փ' => 'փ',
  'Ք' => 'ք',
  'Օ' => 'օ',
  'Ֆ' => 'ֆ',
  'Ⴀ' => 'ⴀ',
  'Ⴁ' => 'ⴁ',
  'Ⴂ' => 'ⴂ',
  'Ⴃ' => 'ⴃ',
  'Ⴄ' => 'ⴄ',
  'Ⴅ' => 'ⴅ',
  'Ⴆ' => 'ⴆ',
  'Ⴇ' => 'ⴇ',
  'Ⴈ' => 'ⴈ',
  'Ⴉ' => 'ⴉ',
  'Ⴊ' => 'ⴊ',
  'Ⴋ' => 'ⴋ',
  'Ⴌ' => 'ⴌ',
  'Ⴍ' => 'ⴍ',
  'Ⴎ' => 'ⴎ',
  'Ⴏ' => 'ⴏ',
  'Ⴐ' => 'ⴐ',
  'Ⴑ' => 'ⴑ',
  'Ⴒ' => 'ⴒ',
  'Ⴓ' => 'ⴓ',
  'Ⴔ' => 'ⴔ',
  'Ⴕ' => 'ⴕ',
  'Ⴖ' => 'ⴖ',
  'Ⴗ' => 'ⴗ',
  'Ⴘ' => 'ⴘ',
  'Ⴙ' => 'ⴙ',
  'Ⴚ' => 'ⴚ',
  'Ⴛ' => 'ⴛ',
  'Ⴜ' => 'ⴜ',
  'Ⴝ' => 'ⴝ',
  'Ⴞ' => 'ⴞ',
  'Ⴟ' => 'ⴟ',
  'Ⴠ' => 'ⴠ',
  'Ⴡ' => 'ⴡ',
  'Ⴢ' => 'ⴢ',
  'Ⴣ' => 'ⴣ',
  'Ⴤ' => 'ⴤ',
  'Ⴥ' => 'ⴥ',
  'Ⴧ' => 'ⴧ',
  'Ⴭ' => 'ⴭ',
  'Ḁ' => 'ḁ',
  'Ḃ' => 'ḃ',
  'Ḅ' => 'ḅ',
  'Ḇ' => 'ḇ',
  'Ḉ' => 'ḉ',
  'Ḋ' => 'ḋ',
  'Ḍ' => 'ḍ',
  'Ḏ' => 'ḏ',
  'Ḑ' => 'ḑ',
  'Ḓ' => 'ḓ',
  'Ḕ' => 'ḕ',
  'Ḗ' => 'ḗ',
  'Ḙ' => 'ḙ',
  'Ḛ' => 'ḛ',
  'Ḝ' => 'ḝ',
  'Ḟ' => 'ḟ',
  'Ḡ' => 'ḡ',
  'Ḣ' => 'ḣ',
  'Ḥ' => 'ḥ',
  'Ḧ' => 'ḧ',
  'Ḩ' => 'ḩ',
  'Ḫ' => 'ḫ',
  'Ḭ' => 'ḭ',
  'Ḯ' => 'ḯ',
  'Ḱ' => 'ḱ',
  'Ḳ' => 'ḳ',
  'Ḵ' => 'ḵ',
  'Ḷ' => 'ḷ',
  'Ḹ' => 'ḹ',
  'Ḻ' => 'ḻ',
  'Ḽ' => 'ḽ',
  'Ḿ' => 'ḿ',
  'Ṁ' => 'ṁ',
  'Ṃ' => 'ṃ',
  'Ṅ' => 'ṅ',
  'Ṇ' => 'ṇ',
  'Ṉ' => 'ṉ',
  'Ṋ' => 'ṋ',
  'Ṍ' => 'ṍ',
  'Ṏ' => 'ṏ',
  'Ṑ' => 'ṑ',
  'Ṓ' => 'ṓ',
  'Ṕ' => 'ṕ',
  'Ṗ' => 'ṗ',
  'Ṙ' => 'ṙ',
  'Ṛ' => 'ṛ',
  'Ṝ' => 'ṝ',
  'Ṟ' => 'ṟ',
  'Ṡ' => 'ṡ',
  'Ṣ' => 'ṣ',
  'Ṥ' => 'ṥ',
  'Ṧ' => 'ṧ',
  'Ṩ' => 'ṩ',
  'Ṫ' => 'ṫ',
  'Ṭ' => 'ṭ',
  'Ṯ' => 'ṯ',
  'Ṱ' => 'ṱ',
  'Ṳ' => 'ṳ',
  'Ṵ' => 'ṵ',
  'Ṷ' => 'ṷ',
  'Ṹ' => 'ṹ',
  'Ṻ' => 'ṻ',
  'Ṽ' => 'ṽ',
  'Ṿ' => 'ṿ',
  'Ẁ' => 'ẁ',
  'Ẃ' => 'ẃ',
  'Ẅ' => 'ẅ',
  'Ẇ' => 'ẇ',
  'Ẉ' => 'ẉ',
  'Ẋ' => 'ẋ',
  'Ẍ' => 'ẍ',
  'Ẏ' => 'ẏ',
  'Ẑ' => 'ẑ',
  'Ẓ' => 'ẓ',
  'Ẕ' => 'ẕ',
  'ẞ' => 'ß',
  'Ạ' => 'ạ',
  'Ả' => 'ả',
  'Ấ' => 'ấ',
  'Ầ' => 'ầ',
  'Ẩ' => 'ẩ',
  'Ẫ' => 'ẫ',
  'Ậ' => 'ậ',
  'Ắ' => 'ắ',
  'Ằ' => 'ằ',
  'Ẳ' => 'ẳ',
  'Ẵ' => 'ẵ',
  'Ặ' => 'ặ',
  'Ẹ' => 'ẹ',
  'Ẻ' => 'ẻ',
  'Ẽ' => 'ẽ',
  'Ế' => 'ế',
  'Ề' => 'ề',
  'Ể' => 'ể',
  'Ễ' => 'ễ',
  'Ệ' => 'ệ',
  'Ỉ' => 'ỉ',
  'Ị' => 'ị',
  'Ọ' => 'ọ',
  'Ỏ' => 'ỏ',
  'Ố' => 'ố',
  'Ồ' => 'ồ',
  'Ổ' => 'ổ',
  'Ỗ' => 'ỗ',
  'Ộ' => 'ộ',
  'Ớ' => 'ớ',
  'Ờ' => 'ờ',
  'Ở' => 'ở',
  'Ỡ' => 'ỡ',
  'Ợ' => 'ợ',
  'Ụ' => 'ụ',
  'Ủ' => 'ủ',
  'Ứ' => 'ứ',
  'Ừ' => 'ừ',
  'Ử' => 'ử',
  'Ữ' => 'ữ',
  'Ự' => 'ự',
  'Ỳ' => 'ỳ',
  'Ỵ' => 'ỵ',
  'Ỷ' => 'ỷ',
  'Ỹ' => 'ỹ',
  'Ỻ' => 'ỻ',
  'Ỽ' => 'ỽ',
  'Ỿ' => 'ỿ',
  'Ἀ' => 'ἀ',
  'Ἁ' => 'ἁ',
  'Ἂ' => 'ἂ',
  'Ἃ' => 'ἃ',
  'Ἄ' => 'ἄ',
  'Ἅ' => 'ἅ',
  'Ἆ' => 'ἆ',
  'Ἇ' => 'ἇ',
  'Ἐ' => 'ἐ',
  'Ἑ' => 'ἑ',
  'Ἒ' => 'ἒ',
  'Ἓ' => 'ἓ',
  'Ἔ' => 'ἔ',
  'Ἕ' => 'ἕ',
  'Ἠ' => 'ἠ',
  'Ἡ' => 'ἡ',
  'Ἢ' => 'ἢ',
  'Ἣ' => 'ἣ',
  'Ἤ' => 'ἤ',
  'Ἥ' => 'ἥ',
  'Ἦ' => 'ἦ',
  'Ἧ' => 'ἧ',
  'Ἰ' => 'ἰ',
  'Ἱ' => 'ἱ',
  'Ἲ' => 'ἲ',
  'Ἳ' => 'ἳ',
  'Ἴ' => 'ἴ',
  'Ἵ' => 'ἵ',
  'Ἶ' => 'ἶ',
  'Ἷ' => 'ἷ',
  'Ὀ' => 'ὀ',
  'Ὁ' => 'ὁ',
  'Ὂ' => 'ὂ',
  'Ὃ' => 'ὃ',
  'Ὄ' => 'ὄ',
  'Ὅ' => 'ὅ',
  'Ὑ' => 'ὑ',
  'Ὓ' => 'ὓ',
  'Ὕ' => 'ὕ',
  'Ὗ' => 'ὗ',
  'Ὠ' => 'ὠ',
  'Ὡ' => 'ὡ',
  'Ὢ' => 'ὢ',
  'Ὣ' => 'ὣ',
  'Ὤ' => 'ὤ',
  'Ὥ' => 'ὥ',
  'Ὦ' => 'ὦ',
  'Ὧ' => 'ὧ',
  'ᾈ' => 'ᾀ',
  'ᾉ' => 'ᾁ',
  'ᾊ' => 'ᾂ',
  'ᾋ' => 'ᾃ',
  'ᾌ' => 'ᾄ',
  'ᾍ' => 'ᾅ',
  'ᾎ' => 'ᾆ',
  'ᾏ' => 'ᾇ',
  'ᾘ' => 'ᾐ',
  'ᾙ' => 'ᾑ',
  'ᾚ' => 'ᾒ',
  'ᾛ' => 'ᾓ',
  'ᾜ' => 'ᾔ',
  'ᾝ' => 'ᾕ',
  'ᾞ' => 'ᾖ',
  'ᾟ' => 'ᾗ',
  'ᾨ' => 'ᾠ',
  'ᾩ' => 'ᾡ',
  'ᾪ' => 'ᾢ',
  'ᾫ' => 'ᾣ',
  'ᾬ' => 'ᾤ',
  'ᾭ' => 'ᾥ',
  'ᾮ' => 'ᾦ',
  'ᾯ' => 'ᾧ',
  'Ᾰ' => 'ᾰ',
  'Ᾱ' => 'ᾱ',
  'Ὰ' => 'ὰ',
  'Ά' => 'ά',
  'ᾼ' => 'ᾳ',
  'Ὲ' => 'ὲ',
  'Έ' => 'έ',
  'Ὴ' => 'ὴ',
  'Ή' => 'ή',
  'ῌ' => 'ῃ',
  'Ῐ' => 'ῐ',
  'Ῑ' => 'ῑ',
  'Ὶ' => 'ὶ',
  'Ί' => 'ί',
  'Ῠ' => 'ῠ',
  'Ῡ' => 'ῡ',
  'Ὺ' => 'ὺ',
  'Ύ' => 'ύ',
  'Ῥ' => 'ῥ',
  'Ὸ' => 'ὸ',
  'Ό' => 'ό',
  'Ὼ' => 'ὼ',
  'Ώ' => 'ώ',
  'ῼ' => 'ῳ',
  'Ω' => 'ω',
  'K' => 'k',
  'Å' => 'å',
  'Ⅎ' => 'ⅎ',
  'Ⅰ' => 'ⅰ',
  'Ⅱ' => 'ⅱ',
  'Ⅲ' => 'ⅲ',
  'Ⅳ' => 'ⅳ',
  'Ⅴ' => 'ⅴ',
  'Ⅵ' => 'ⅵ',
  'Ⅶ' => 'ⅶ',
  'Ⅷ' => 'ⅷ',
  'Ⅸ' => 'ⅸ',
  'Ⅹ' => 'ⅹ',
  'Ⅺ' => 'ⅺ',
  'Ⅻ' => 'ⅻ',
  'Ⅼ' => 'ⅼ',
  'Ⅽ' => 'ⅽ',
  'Ⅾ' => 'ⅾ',
  'Ⅿ' => 'ⅿ',
  'Ↄ' => 'ↄ',
  'Ⓐ' => 'ⓐ',
  'Ⓑ' => 'ⓑ',
  'Ⓒ' => 'ⓒ',
  'Ⓓ' => 'ⓓ',
  'Ⓔ' => 'ⓔ',
  'Ⓕ' => 'ⓕ',
  'Ⓖ' => 'ⓖ',
  'Ⓗ' => 'ⓗ',
  'Ⓘ' => 'ⓘ',
  'Ⓙ' => 'ⓙ',
  'Ⓚ' => 'ⓚ',
  'Ⓛ' => 'ⓛ',
  'Ⓜ' => 'ⓜ',
  'Ⓝ' => 'ⓝ',
  'Ⓞ' => 'ⓞ',
  'Ⓟ' => 'ⓟ',
  'Ⓠ' => 'ⓠ',
  'Ⓡ' => 'ⓡ',
  'Ⓢ' => 'ⓢ',
  'Ⓣ' => 'ⓣ',
  'Ⓤ' => 'ⓤ',
  'Ⓥ' => 'ⓥ',
  'Ⓦ' => 'ⓦ',
  'Ⓧ' => 'ⓧ',
  'Ⓨ' => 'ⓨ',
  'Ⓩ' => 'ⓩ',
  'Ⰰ' => 'ⰰ',
  'Ⰱ' => 'ⰱ',
  'Ⰲ' => 'ⰲ',
  'Ⰳ' => 'ⰳ',
  'Ⰴ' => 'ⰴ',
  'Ⰵ' => 'ⰵ',
  'Ⰶ' => 'ⰶ',
  'Ⰷ' => 'ⰷ',
  'Ⰸ' => 'ⰸ',
  'Ⰹ' => 'ⰹ',
  'Ⰺ' => 'ⰺ',
  'Ⰻ' => 'ⰻ',
  'Ⰼ' => 'ⰼ',
  'Ⰽ' => 'ⰽ',
  'Ⰾ' => 'ⰾ',
  'Ⰿ' => 'ⰿ',
  'Ⱀ' => 'ⱀ',
  'Ⱁ' => 'ⱁ',
  'Ⱂ' => 'ⱂ',
  'Ⱃ' => 'ⱃ',
  'Ⱄ' => 'ⱄ',
  'Ⱅ' => 'ⱅ',
  'Ⱆ' => 'ⱆ',
  'Ⱇ' => 'ⱇ',
  'Ⱈ' => 'ⱈ',
  'Ⱉ' => 'ⱉ',
  'Ⱊ' => 'ⱊ',
  'Ⱋ' => 'ⱋ',
  'Ⱌ' => 'ⱌ',
  'Ⱍ' => 'ⱍ',
  'Ⱎ' => 'ⱎ',
  'Ⱏ' => 'ⱏ',
  'Ⱐ' => 'ⱐ',
  'Ⱑ' => 'ⱑ',
  'Ⱒ' => 'ⱒ',
  'Ⱓ' => 'ⱓ',
  'Ⱔ' => 'ⱔ',
  'Ⱕ' => 'ⱕ',
  'Ⱖ' => 'ⱖ',
  'Ⱗ' => 'ⱗ',
  'Ⱘ' => 'ⱘ',
  'Ⱙ' => 'ⱙ',
  'Ⱚ' => 'ⱚ',
  'Ⱛ' => 'ⱛ',
  'Ⱜ' => 'ⱜ',
  'Ⱝ' => 'ⱝ',
  'Ⱞ' => 'ⱞ',
  'Ⱡ' => 'ⱡ',
  'Ɫ' => 'ɫ',
  'Ᵽ' => 'ᵽ',
  'Ɽ' => 'ɽ',
  'Ⱨ' => 'ⱨ',
  'Ⱪ' => 'ⱪ',
  'Ⱬ' => 'ⱬ',
  'Ɑ' => 'ɑ',
  'Ɱ' => 'ɱ',
  'Ɐ' => 'ɐ',
  'Ɒ' => 'ɒ',
  'Ⱳ' => 'ⱳ',
  'Ⱶ' => 'ⱶ',
  'Ȿ' => 'ȿ',
  'Ɀ' => 'ɀ',
  'Ⲁ' => 'ⲁ',
  'Ⲃ' => 'ⲃ',
  'Ⲅ' => 'ⲅ',
  'Ⲇ' => 'ⲇ',
  'Ⲉ' => 'ⲉ',
  'Ⲋ' => 'ⲋ',
  'Ⲍ' => 'ⲍ',
  'Ⲏ' => 'ⲏ',
  'Ⲑ' => 'ⲑ',
  'Ⲓ' => 'ⲓ',
  'Ⲕ' => 'ⲕ',
  'Ⲗ' => 'ⲗ',
  'Ⲙ' => 'ⲙ',
  'Ⲛ' => 'ⲛ',
  'Ⲝ' => 'ⲝ',
  'Ⲟ' => 'ⲟ',
  'Ⲡ' => 'ⲡ',
  'Ⲣ' => 'ⲣ',
  'Ⲥ' => 'ⲥ',
  'Ⲧ' => 'ⲧ',
  'Ⲩ' => 'ⲩ',
  'Ⲫ' => 'ⲫ',
  'Ⲭ' => 'ⲭ',
  'Ⲯ' => 'ⲯ',
  'Ⲱ' => 'ⲱ',
  'Ⲳ' => 'ⲳ',
  'Ⲵ' => 'ⲵ',
  'Ⲷ' => 'ⲷ',
  'Ⲹ' => 'ⲹ',
  'Ⲻ' => 'ⲻ',
  'Ⲽ' => 'ⲽ',
  'Ⲿ' => 'ⲿ',
  'Ⳁ' => 'ⳁ',
  'Ⳃ' => 'ⳃ',
  'Ⳅ' => 'ⳅ',
  'Ⳇ' => 'ⳇ',
  'Ⳉ' => 'ⳉ',
  'Ⳋ' => 'ⳋ',
  'Ⳍ' => 'ⳍ',
  'Ⳏ' => 'ⳏ',
  'Ⳑ' => 'ⳑ',
  'Ⳓ' => 'ⳓ',
  'Ⳕ' => 'ⳕ',
  'Ⳗ' => 'ⳗ',
  'Ⳙ' => 'ⳙ',
  'Ⳛ' => 'ⳛ',
  'Ⳝ' => 'ⳝ',
  'Ⳟ' => 'ⳟ',
  'Ⳡ' => 'ⳡ',
  'Ⳣ' => 'ⳣ',
  'Ⳬ' => 'ⳬ',
  'Ⳮ' => 'ⳮ',
  'Ⳳ' => 'ⳳ',
  'Ꙁ' => 'ꙁ',
  'Ꙃ' => 'ꙃ',
  'Ꙅ' => 'ꙅ',
  'Ꙇ' => 'ꙇ',
  'Ꙉ' => 'ꙉ',
  'Ꙋ' => 'ꙋ',
  'Ꙍ' => 'ꙍ',
  'Ꙏ' => 'ꙏ',
  'Ꙑ' => 'ꙑ',
  'Ꙓ' => 'ꙓ',
  'Ꙕ' => 'ꙕ',
  'Ꙗ' => 'ꙗ',
  'Ꙙ' => 'ꙙ',
  'Ꙛ' => 'ꙛ',
  'Ꙝ' => 'ꙝ',
  'Ꙟ' => 'ꙟ',
  'Ꙡ' => 'ꙡ',
  'Ꙣ' => 'ꙣ',
  'Ꙥ' => 'ꙥ',
  'Ꙧ' => 'ꙧ',
  'Ꙩ' => 'ꙩ',
  'Ꙫ' => 'ꙫ',
  'Ꙭ' => 'ꙭ',
  'Ꚁ' => 'ꚁ',
  'Ꚃ' => 'ꚃ',
  'Ꚅ' => 'ꚅ',
  'Ꚇ' => 'ꚇ',
  'Ꚉ' => 'ꚉ',
  'Ꚋ' => 'ꚋ',
  'Ꚍ' => 'ꚍ',
  'Ꚏ' => 'ꚏ',
  'Ꚑ' => 'ꚑ',
  'Ꚓ' => 'ꚓ',
  'Ꚕ' => 'ꚕ',
  'Ꚗ' => 'ꚗ',
  'Ꚙ' => 'ꚙ',
  'Ꚛ' => 'ꚛ',
  'Ꜣ' => 'ꜣ',
  'Ꜥ' => 'ꜥ',
  'Ꜧ' => 'ꜧ',
  'Ꜩ' => 'ꜩ',
  'Ꜫ' => 'ꜫ',
  'Ꜭ' => 'ꜭ',
  'Ꜯ' => 'ꜯ',
  'Ꜳ' => 'ꜳ',
  'Ꜵ' => 'ꜵ',
  'Ꜷ' => 'ꜷ',
  'Ꜹ' => 'ꜹ',
  'Ꜻ' => 'ꜻ',
  'Ꜽ' => 'ꜽ',
  'Ꜿ' => 'ꜿ',
  'Ꝁ' => 'ꝁ',
  'Ꝃ' => 'ꝃ',
  'Ꝅ' => 'ꝅ',
  'Ꝇ' => 'ꝇ',
  'Ꝉ' => 'ꝉ',
  'Ꝋ' => 'ꝋ',
  'Ꝍ' => 'ꝍ',
  'Ꝏ' => 'ꝏ',
  'Ꝑ' => 'ꝑ',
  'Ꝓ' => 'ꝓ',
  'Ꝕ' => 'ꝕ',
  'Ꝗ' => 'ꝗ',
  'Ꝙ' => 'ꝙ',
  'Ꝛ' => 'ꝛ',
  'Ꝝ' => 'ꝝ',
  'Ꝟ' => 'ꝟ',
  'Ꝡ' => 'ꝡ',
  'Ꝣ' => 'ꝣ',
  'Ꝥ' => 'ꝥ',
  'Ꝧ' => 'ꝧ',
  'Ꝩ' => 'ꝩ',
  'Ꝫ' => 'ꝫ',
  'Ꝭ' => 'ꝭ',
  'Ꝯ' => 'ꝯ',
  'Ꝺ' => 'ꝺ',
  'Ꝼ' => 'ꝼ',
  'Ᵹ' => 'ᵹ',
  'Ꝿ' => 'ꝿ',
  'Ꞁ' => 'ꞁ',
  'Ꞃ' => 'ꞃ',
  'Ꞅ' => 'ꞅ',
  'Ꞇ' => 'ꞇ',
  'Ꞌ' => 'ꞌ',
  'Ɥ' => 'ɥ',
  'Ꞑ' => 'ꞑ',
  'Ꞓ' => 'ꞓ',
  'Ꞗ' => 'ꞗ',
  'Ꞙ' => 'ꞙ',
  'Ꞛ' => 'ꞛ',
  'Ꞝ' => 'ꞝ',
  'Ꞟ' => 'ꞟ',
  'Ꞡ' => 'ꞡ',
  'Ꞣ' => 'ꞣ',
  'Ꞥ' => 'ꞥ',
  'Ꞧ' => 'ꞧ',
  'Ꞩ' => 'ꞩ',
  'Ɦ' => 'ɦ',
  'Ɜ' => 'ɜ',
  'Ɡ' => 'ɡ',
  'Ɬ' => 'ɬ',
  'Ʞ' => 'ʞ',
  'Ʇ' => 'ʇ',
  'A' => 'a',
  'B' => 'b',
  'C' => 'c',
  'D' => 'd',
  'E' => 'e',
  'F' => 'f',
  'G' => 'g',
  'H' => 'h',
  'I' => 'i',
  'J' => 'j',
  'K' => 'k',
  'L' => 'l',
  'M' => 'm',
  'N' => 'n',
  'O' => 'o',
  'P' => 'p',
  'Q' => 'q',
  'R' => 'r',
  'S' => 's',
  'T' => 't',
  'U' => 'u',
  'V' => 'v',
  'W' => 'w',
  'X' => 'x',
  'Y' => 'y',
  'Z' => 'z',
  '𐐀' => '𐐨',
  '𐐁' => '𐐩',
  '𐐂' => '𐐪',
  '𐐃' => '𐐫',
  '𐐄' => '𐐬',
  '𐐅' => '𐐭',
  '𐐆' => '𐐮',
  '𐐇' => '𐐯',
  '𐐈' => '𐐰',
  '𐐉' => '𐐱',
  '𐐊' => '𐐲',
  '𐐋' => '𐐳',
  '𐐌' => '𐐴',
  '𐐍' => '𐐵',
  '𐐎' => '𐐶',
  '𐐏' => '𐐷',
  '𐐐' => '𐐸',
  '𐐑' => '𐐹',
  '𐐒' => '𐐺',
  '𐐓' => '𐐻',
  '𐐔' => '𐐼',
  '𐐕' => '𐐽',
  '𐐖' => '𐐾',
  '𐐗' => '𐐿',
  '𐐘' => '𐑀',
  '𐐙' => '𐑁',
  '𐐚' => '𐑂',
  '𐐛' => '𐑃',
  '𐐜' => '𐑄',
  '𐐝' => '𐑅',
  '𐐞' => '𐑆',
  '𐐟' => '𐑇',
  '𐐠' => '𐑈',
  '𐐡' => '𐑉',
  '𐐢' => '𐑊',
  '𐐣' => '𐑋',
  '𐐤' => '𐑌',
  '𐐥' => '𐑍',
  '𐐦' => '𐑎',
  '𐐧' => '𐑏',
  '𑢠' => '𑣀',
  '𑢡' => '𑣁',
  '𑢢' => '𑣂',
  '𑢣' => '𑣃',
  '𑢤' => '𑣄',
  '𑢥' => '𑣅',
  '𑢦' => '𑣆',
  '𑢧' => '𑣇',
  '𑢨' => '𑣈',
  '𑢩' => '𑣉',
  '𑢪' => '𑣊',
  '𑢫' => '𑣋',
  '𑢬' => '𑣌',
  '𑢭' => '𑣍',
  '𑢮' => '𑣎',
  '𑢯' => '𑣏',
  '𑢰' => '𑣐',
  '𑢱' => '𑣑',
  '𑢲' => '𑣒',
  '𑢳' => '𑣓',
  '𑢴' => '𑣔',
  '𑢵' => '𑣕',
  '𑢶' => '𑣖',
  '𑢷' => '𑣗',
  '𑢸' => '𑣘',
  '𑢹' => '𑣙',
  '𑢺' => '𑣚',
  '𑢻' => '𑣛',
  '𑢼' => '𑣜',
  '𑢽' => '𑣝',
  '𑢾' => '𑣞',
  '𑢿' => '𑣟',
);

$result =& $data;
unset($data);

return $result;
<?php

static $data = array (
  'a' => 'A',
  'b' => 'B',
  'c' => 'C',
  'd' => 'D',
  'e' => 'E',
  'f' => 'F',
  'g' => 'G',
  'h' => 'H',
  'i' => 'I',
  'j' => 'J',
  'k' => 'K',
  'l' => 'L',
  'm' => 'M',
  'n' => 'N',
  'o' => 'O',
  'p' => 'P',
  'q' => 'Q',
  'r' => 'R',
  's' => 'S',
  't' => 'T',
  'u' => 'U',
  'v' => 'V',
  'w' => 'W',
  'x' => 'X',
  'y' => 'Y',
  'z' => 'Z',
  'µ' => 'Μ',
  'à' => 'À',
  'á' => 'Á',
  'â' => 'Â',
  'ã' => 'Ã',
  'ä' => 'Ä',
  'å' => 'Å',
  'æ' => 'Æ',
  'ç' => 'Ç',
  'è' => 'È',
  'é' => 'É',
  'ê' => 'Ê',
  'ë' => 'Ë',
  'ì' => 'Ì',
  'í' => 'Í',
  'î' => 'Î',
  'ï' => 'Ï',
  'ð' => 'Ð',
  'ñ' => 'Ñ',
  'ò' => 'Ò',
  'ó' => 'Ó',
  'ô' => 'Ô',
  'õ' => 'Õ',
  'ö' => 'Ö',
  'ø' => 'Ø',
  'ù' => 'Ù',
  'ú' => 'Ú',
  'û' => 'Û',
  'ü' => 'Ü',
  'ý' => 'Ý',
  'þ' => 'Þ',
  'ÿ' => 'Ÿ',
  'ā' => 'Ā',
  'ă' => 'Ă',
  'ą' => 'Ą',
  'ć' => 'Ć',
  'ĉ' => 'Ĉ',
  'ċ' => 'Ċ',
  'č' => 'Č',
  'ď' => 'Ď',
  'đ' => 'Đ',
  'ē' => 'Ē',
  'ĕ' => 'Ĕ',
  'ė' => 'Ė',
  'ę' => 'Ę',
  'ě' => 'Ě',
  'ĝ' => 'Ĝ',
  'ğ' => 'Ğ',
  'ġ' => 'Ġ',
  'ģ' => 'Ģ',
  'ĥ' => 'Ĥ',
  'ħ' => 'Ħ',
  'ĩ' => 'Ĩ',
  'ī' => 'Ī',
  'ĭ' => 'Ĭ',
  'į' => 'Į',
  'ı' => 'I',
  'ij' => 'IJ',
  'ĵ' => 'Ĵ',
  'ķ' => 'Ķ',
  'ĺ' => 'Ĺ',
  'ļ' => 'Ļ',
  'ľ' => 'Ľ',
  'ŀ' => 'Ŀ',
  'ł' => 'Ł',
  'ń' => 'Ń',
  'ņ' => 'Ņ',
  'ň' => 'Ň',
  'ŋ' => 'Ŋ',
  'ō' => 'Ō',
  'ŏ' => 'Ŏ',
  'ő' => 'Ő',
  'œ' => 'Œ',
  'ŕ' => 'Ŕ',
  'ŗ' => 'Ŗ',
  'ř' => 'Ř',
  'ś' => 'Ś',
  'ŝ' => 'Ŝ',
  'ş' => 'Ş',
  'š' => 'Š',
  'ţ' => 'Ţ',
  'ť' => 'Ť',
  'ŧ' => 'Ŧ',
  'ũ' => 'Ũ',
  'ū' => 'Ū',
  'ŭ' => 'Ŭ',
  'ů' => 'Ů',
  'ű' => 'Ű',
  'ų' => 'Ų',
  'ŵ' => 'Ŵ',
  'ŷ' => 'Ŷ',
  'ź' => 'Ź',
  'ż' => 'Ż',
  'ž' => 'Ž',
  'ſ' => 'S',
  'ƀ' => 'Ƀ',
  'ƃ' => 'Ƃ',
  'ƅ' => 'Ƅ',
  'ƈ' => 'Ƈ',
  'ƌ' => 'Ƌ',
  'ƒ' => 'Ƒ',
  'ƕ' => 'Ƕ',
  'ƙ' => 'Ƙ',
  'ƚ' => 'Ƚ',
  'ƞ' => 'Ƞ',
  'ơ' => 'Ơ',
  'ƣ' => 'Ƣ',
  'ƥ' => 'Ƥ',
  'ƨ' => 'Ƨ',
  'ƭ' => 'Ƭ',
  'ư' => 'Ư',
  'ƴ' => 'Ƴ',
  'ƶ' => 'Ƶ',
  'ƹ' => 'Ƹ',
  'ƽ' => 'Ƽ',
  'ƿ' => 'Ƿ',
  'Dž' => 'DŽ',
  'dž' => 'DŽ',
  'Lj' => 'LJ',
  'lj' => 'LJ',
  'Nj' => 'NJ',
  'nj' => 'NJ',
  'ǎ' => 'Ǎ',
  'ǐ' => 'Ǐ',
  'ǒ' => 'Ǒ',
  'ǔ' => 'Ǔ',
  'ǖ' => 'Ǖ',
  'ǘ' => 'Ǘ',
  'ǚ' => 'Ǚ',
  'ǜ' => 'Ǜ',
  'ǝ' => 'Ǝ',
  'ǟ' => 'Ǟ',
  'ǡ' => 'Ǡ',
  'ǣ' => 'Ǣ',
  'ǥ' => 'Ǥ',
  'ǧ' => 'Ǧ',
  'ǩ' => 'Ǩ',
  'ǫ' => 'Ǫ',
  'ǭ' => 'Ǭ',
  'ǯ' => 'Ǯ',
  'Dz' => 'DZ',
  'dz' => 'DZ',
  'ǵ' => 'Ǵ',
  'ǹ' => 'Ǹ',
  'ǻ' => 'Ǻ',
  'ǽ' => 'Ǽ',
  'ǿ' => 'Ǿ',
  'ȁ' => 'Ȁ',
  'ȃ' => 'Ȃ',
  'ȅ' => 'Ȅ',
  'ȇ' => 'Ȇ',
  'ȉ' => 'Ȉ',
  'ȋ' => 'Ȋ',
  'ȍ' => 'Ȍ',
  'ȏ' => 'Ȏ',
  'ȑ' => 'Ȑ',
  'ȓ' => 'Ȓ',
  'ȕ' => 'Ȕ',
  'ȗ' => 'Ȗ',
  'ș' => 'Ș',
  'ț' => 'Ț',
  'ȝ' => 'Ȝ',
  'ȟ' => 'Ȟ',
  'ȣ' => 'Ȣ',
  'ȥ' => 'Ȥ',
  'ȧ' => 'Ȧ',
  'ȩ' => 'Ȩ',
  'ȫ' => 'Ȫ',
  'ȭ' => 'Ȭ',
  'ȯ' => 'Ȯ',
  'ȱ' => 'Ȱ',
  'ȳ' => 'Ȳ',
  'ȼ' => 'Ȼ',
  'ȿ' => 'Ȿ',
  'ɀ' => 'Ɀ',
  'ɂ' => 'Ɂ',
  'ɇ' => 'Ɇ',
  'ɉ' => 'Ɉ',
  'ɋ' => 'Ɋ',
  'ɍ' => 'Ɍ',
  'ɏ' => 'Ɏ',
  'ɐ' => 'Ɐ',
  'ɑ' => 'Ɑ',
  'ɒ' => 'Ɒ',
  'ɓ' => 'Ɓ',
  'ɔ' => 'Ɔ',
  'ɖ' => 'Ɖ',
  'ɗ' => 'Ɗ',
  'ə' => 'Ə',
  'ɛ' => 'Ɛ',
  'ɜ' => 'Ɜ',
  'ɠ' => 'Ɠ',
  'ɡ' => 'Ɡ',
  'ɣ' => 'Ɣ',
  'ɥ' => 'Ɥ',
  'ɦ' => 'Ɦ',
  'ɨ' => 'Ɨ',
  'ɩ' => 'Ɩ',
  'ɫ' => 'Ɫ',
  'ɬ' => 'Ɬ',
  'ɯ' => 'Ɯ',
  'ɱ' => 'Ɱ',
  'ɲ' => 'Ɲ',
  'ɵ' => 'Ɵ',
  'ɽ' => 'Ɽ',
  'ʀ' => 'Ʀ',
  'ʃ' => 'Ʃ',
  'ʇ' => 'Ʇ',
  'ʈ' => 'Ʈ',
  'ʉ' => 'Ʉ',
  'ʊ' => 'Ʊ',
  'ʋ' => 'Ʋ',
  'ʌ' => 'Ʌ',
  'ʒ' => 'Ʒ',
  'ʞ' => 'Ʞ',
  'ͅ' => 'Ι',
  'ͱ' => 'Ͱ',
  'ͳ' => 'Ͳ',
  'ͷ' => 'Ͷ',
  'ͻ' => 'Ͻ',
  'ͼ' => 'Ͼ',
  'ͽ' => 'Ͽ',
  'ά' => 'Ά',
  'έ' => 'Έ',
  'ή' => 'Ή',
  'ί' => 'Ί',
  'α' => 'Α',
  'β' => 'Β',
  'γ' => 'Γ',
  'δ' => 'Δ',
  'ε' => 'Ε',
  'ζ' => 'Ζ',
  'η' => 'Η',
  'θ' => 'Θ',
  'ι' => 'Ι',
  'κ' => 'Κ',
  'λ' => 'Λ',
  'μ' => 'Μ',
  'ν' => 'Ν',
  'ξ' => 'Ξ',
  'ο' => 'Ο',
  'π' => 'Π',
  'ρ' => 'Ρ',
  'ς' => 'Σ',
  'σ' => 'Σ',
  'τ' => 'Τ',
  'υ' => 'Υ',
  'φ' => 'Φ',
  'χ' => 'Χ',
  'ψ' => 'Ψ',
  'ω' => 'Ω',
  'ϊ' => 'Ϊ',
  'ϋ' => 'Ϋ',
  'ό' => 'Ό',
  'ύ' => 'Ύ',
  'ώ' => 'Ώ',
  'ϐ' => 'Β',
  'ϑ' => 'Θ',
  'ϕ' => 'Φ',
  'ϖ' => 'Π',
  'ϗ' => 'Ϗ',
  'ϙ' => 'Ϙ',
  'ϛ' => 'Ϛ',
  'ϝ' => 'Ϝ',
  'ϟ' => 'Ϟ',
  'ϡ' => 'Ϡ',
  'ϣ' => 'Ϣ',
  'ϥ' => 'Ϥ',
  'ϧ' => 'Ϧ',
  'ϩ' => 'Ϩ',
  'ϫ' => 'Ϫ',
  'ϭ' => 'Ϭ',
  'ϯ' => 'Ϯ',
  'ϰ' => 'Κ',
  'ϱ' => 'Ρ',
  'ϲ' => 'Ϲ',
  'ϳ' => 'Ϳ',
  'ϵ' => 'Ε',
  'ϸ' => 'Ϸ',
  'ϻ' => 'Ϻ',
  'а' => 'А',
  'б' => 'Б',
  'в' => 'В',
  'г' => 'Г',
  'д' => 'Д',
  'е' => 'Е',
  'ж' => 'Ж',
  'з' => 'З',
  'и' => 'И',
  'й' => 'Й',
  'к' => 'К',
  'л' => 'Л',
  'м' => 'М',
  'н' => 'Н',
  'о' => 'О',
  'п' => 'П',
  'р' => 'Р',
  'с' => 'С',
  'т' => 'Т',
  'у' => 'У',
  'ф' => 'Ф',
  'х' => 'Х',
  'ц' => 'Ц',
  'ч' => 'Ч',
  'ш' => 'Ш',
  'щ' => 'Щ',
  'ъ' => 'Ъ',
  'ы' => 'Ы',
  'ь' => 'Ь',
  'э' => 'Э',
  'ю' => 'Ю',
  'я' => 'Я',
  'ѐ' => 'Ѐ',
  'ё' => 'Ё',
  'ђ' => 'Ђ',
  'ѓ' => 'Ѓ',
  'є' => 'Є',
  'ѕ' => 'Ѕ',
  'і' => 'І',
  'ї' => 'Ї',
  'ј' => 'Ј',
  'љ' => 'Љ',
  'њ' => 'Њ',
  'ћ' => 'Ћ',
  'ќ' => 'Ќ',
  'ѝ' => 'Ѝ',
  'ў' => 'Ў',
  'џ' => 'Џ',
  'ѡ' => 'Ѡ',
  'ѣ' => 'Ѣ',
  'ѥ' => 'Ѥ',
  'ѧ' => 'Ѧ',
  'ѩ' => 'Ѩ',
  'ѫ' => 'Ѫ',
  'ѭ' => 'Ѭ',
  'ѯ' => 'Ѯ',
  'ѱ' => 'Ѱ',
  'ѳ' => 'Ѳ',
  'ѵ' => 'Ѵ',
  'ѷ' => 'Ѷ',
  'ѹ' => 'Ѹ',
  'ѻ' => 'Ѻ',
  'ѽ' => 'Ѽ',
  'ѿ' => 'Ѿ',
  'ҁ' => 'Ҁ',
  'ҋ' => 'Ҋ',
  'ҍ' => 'Ҍ',
  'ҏ' => 'Ҏ',
  'ґ' => 'Ґ',
  'ғ' => 'Ғ',
  'ҕ' => 'Ҕ',
  'җ' => 'Җ',
  'ҙ' => 'Ҙ',
  'қ' => 'Қ',
  'ҝ' => 'Ҝ',
  'ҟ' => 'Ҟ',
  'ҡ' => 'Ҡ',
  'ң' => 'Ң',
  'ҥ' => 'Ҥ',
  'ҧ' => 'Ҧ',
  'ҩ' => 'Ҩ',
  'ҫ' => 'Ҫ',
  'ҭ' => 'Ҭ',
  'ү' => 'Ү',
  'ұ' => 'Ұ',
  'ҳ' => 'Ҳ',
  'ҵ' => 'Ҵ',
  'ҷ' => 'Ҷ',
  'ҹ' => 'Ҹ',
  'һ' => 'Һ',
  'ҽ' => 'Ҽ',
  'ҿ' => 'Ҿ',
  'ӂ' => 'Ӂ',
  'ӄ' => 'Ӄ',
  'ӆ' => 'Ӆ',
  'ӈ' => 'Ӈ',
  'ӊ' => 'Ӊ',
  'ӌ' => 'Ӌ',
  'ӎ' => 'Ӎ',
  'ӏ' => 'Ӏ',
  'ӑ' => 'Ӑ',
  'ӓ' => 'Ӓ',
  'ӕ' => 'Ӕ',
  'ӗ' => 'Ӗ',
  'ә' => 'Ә',
  'ӛ' => 'Ӛ',
  'ӝ' => 'Ӝ',
  'ӟ' => 'Ӟ',
  'ӡ' => 'Ӡ',
  'ӣ' => 'Ӣ',
  'ӥ' => 'Ӥ',
  'ӧ' => 'Ӧ',
  'ө' => 'Ө',
  'ӫ' => 'Ӫ',
  'ӭ' => 'Ӭ',
  'ӯ' => 'Ӯ',
  'ӱ' => 'Ӱ',
  'ӳ' => 'Ӳ',
  'ӵ' => 'Ӵ',
  'ӷ' => 'Ӷ',
  'ӹ' => 'Ӹ',
  'ӻ' => 'Ӻ',
  'ӽ' => 'Ӽ',
  'ӿ' => 'Ӿ',
  'ԁ' => 'Ԁ',
  'ԃ' => 'Ԃ',
  'ԅ' => 'Ԅ',
  'ԇ' => 'Ԇ',
  'ԉ' => 'Ԉ',
  'ԋ' => 'Ԋ',
  'ԍ' => 'Ԍ',
  'ԏ' => 'Ԏ',
  'ԑ' => 'Ԑ',
  'ԓ' => 'Ԓ',
  'ԕ' => 'Ԕ',
  'ԗ' => 'Ԗ',
  'ԙ' => 'Ԙ',
  'ԛ' => 'Ԛ',
  'ԝ' => 'Ԝ',
  'ԟ' => 'Ԟ',
  'ԡ' => 'Ԡ',
  'ԣ' => 'Ԣ',
  'ԥ' => 'Ԥ',
  'ԧ' => 'Ԧ',
  'ԩ' => 'Ԩ',
  'ԫ' => 'Ԫ',
  'ԭ' => 'Ԭ',
  'ԯ' => 'Ԯ',
  'ա' => 'Ա',
  'բ' => 'Բ',
  'գ' => 'Գ',
  'դ' => 'Դ',
  'ե' => 'Ե',
  'զ' => 'Զ',
  'է' => 'Է',
  'ը' => 'Ը',
  'թ' => 'Թ',
  'ժ' => 'Ժ',
  'ի' => 'Ի',
  'լ' => 'Լ',
  'խ' => 'Խ',
  'ծ' => 'Ծ',
  'կ' => 'Կ',
  'հ' => 'Հ',
  'ձ' => 'Ձ',
  'ղ' => 'Ղ',
  'ճ' => 'Ճ',
  'մ' => 'Մ',
  'յ' => 'Յ',
  'ն' => 'Ն',
  'շ' => 'Շ',
  'ո' => 'Ո',
  'չ' => 'Չ',
  'պ' => 'Պ',
  'ջ' => 'Ջ',
  'ռ' => 'Ռ',
  'ս' => 'Ս',
  'վ' => 'Վ',
  'տ' => 'Տ',
  'ր' => 'Ր',
  'ց' => 'Ց',
  'ւ' => 'Ւ',
  'փ' => 'Փ',
  'ք' => 'Ք',
  'օ' => 'Օ',
  'ֆ' => 'Ֆ',
  'ᵹ' => 'Ᵹ',
  'ᵽ' => 'Ᵽ',
  'ḁ' => 'Ḁ',
  'ḃ' => 'Ḃ',
  'ḅ' => 'Ḅ',
  'ḇ' => 'Ḇ',
  'ḉ' => 'Ḉ',
  'ḋ' => 'Ḋ',
  'ḍ' => 'Ḍ',
  'ḏ' => 'Ḏ',
  'ḑ' => 'Ḑ',
  'ḓ' => 'Ḓ',
  'ḕ' => 'Ḕ',
  'ḗ' => 'Ḗ',
  'ḙ' => 'Ḙ',
  'ḛ' => 'Ḛ',
  'ḝ' => 'Ḝ',
  'ḟ' => 'Ḟ',
  'ḡ' => 'Ḡ',
  'ḣ' => 'Ḣ',
  'ḥ' => 'Ḥ',
  'ḧ' => 'Ḧ',
  'ḩ' => 'Ḩ',
  'ḫ' => 'Ḫ',
  'ḭ' => 'Ḭ',
  'ḯ' => 'Ḯ',
  'ḱ' => 'Ḱ',
  'ḳ' => 'Ḳ',
  'ḵ' => 'Ḵ',
  'ḷ' => 'Ḷ',
  'ḹ' => 'Ḹ',
  'ḻ' => 'Ḻ',
  'ḽ' => 'Ḽ',
  'ḿ' => 'Ḿ',
  'ṁ' => 'Ṁ',
  'ṃ' => 'Ṃ',
  'ṅ' => 'Ṅ',
  'ṇ' => 'Ṇ',
  'ṉ' => 'Ṉ',
  'ṋ' => 'Ṋ',
  'ṍ' => 'Ṍ',
  'ṏ' => 'Ṏ',
  'ṑ' => 'Ṑ',
  'ṓ' => 'Ṓ',
  'ṕ' => 'Ṕ',
  'ṗ' => 'Ṗ',
  'ṙ' => 'Ṙ',
  'ṛ' => 'Ṛ',
  'ṝ' => 'Ṝ',
  'ṟ' => 'Ṟ',
  'ṡ' => 'Ṡ',
  'ṣ' => 'Ṣ',
  'ṥ' => 'Ṥ',
  'ṧ' => 'Ṧ',
  'ṩ' => 'Ṩ',
  'ṫ' => 'Ṫ',
  'ṭ' => 'Ṭ',
  'ṯ' => 'Ṯ',
  'ṱ' => 'Ṱ',
  'ṳ' => 'Ṳ',
  'ṵ' => 'Ṵ',
  'ṷ' => 'Ṷ',
  'ṹ' => 'Ṹ',
  'ṻ' => 'Ṻ',
  'ṽ' => 'Ṽ',
  'ṿ' => 'Ṿ',
  'ẁ' => 'Ẁ',
  'ẃ' => 'Ẃ',
  'ẅ' => 'Ẅ',
  'ẇ' => 'Ẇ',
  'ẉ' => 'Ẉ',
  'ẋ' => 'Ẋ',
  'ẍ' => 'Ẍ',
  'ẏ' => 'Ẏ',
  'ẑ' => 'Ẑ',
  'ẓ' => 'Ẓ',
  'ẕ' => 'Ẕ',
  'ẛ' => 'Ṡ',
  'ạ' => 'Ạ',
  'ả' => 'Ả',
  'ấ' => 'Ấ',
  'ầ' => 'Ầ',
  'ẩ' => 'Ẩ',
  'ẫ' => 'Ẫ',
  'ậ' => 'Ậ',
  'ắ' => 'Ắ',
  'ằ' => 'Ằ',
  'ẳ' => 'Ẳ',
  'ẵ' => 'Ẵ',
  'ặ' => 'Ặ',
  'ẹ' => 'Ẹ',
  'ẻ' => 'Ẻ',
  'ẽ' => 'Ẽ',
  'ế' => 'Ế',
  'ề' => 'Ề',
  'ể' => 'Ể',
  'ễ' => 'Ễ',
  'ệ' => 'Ệ',
  'ỉ' => 'Ỉ',
  'ị' => 'Ị',
  'ọ' => 'Ọ',
  'ỏ' => 'Ỏ',
  'ố' => 'Ố',
  'ồ' => 'Ồ',
  'ổ' => 'Ổ',
  'ỗ' => 'Ỗ',
  'ộ' => 'Ộ',
  'ớ' => 'Ớ',
  'ờ' => 'Ờ',
  'ở' => 'Ở',
  'ỡ' => 'Ỡ',
  'ợ' => 'Ợ',
  'ụ' => 'Ụ',
  'ủ' => 'Ủ',
  'ứ' => 'Ứ',
  'ừ' => 'Ừ',
  'ử' => 'Ử',
  'ữ' => 'Ữ',
  'ự' => 'Ự',
  'ỳ' => 'Ỳ',
  'ỵ' => 'Ỵ',
  'ỷ' => 'Ỷ',
  'ỹ' => 'Ỹ',
  'ỻ' => 'Ỻ',
  'ỽ' => 'Ỽ',
  'ỿ' => 'Ỿ',
  'ἀ' => 'Ἀ',
  'ἁ' => 'Ἁ',
  'ἂ' => 'Ἂ',
  'ἃ' => 'Ἃ',
  'ἄ' => 'Ἄ',
  'ἅ' => 'Ἅ',
  'ἆ' => 'Ἆ',
  'ἇ' => 'Ἇ',
  'ἐ' => 'Ἐ',
  'ἑ' => 'Ἑ',
  'ἒ' => 'Ἒ',
  'ἓ' => 'Ἓ',
  'ἔ' => 'Ἔ',
  'ἕ' => 'Ἕ',
  'ἠ' => 'Ἠ',
  'ἡ' => 'Ἡ',
  'ἢ' => 'Ἢ',
  'ἣ' => 'Ἣ',
  'ἤ' => 'Ἤ',
  'ἥ' => 'Ἥ',
  'ἦ' => 'Ἦ',
  'ἧ' => 'Ἧ',
  'ἰ' => 'Ἰ',
  'ἱ' => 'Ἱ',
  'ἲ' => 'Ἲ',
  'ἳ' => 'Ἳ',
  'ἴ' => 'Ἴ',
  'ἵ' => 'Ἵ',
  'ἶ' => 'Ἶ',
  'ἷ' => 'Ἷ',
  'ὀ' => 'Ὀ',
  'ὁ' => 'Ὁ',
  'ὂ' => 'Ὂ',
  'ὃ' => 'Ὃ',
  'ὄ' => 'Ὄ',
  'ὅ' => 'Ὅ',
  'ὑ' => 'Ὑ',
  'ὓ' => 'Ὓ',
  'ὕ' => 'Ὕ',
  'ὗ' => 'Ὗ',
  'ὠ' => 'Ὠ',
  'ὡ' => 'Ὡ',
  'ὢ' => 'Ὢ',
  'ὣ' => 'Ὣ',
  'ὤ' => 'Ὤ',
  'ὥ' => 'Ὥ',
  'ὦ' => 'Ὦ',
  'ὧ' => 'Ὧ',
  'ὰ' => 'Ὰ',
  'ά' => 'Ά',
  'ὲ' => 'Ὲ',
  'έ' => 'Έ',
  'ὴ' => 'Ὴ',
  'ή' => 'Ή',
  'ὶ' => 'Ὶ',
  'ί' => 'Ί',
  'ὸ' => 'Ὸ',
  'ό' => 'Ό',
  'ὺ' => 'Ὺ',
  'ύ' => 'Ύ',
  'ὼ' => 'Ὼ',
  'ώ' => 'Ώ',
  'ᾀ' => 'ᾈ',
  'ᾁ' => 'ᾉ',
  'ᾂ' => 'ᾊ',
  'ᾃ' => 'ᾋ',
  'ᾄ' => 'ᾌ',
  'ᾅ' => 'ᾍ',
  'ᾆ' => 'ᾎ',
  'ᾇ' => 'ᾏ',
  'ᾐ' => 'ᾘ',
  'ᾑ' => 'ᾙ',
  'ᾒ' => 'ᾚ',
  'ᾓ' => 'ᾛ',
  'ᾔ' => 'ᾜ',
  'ᾕ' => 'ᾝ',
  'ᾖ' => 'ᾞ',
  'ᾗ' => 'ᾟ',
  'ᾠ' => 'ᾨ',
  'ᾡ' => 'ᾩ',
  'ᾢ' => 'ᾪ',
  'ᾣ' => 'ᾫ',
  'ᾤ' => 'ᾬ',
  'ᾥ' => 'ᾭ',
  'ᾦ' => 'ᾮ',
  'ᾧ' => 'ᾯ',
  'ᾰ' => 'Ᾰ',
  'ᾱ' => 'Ᾱ',
  'ᾳ' => 'ᾼ',
  'ι' => 'Ι',
  'ῃ' => 'ῌ',
  'ῐ' => 'Ῐ',
  'ῑ' => 'Ῑ',
  'ῠ' => 'Ῠ',
  'ῡ' => 'Ῡ',
  'ῥ' => 'Ῥ',
  'ῳ' => 'ῼ',
  'ⅎ' => 'Ⅎ',
  'ⅰ' => 'Ⅰ',
  'ⅱ' => 'Ⅱ',
  'ⅲ' => 'Ⅲ',
  'ⅳ' => 'Ⅳ',
  'ⅴ' => 'Ⅴ',
  'ⅵ' => 'Ⅵ',
  'ⅶ' => 'Ⅶ',
  'ⅷ' => 'Ⅷ',
  'ⅸ' => 'Ⅸ',
  'ⅹ' => 'Ⅹ',
  'ⅺ' => 'Ⅺ',
  'ⅻ' => 'Ⅻ',
  'ⅼ' => 'Ⅼ',
  'ⅽ' => 'Ⅽ',
  'ⅾ' => 'Ⅾ',
  'ⅿ' => 'Ⅿ',
  'ↄ' => 'Ↄ',
  'ⓐ' => 'Ⓐ',
  'ⓑ' => 'Ⓑ',
  'ⓒ' => 'Ⓒ',
  'ⓓ' => 'Ⓓ',
  'ⓔ' => 'Ⓔ',
  'ⓕ' => 'Ⓕ',
  'ⓖ' => 'Ⓖ',
  'ⓗ' => 'Ⓗ',
  'ⓘ' => 'Ⓘ',
  'ⓙ' => 'Ⓙ',
  'ⓚ' => 'Ⓚ',
  'ⓛ' => 'Ⓛ',
  'ⓜ' => 'Ⓜ',
  'ⓝ' => 'Ⓝ',
  'ⓞ' => 'Ⓞ',
  'ⓟ' => 'Ⓟ',
  'ⓠ' => 'Ⓠ',
  'ⓡ' => 'Ⓡ',
  'ⓢ' => 'Ⓢ',
  'ⓣ' => 'Ⓣ',
  'ⓤ' => 'Ⓤ',
  'ⓥ' => 'Ⓥ',
  'ⓦ' => 'Ⓦ',
  'ⓧ' => 'Ⓧ',
  'ⓨ' => 'Ⓨ',
  'ⓩ' => 'Ⓩ',
  'ⰰ' => 'Ⰰ',
  'ⰱ' => 'Ⰱ',
  'ⰲ' => 'Ⰲ',
  'ⰳ' => 'Ⰳ',
  'ⰴ' => 'Ⰴ',
  'ⰵ' => 'Ⰵ',
  'ⰶ' => 'Ⰶ',
  'ⰷ' => 'Ⰷ',
  'ⰸ' => 'Ⰸ',
  'ⰹ' => 'Ⰹ',
  'ⰺ' => 'Ⰺ',
  'ⰻ' => 'Ⰻ',
  'ⰼ' => 'Ⰼ',
  'ⰽ' => 'Ⰽ',
  'ⰾ' => 'Ⰾ',
  'ⰿ' => 'Ⰿ',
  'ⱀ' => 'Ⱀ',
  'ⱁ' => 'Ⱁ',
  'ⱂ' => 'Ⱂ',
  'ⱃ' => 'Ⱃ',
  'ⱄ' => 'Ⱄ',
  'ⱅ' => 'Ⱅ',
  'ⱆ' => 'Ⱆ',
  'ⱇ' => 'Ⱇ',
  'ⱈ' => 'Ⱈ',
  'ⱉ' => 'Ⱉ',
  'ⱊ' => 'Ⱊ',
  'ⱋ' => 'Ⱋ',
  'ⱌ' => 'Ⱌ',
  'ⱍ' => 'Ⱍ',
  'ⱎ' => 'Ⱎ',
  'ⱏ' => 'Ⱏ',
  'ⱐ' => 'Ⱐ',
  'ⱑ' => 'Ⱑ',
  'ⱒ' => 'Ⱒ',
  'ⱓ' => 'Ⱓ',
  'ⱔ' => 'Ⱔ',
  'ⱕ' => 'Ⱕ',
  'ⱖ' => 'Ⱖ',
  'ⱗ' => 'Ⱗ',
  'ⱘ' => 'Ⱘ',
  'ⱙ' => 'Ⱙ',
  'ⱚ' => 'Ⱚ',
  'ⱛ' => 'Ⱛ',
  'ⱜ' => 'Ⱜ',
  'ⱝ' => 'Ⱝ',
  'ⱞ' => 'Ⱞ',
  'ⱡ' => 'Ⱡ',
  'ⱥ' => 'Ⱥ',
  'ⱦ' => 'Ⱦ',
  'ⱨ' => 'Ⱨ',
  'ⱪ' => 'Ⱪ',
  'ⱬ' => 'Ⱬ',
  'ⱳ' => 'Ⱳ',
  'ⱶ' => 'Ⱶ',
  'ⲁ' => 'Ⲁ',
  'ⲃ' => 'Ⲃ',
  'ⲅ' => 'Ⲅ',
  'ⲇ' => 'Ⲇ',
  'ⲉ' => 'Ⲉ',
  'ⲋ' => 'Ⲋ',
  'ⲍ' => 'Ⲍ',
  'ⲏ' => 'Ⲏ',
  'ⲑ' => 'Ⲑ',
  'ⲓ' => 'Ⲓ',
  'ⲕ' => 'Ⲕ',
  'ⲗ' => 'Ⲗ',
  'ⲙ' => 'Ⲙ',
  'ⲛ' => 'Ⲛ',
  'ⲝ' => 'Ⲝ',
  'ⲟ' => 'Ⲟ',
  'ⲡ' => 'Ⲡ',
  'ⲣ' => 'Ⲣ',
  'ⲥ' => 'Ⲥ',
  'ⲧ' => 'Ⲧ',
  'ⲩ' => 'Ⲩ',
  'ⲫ' => 'Ⲫ',
  'ⲭ' => 'Ⲭ',
  'ⲯ' => 'Ⲯ',
  'ⲱ' => 'Ⲱ',
  'ⲳ' => 'Ⲳ',
  'ⲵ' => 'Ⲵ',
  'ⲷ' => 'Ⲷ',
  'ⲹ' => 'Ⲹ',
  'ⲻ' => 'Ⲻ',
  'ⲽ' => 'Ⲽ',
  'ⲿ' => 'Ⲿ',
  'ⳁ' => 'Ⳁ',
  'ⳃ' => 'Ⳃ',
  'ⳅ' => 'Ⳅ',
  'ⳇ' => 'Ⳇ',
  'ⳉ' => 'Ⳉ',
  'ⳋ' => 'Ⳋ',
  'ⳍ' => 'Ⳍ',
  'ⳏ' => 'Ⳏ',
  'ⳑ' => 'Ⳑ',
  'ⳓ' => 'Ⳓ',
  'ⳕ' => 'Ⳕ',
  'ⳗ' => 'Ⳗ',
  'ⳙ' => 'Ⳙ',
  'ⳛ' => 'Ⳛ',
  'ⳝ' => 'Ⳝ',
  'ⳟ' => 'Ⳟ',
  'ⳡ' => 'Ⳡ',
  'ⳣ' => 'Ⳣ',
  'ⳬ' => 'Ⳬ',
  'ⳮ' => 'Ⳮ',
  'ⳳ' => 'Ⳳ',
  'ⴀ' => 'Ⴀ',
  'ⴁ' => 'Ⴁ',
  'ⴂ' => 'Ⴂ',
  'ⴃ' => 'Ⴃ',
  'ⴄ' => 'Ⴄ',
  'ⴅ' => 'Ⴅ',
  'ⴆ' => 'Ⴆ',
  'ⴇ' => 'Ⴇ',
  'ⴈ' => 'Ⴈ',
  'ⴉ' => 'Ⴉ',
  'ⴊ' => 'Ⴊ',
  'ⴋ' => 'Ⴋ',
  'ⴌ' => 'Ⴌ',
  'ⴍ' => 'Ⴍ',
  'ⴎ' => 'Ⴎ',
  'ⴏ' => 'Ⴏ',
  'ⴐ' => 'Ⴐ',
  'ⴑ' => 'Ⴑ',
  'ⴒ' => 'Ⴒ',
  'ⴓ' => 'Ⴓ',
  'ⴔ' => 'Ⴔ',
  'ⴕ' => 'Ⴕ',
  'ⴖ' => 'Ⴖ',
  'ⴗ' => 'Ⴗ',
  'ⴘ' => 'Ⴘ',
  'ⴙ' => 'Ⴙ',
  'ⴚ' => 'Ⴚ',
  'ⴛ' => 'Ⴛ',
  'ⴜ' => 'Ⴜ',
  'ⴝ' => 'Ⴝ',
  'ⴞ' => 'Ⴞ',
  'ⴟ' => 'Ⴟ',
  'ⴠ' => 'Ⴠ',
  'ⴡ' => 'Ⴡ',
  'ⴢ' => 'Ⴢ',
  'ⴣ' => 'Ⴣ',
  'ⴤ' => 'Ⴤ',
  'ⴥ' => 'Ⴥ',
  'ⴧ' => 'Ⴧ',
  'ⴭ' => 'Ⴭ',
  'ꙁ' => 'Ꙁ',
  'ꙃ' => 'Ꙃ',
  'ꙅ' => 'Ꙅ',
  'ꙇ' => 'Ꙇ',
  'ꙉ' => 'Ꙉ',
  'ꙋ' => 'Ꙋ',
  'ꙍ' => 'Ꙍ',
  'ꙏ' => 'Ꙏ',
  'ꙑ' => 'Ꙑ',
  'ꙓ' => 'Ꙓ',
  'ꙕ' => 'Ꙕ',
  'ꙗ' => 'Ꙗ',
  'ꙙ' => 'Ꙙ',
  'ꙛ' => 'Ꙛ',
  'ꙝ' => 'Ꙝ',
  'ꙟ' => 'Ꙟ',
  'ꙡ' => 'Ꙡ',
  'ꙣ' => 'Ꙣ',
  'ꙥ' => 'Ꙥ',
  'ꙧ' => 'Ꙧ',
  'ꙩ' => 'Ꙩ',
  'ꙫ' => 'Ꙫ',
  'ꙭ' => 'Ꙭ',
  'ꚁ' => 'Ꚁ',
  'ꚃ' => 'Ꚃ',
  'ꚅ' => 'Ꚅ',
  'ꚇ' => 'Ꚇ',
  'ꚉ' => 'Ꚉ',
  'ꚋ' => 'Ꚋ',
  'ꚍ' => 'Ꚍ',
  'ꚏ' => 'Ꚏ',
  'ꚑ' => 'Ꚑ',
  'ꚓ' => 'Ꚓ',
  'ꚕ' => 'Ꚕ',
  'ꚗ' => 'Ꚗ',
  'ꚙ' => 'Ꚙ',
  'ꚛ' => 'Ꚛ',
  'ꜣ' => 'Ꜣ',
  'ꜥ' => 'Ꜥ',
  'ꜧ' => 'Ꜧ',
  'ꜩ' => 'Ꜩ',
  'ꜫ' => 'Ꜫ',
  'ꜭ' => 'Ꜭ',
  'ꜯ' => 'Ꜯ',
  'ꜳ' => 'Ꜳ',
  'ꜵ' => 'Ꜵ',
  'ꜷ' => 'Ꜷ',
  'ꜹ' => 'Ꜹ',
  'ꜻ' => 'Ꜻ',
  'ꜽ' => 'Ꜽ',
  'ꜿ' => 'Ꜿ',
  'ꝁ' => 'Ꝁ',
  'ꝃ' => 'Ꝃ',
  'ꝅ' => 'Ꝅ',
  'ꝇ' => 'Ꝇ',
  'ꝉ' => 'Ꝉ',
  'ꝋ' => 'Ꝋ',
  'ꝍ' => 'Ꝍ',
  'ꝏ' => 'Ꝏ',
  'ꝑ' => 'Ꝑ',
  'ꝓ' => 'Ꝓ',
  'ꝕ' => 'Ꝕ',
  'ꝗ' => 'Ꝗ',
  'ꝙ' => 'Ꝙ',
  'ꝛ' => 'Ꝛ',
  'ꝝ' => 'Ꝝ',
  'ꝟ' => 'Ꝟ',
  'ꝡ' => 'Ꝡ',
  'ꝣ' => 'Ꝣ',
  'ꝥ' => 'Ꝥ',
  'ꝧ' => 'Ꝧ',
  'ꝩ' => 'Ꝩ',
  'ꝫ' => 'Ꝫ',
  'ꝭ' => 'Ꝭ',
  'ꝯ' => 'Ꝯ',
  'ꝺ' => 'Ꝺ',
  'ꝼ' => 'Ꝼ',
  'ꝿ' => 'Ꝿ',
  'ꞁ' => 'Ꞁ',
  'ꞃ' => 'Ꞃ',
  'ꞅ' => 'Ꞅ',
  'ꞇ' => 'Ꞇ',
  'ꞌ' => 'Ꞌ',
  'ꞑ' => 'Ꞑ',
  'ꞓ' => 'Ꞓ',
  'ꞗ' => 'Ꞗ',
  'ꞙ' => 'Ꞙ',
  'ꞛ' => 'Ꞛ',
  'ꞝ' => 'Ꞝ',
  'ꞟ' => 'Ꞟ',
  'ꞡ' => 'Ꞡ',
  'ꞣ' => 'Ꞣ',
  'ꞥ' => 'Ꞥ',
  'ꞧ' => 'Ꞧ',
  'ꞩ' => 'Ꞩ',
  'a' => 'A',
  'b' => 'B',
  'c' => 'C',
  'd' => 'D',
  'e' => 'E',
  'f' => 'F',
  'g' => 'G',
  'h' => 'H',
  'i' => 'I',
  'j' => 'J',
  'k' => 'K',
  'l' => 'L',
  'm' => 'M',
  'n' => 'N',
  'o' => 'O',
  'p' => 'P',
  'q' => 'Q',
  'r' => 'R',
  's' => 'S',
  't' => 'T',
  'u' => 'U',
  'v' => 'V',
  'w' => 'W',
  'x' => 'X',
  'y' => 'Y',
  'z' => 'Z',
  '𐐨' => '𐐀',
  '𐐩' => '𐐁',
  '𐐪' => '𐐂',
  '𐐫' => '𐐃',
  '𐐬' => '𐐄',
  '𐐭' => '𐐅',
  '𐐮' => '𐐆',
  '𐐯' => '𐐇',
  '𐐰' => '𐐈',
  '𐐱' => '𐐉',
  '𐐲' => '𐐊',
  '𐐳' => '𐐋',
  '𐐴' => '𐐌',
  '𐐵' => '𐐍',
  '𐐶' => '𐐎',
  '𐐷' => '𐐏',
  '𐐸' => '𐐐',
  '𐐹' => '𐐑',
  '𐐺' => '𐐒',
  '𐐻' => '𐐓',
  '𐐼' => '𐐔',
  '𐐽' => '𐐕',
  '𐐾' => '𐐖',
  '𐐿' => '𐐗',
  '𐑀' => '𐐘',
  '𐑁' => '𐐙',
  '𐑂' => '𐐚',
  '𐑃' => '𐐛',
  '𐑄' => '𐐜',
  '𐑅' => '𐐝',
  '𐑆' => '𐐞',
  '𐑇' => '𐐟',
  '𐑈' => '𐐠',
  '𐑉' => '𐐡',
  '𐑊' => '𐐢',
  '𐑋' => '𐐣',
  '𐑌' => '𐐤',
  '𐑍' => '𐐥',
  '𐑎' => '𐐦',
  '𐑏' => '𐐧',
  '𑣀' => '𑢠',
  '𑣁' => '𑢡',
  '𑣂' => '𑢢',
  '𑣃' => '𑢣',
  '𑣄' => '𑢤',
  '𑣅' => '𑢥',
  '𑣆' => '𑢦',
  '𑣇' => '𑢧',
  '𑣈' => '𑢨',
  '𑣉' => '𑢩',
  '𑣊' => '𑢪',
  '𑣋' => '𑢫',
  '𑣌' => '𑢬',
  '𑣍' => '𑢭',
  '𑣎' => '𑢮',
  '𑣏' => '𑢯',
  '𑣐' => '𑢰',
  '𑣑' => '𑢱',
  '𑣒' => '𑢲',
  '𑣓' => '𑢳',
  '𑣔' => '𑢴',
  '𑣕' => '𑢵',
  '𑣖' => '𑢶',
  '𑣗' => '𑢷',
  '𑣘' => '𑢸',
  '𑣙' => '𑢹',
  '𑣚' => '𑢺',
  '𑣛' => '𑢻',
  '𑣜' => '𑢼',
  '𑣝' => '𑢽',
  '𑣞' => '𑢾',
  '𑣟' => '𑢿',
);

$result =& $data;
unset($data);

return $result;
<?php
{
    "name": "symfony/polyfill-mbstring",
    "type": "library",
    "description": "Symfony polyfill for the Mbstring extension",
    "keywords": ["polyfill", "shim", "compatibility", "portable", "mbstring"],
    "homepage": "https://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=5.3.3"
    },
    "autoload": {
        "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" },
        "files": [ "bootstrap.php" ]
    },
    "suggest": {
        "ext-mbstring": "For best performance"
    },
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-master": "1.6-dev"
        }
    }
}
�Mo�[ķ�D�J�YL�8�GBMB