From 1fc144e17851c2a450171a8b352407871b725143 Mon Sep 17 00:00:00 2001 From: Clemens Schwaighofer Date: Wed, 2 Aug 2023 14:52:33 +0900 Subject: [PATCH] Composer Workspace global packages --- composer.lock | 178 ++-- vendor/composer/installed.json | 202 +++-- vendor/composer/installed.php | 74 +- vendor/doctrine/deprecations/README.md | 7 +- vendor/doctrine/deprecations/composer.json | 20 +- .../lib/Doctrine/Deprecations/Deprecation.php | 108 ++- vendor/doctrine/deprecations/phpstan.neon | 9 + vendor/doctrine/deprecations/psalm.xml | 30 + vendor/nikic/php-parser/grammar/php5.y | 2 +- vendor/nikic/php-parser/grammar/php7.y | 2 +- .../php-parser/lib/PhpParser/Node/Name.php | 14 +- .../php-parser/lib/PhpParser/Parser/Php5.php | 2 +- .../php-parser/lib/PhpParser/Parser/Php7.php | 2 +- .../src/PseudoTypes/StringValue.php | 4 +- vendor/phpstan/phpdoc-parser/README.md | 5 +- vendor/phpstan/phpdoc-parser/composer.json | 1 + .../src/Ast/AbstractNodeVisitor.php | 2 +- .../PhpDoc/Doctrine/DoctrineAnnotation.php | 35 + .../Ast/PhpDoc/Doctrine/DoctrineArgument.php | 43 + .../src/Ast/PhpDoc/Doctrine/DoctrineArray.php | 32 + .../Ast/PhpDoc/Doctrine/DoctrineArrayItem.php | 47 + .../PhpDoc/Doctrine/DoctrineTagValueNode.php | 36 + .../src/Ast/PhpDoc/PhpDocTagNode.php | 5 + .../phpstan/phpdoc-parser/src/Lexer/Lexer.php | 58 +- .../src/Parser/ConstExprParser.php | 12 +- .../phpdoc-parser/src/Parser/PhpDocParser.php | 524 ++++++++++- .../src/Parser/TokenIterator.php | 102 ++- .../phpdoc-parser/src/Parser/TypeParser.php | 13 +- .../phpdoc-parser/src/Printer/Printer.php | 42 +- vendor/phpstan/phpstan/phpstan.phar | Bin 21742779 -> 21953985 bytes vendor/phpstan/phpstan/phpstan.phar.asc | 26 +- vendor/spatie/array-to-xml/CHANGELOG.md | 15 + vendor/spatie/array-to-xml/README.md | 52 ++ vendor/spatie/array-to-xml/src/ArrayToXml.php | 5 + vendor/symfony/console/Application.php | 105 ++- vendor/symfony/console/CHANGELOG.md | 7 + vendor/symfony/console/Command/Command.php | 18 +- .../console/Command/CompleteCommand.php | 8 +- .../console/Command/DumpCompletionCommand.php | 2 +- .../symfony/console/Command/HelpCommand.php | 14 +- .../symfony/console/Command/ListCommand.php | 11 +- .../symfony/console/Command/LockableTrait.php | 4 +- .../Command/SignalableCommandInterface.php | 6 +- .../console/Completion/CompletionInput.php | 2 +- .../AddConsoleCommandPass.php | 3 + .../Descriptor/ApplicationDescription.php | 2 +- .../symfony/console/Descriptor/Descriptor.php | 22 +- .../Descriptor/DescriptorInterface.php | 3 + .../console/Descriptor/JsonDescriptor.php | 12 +- .../console/Descriptor/MarkdownDescriptor.php | 38 +- .../Descriptor/ReStructuredTextDescriptor.php | 272 ++++++ .../console/Descriptor/TextDescriptor.php | 20 +- .../console/Descriptor/XmlDescriptor.php | 14 +- .../console/Event/ConsoleSignalEvent.php | 23 +- .../console/EventListener/ErrorListener.php | 6 + .../console/Formatter/OutputFormatter.php | 9 + .../Formatter/OutputFormatterInterface.php | 4 + .../Formatter/OutputFormatterStyle.php | 15 + .../OutputFormatterStyleInterface.php | 10 + .../Formatter/OutputFormatterStyleStack.php | 4 + .../console/Helper/DescriptorHelper.php | 4 + vendor/symfony/console/Helper/Dumper.php | 14 +- vendor/symfony/console/Helper/Helper.php | 14 +- .../console/Helper/HelperInterface.php | 2 + vendor/symfony/console/Helper/HelperSet.php | 3 + .../console/Helper/InputAwareHelper.php | 3 + vendor/symfony/console/Helper/ProgressBar.php | 79 +- .../console/Helper/ProgressIndicator.php | 30 +- .../symfony/console/Helper/QuestionHelper.php | 16 +- .../console/Helper/SymfonyQuestionHelper.php | 6 + vendor/symfony/console/Helper/Table.php | 16 +- .../symfony/console/Helper/TableCellStyle.php | 4 +- vendor/symfony/console/Input/ArgvInput.php | 18 +- vendor/symfony/console/Input/ArrayInput.php | 9 +- vendor/symfony/console/Input/Input.php | 29 +- .../symfony/console/Input/InputArgument.php | 2 + .../console/Input/InputAwareInterface.php | 2 + .../symfony/console/Input/InputDefinition.php | 14 + .../symfony/console/Input/InputInterface.php | 10 + vendor/symfony/console/Input/InputOption.php | 3 + .../Input/StreamableInputInterface.php | 2 + .../symfony/console/Output/AnsiColorMode.php | 22 +- .../symfony/console/Output/BufferedOutput.php | 3 + .../symfony/console/Output/ConsoleOutput.php | 12 + .../console/Output/ConsoleOutputInterface.php | 3 + .../console/Output/ConsoleSectionOutput.php | 9 +- vendor/symfony/console/Output/NullOutput.php | 15 + vendor/symfony/console/Output/Output.php | 17 + .../console/Output/OutputInterface.php | 11 + .../symfony/console/Output/StreamOutput.php | 3 + .../console/Output/TrimmedBufferOutput.php | 3 + vendor/symfony/console/Question/Question.php | 12 +- vendor/symfony/console/README.md | 16 + .../symfony/console/Resources/completion.bash | 10 + vendor/symfony/console/Style/OutputStyle.php | 21 + .../symfony/console/Style/StyleInterface.php | 28 + vendor/symfony/console/Style/SymfonyStyle.php | 64 +- vendor/symfony/console/Terminal.php | 4 +- vendor/symfony/console/Tester/TesterTrait.php | 2 +- vendor/symfony/console/composer.json | 10 +- .../deprecation-contracts/composer.json | 2 +- vendor/symfony/filesystem/Filesystem.php | 46 +- .../Test/ServiceLocatorTest.php | 81 +- .../Test/ServiceLocatorTestCase.php | 92 ++ .../symfony/service-contracts/composer.json | 5 +- .../symfony/string/AbstractUnicodeString.php | 12 +- .../string/Inflector/EnglishInflector.php | 9 + vendor/symfony/string/LazyString.php | 4 +- .../symfony/string/Slugger/AsciiSlugger.php | 7 +- vendor/symfony/string/composer.json | 4 +- vendor/vimeo/psalm/composer.json | 6 +- vendor/vimeo/psalm/config.xsd | 1 + vendor/vimeo/psalm/dictionaries/CallMap.php | 223 ++--- .../psalm/dictionaries/CallMap_83_delta.php | 116 +++ .../psalm/dictionaries/CallMap_historical.php | 153 ++-- .../type_syntax/array_types.md | 13 + .../type_syntax/atomic_types.md | 2 +- .../psalm/docs/running_psalm/configuration.md | 11 +- .../docs/running_psalm/language_server.md | 25 +- vendor/vimeo/psalm/src/Psalm/Codebase.php | 11 +- vendor/vimeo/psalm/src/Psalm/Config.php | 62 +- .../vimeo/psalm/src/Psalm/Config/Creator.php | 6 + .../psalm/src/Psalm/Config/FileFilter.php | 119 ++- .../psalm/src/Psalm/Internal/Algebra.php | 72 ++ .../src/Psalm/Internal/Analyzer/CanAlias.php | 7 +- .../Psalm/Internal/Analyzer/ClassAnalyzer.php | 24 +- .../Internal/Analyzer/ClassLikeAnalyzer.php | 9 +- .../Internal/Analyzer/CommentAnalyzer.php | 27 +- .../Psalm/Internal/Analyzer/FileAnalyzer.php | 3 +- .../src/Psalm/Internal/Analyzer/IssueData.php | 7 + .../Internal/Analyzer/NamespaceAnalyzer.php | 3 +- .../Internal/Analyzer/ProjectAnalyzer.php | 9 + .../Block/IfConditionalAnalyzer.php | 8 +- .../Block/IfElse/ElseIfAnalyzer.php | 10 - .../Statements/Block/SwitchCaseAnalyzer.php | 2 +- .../Statements/Block/WhileAnalyzer.php | 3 +- .../Statements/Expression/AssertionFinder.php | 254 ++++-- .../Expression/AssignmentAnalyzer.php | 18 +- .../BinaryOp/ArithmeticOpAnalyzer.php | 44 +- .../Expression/BinaryOpAnalyzer.php | 2 +- .../Expression/Call/ArgumentsAnalyzer.php | 7 +- .../Expression/Call/FunctionCallAnalyzer.php | 15 +- .../Call/FunctionCallReturnTypeFetcher.php | 2 +- .../Expression/Call/NewAnalyzer.php | 11 +- .../Expression/Call/StaticCallAnalyzer.php | 12 +- .../StaticMethod/AtomicStaticCallAnalyzer.php | 14 +- .../ExistingAtomicStaticCallAnalyzer.php | 10 +- .../Statements/Expression/CallAnalyzer.php | 2 +- .../Expression/ClassConstAnalyzer.php | 8 +- .../Expression/ExpressionIdentifier.php | 12 +- .../Expression/Fetch/ConstFetchAnalyzer.php | 5 +- .../Fetch/StaticPropertyFetchAnalyzer.php | 8 +- .../Fetch/VariableFetchAnalyzer.php | 2 +- .../Statements/Expression/IncludeAnalyzer.php | 8 +- .../Expression/InstanceofAnalyzer.php | 4 +- .../Expression/MagicConstAnalyzer.php | 2 +- .../Statements/Expression/MatchAnalyzer.php | 10 +- .../Expression/SimpleTypeInferer.php | 14 +- .../Analyzer/Statements/UnsetAnalyzer.php | 3 +- .../Internal/Analyzer/StatementsAnalyzer.php | 2 +- .../vimeo/psalm/src/Psalm/Internal/Cache.php | 128 +++ .../src/Psalm/Internal/Cli/LanguageServer.php | 67 +- .../psalm/src/Psalm/Internal/Cli/Psalm.php | 28 +- .../src/Psalm/Internal/Codebase/Analyzer.php | 24 +- .../Psalm/Internal/Codebase/ClassLikes.php | 34 +- .../src/Psalm/Internal/Codebase/Methods.php | 26 +- .../Internal/Diff/ClassStatementsDiffer.php | 16 + .../Internal/Diff/FileStatementsDiffer.php | 4 +- .../Diff/NamespaceStatementsDiffer.php | 4 +- .../psalm/src/Psalm/Internal/Fork/Pool.php | 1 + .../Client/Progress/LegacyProgress.php | 83 ++ .../Client/Progress/Progress.php | 121 +++ .../Client/Progress/ProgressInterface.php | 16 + .../LanguageServer/LanguageClient.php | 14 +- .../LanguageServer/LanguageServer.php | 131 +-- .../Internal/LanguageServer/PathMapper.php | 61 ++ .../Provider/FileReferenceCacheProvider.php | 2 +- .../Provider/FileStorageCacheProvider.php | 24 +- .../LanguageServer/Server/TextDocument.php | 38 +- .../LanguageServer/Server/Workspace.php | 11 +- .../Reflector/ClassLikeNodeScanner.php | 9 +- .../Reflector/ExpressionResolver.php | 68 +- .../Reflector/ExpressionScanner.php | 29 +- .../Reflector/FunctionLikeNodeScanner.php | 7 +- .../PhpVisitor/Reflector/TypeHintResolver.php | 5 +- .../Internal/PhpVisitor/ReflectorVisitor.php | 13 +- .../AddRemoveTaints/HtmlFunctionTainter.php | 8 +- .../ClassLikeStorageCacheProvider.php | 52 +- .../Internal/Provider/FakeFileProvider.php | 6 + .../Provider/FileReferenceCacheProvider.php | 822 ++---------------- .../Provider/FileReferenceProvider.php | 11 +- .../Provider/FileStorageCacheProvider.php | 67 +- .../Provider/FunctionReturnTypeProvider.php | 2 + .../Internal/Provider/ParserCacheProvider.php | 67 +- .../Provider/ProjectCacheProvider.php | 23 +- .../src/Psalm/Internal/Provider/Providers.php | 2 +- .../ArrayFillReturnTypeProvider.php | 5 +- .../DirnameReturnTypeProvider.php | 11 + .../ImagickPixelColorReturnTypeProvider.php | 17 +- .../MinMaxReturnTypeProvider.php | 2 +- .../PdoStatementReturnTypeProvider.php | 304 +++++-- .../RandReturnTypeProvider.php | 2 +- .../SprintfReturnTypeProvider.php | 329 +++++++ .../StrReplaceReturnTypeProvider.php | 61 +- .../Internal/Provider/StatementsProvider.php | 14 +- .../Provider/StatementsVolatileCache.php | 100 --- .../src/Psalm/Internal/RuntimeCaches.php | 2 - .../Psalm/Internal/Scanner/DocblockParser.php | 41 +- .../Internal/Scanner/PhpStormMetaScanner.php | 15 +- .../Internal/Type/AssertionReconciler.php | 17 +- .../Type/ClosedInheritanceToUnion.php | 81 ++ .../Comparator/CallableTypeComparator.php | 31 + .../Type/NegatedAssertionReconciler.php | 5 + .../Type/SimpleAssertionReconciler.php | 4 +- .../Type/TemplateStandinTypeReplacer.php | 61 +- .../src/Psalm/Internal/Type/TypeCombiner.php | 14 +- .../vimeo/psalm/src/Psalm/Issue/CodeIssue.php | 3 + vendor/vimeo/psalm/src/Psalm/IssueBuffer.php | 123 ++- .../EventHandler/Event/AfterAnalysisEvent.php | 6 +- .../vimeo/psalm/src/Psalm/Plugin/Shepherd.php | 24 +- vendor/vimeo/psalm/src/Psalm/Report.php | 2 +- .../psalm/src/Psalm/Report/CompactReport.php | 3 +- .../psalm/src/Psalm/Report/EmacsReport.php | 4 +- .../src/Psalm/Report/GithubActionsReport.php | 4 +- .../psalm/src/Psalm/Report/JunitReport.php | 4 +- .../psalm/src/Psalm/Report/TextReport.php | 4 +- vendor/vimeo/psalm/src/Psalm/Type.php | 10 +- .../src/Psalm/Type/Atomic/TCallableList.php | 4 +- .../Psalm/Type/Atomic/TDependentListKey.php | 4 +- .../src/Psalm/Type/Atomic/TKeyedArray.php | 2 +- .../psalm/src/Psalm/Type/Atomic/TList.php | 5 +- .../src/Psalm/Type/Atomic/TNonEmptyList.php | 5 +- .../psalm/stubs/CoreGenericAttributes.phpstub | 13 + .../psalm/stubs/CoreGenericClasses.phpstub | 1 - .../psalm/stubs/CoreGenericFunctions.phpstub | 145 ++- vendor/vimeo/psalm/stubs/Php82.phpstub | 12 - .../psalm/stubs/extensions/mongodb.phpstub | 274 +++++- .../vimeo/psalm/stubs/extensions/pdo.phpstub | 10 + vendor/vimeo/psalm/stubs/phpparser.phpstub | 18 + 239 files changed, 5659 insertions(+), 2712 deletions(-) create mode 100644 vendor/doctrine/deprecations/phpstan.neon create mode 100644 vendor/doctrine/deprecations/psalm.xml create mode 100644 vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php create mode 100644 vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php create mode 100644 vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php create mode 100644 vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php create mode 100644 vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php create mode 100644 vendor/symfony/console/Descriptor/ReStructuredTextDescriptor.php create mode 100644 vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php create mode 100644 vendor/vimeo/psalm/src/Psalm/Internal/Cache.php create mode 100644 vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Client/Progress/LegacyProgress.php create mode 100644 vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Client/Progress/Progress.php create mode 100644 vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Client/Progress/ProgressInterface.php create mode 100644 vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/PathMapper.php create mode 100644 vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/SprintfReturnTypeProvider.php delete mode 100644 vendor/vimeo/psalm/src/Psalm/Internal/Provider/StatementsVolatileCache.php create mode 100644 vendor/vimeo/psalm/src/Psalm/Internal/Type/ClosedInheritanceToUnion.php create mode 100644 vendor/vimeo/psalm/stubs/CoreGenericAttributes.phpstub diff --git a/composer.lock b/composer.lock index 5d70e659..6e6585b0 100644 --- a/composer.lock +++ b/composer.lock @@ -481,25 +481,29 @@ }, { "name": "doctrine/deprecations", - "version": "v1.0.0", + "version": "v1.1.1", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de" + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", - "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", "shasum": "" }, "require": { - "php": "^7.1|^8.0" + "php": "^7.1 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^9", - "phpunit/phpunit": "^7.5|^8.5|^9.5", - "psr/log": "^1|^2|^3" + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" }, "suggest": { "psr/log": "Allows logging deprecations via PSR-3 logger implementation" @@ -518,9 +522,9 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/v1.0.0" + "source": "https://github.com/doctrine/deprecations/tree/v1.1.1" }, - "time": "2022-05-02T15:47:09+00:00" + "time": "2023-06-03T09:27:29+00:00" }, { "name": "felixfbecker/advanced-json-rpc", @@ -782,16 +786,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.15.5", + "version": "v4.16.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e" + "reference": "19526a33fb561ef417e822e85f08a00db4059c17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/11e2663a5bc9db5d714eedb4277ee300403b4a9e", - "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", + "reference": "19526a33fb561ef417e822e85f08a00db4059c17", "shasum": "" }, "require": { @@ -832,9 +836,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.5" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" }, - "time": "2023-05-19T20:20:00+00:00" + "time": "2023-06-25T14:52:30+00:00" }, { "name": "phan/phan", @@ -1027,16 +1031,16 @@ }, { "name": "phpdocumentor/type-resolver", - "version": "1.7.1", + "version": "1.7.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "dfc078e8af9c99210337325ff5aa152872c98714" + "reference": "b2fe4d22a5426f38e014855322200b97b5362c0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/dfc078e8af9c99210337325ff5aa152872c98714", - "reference": "dfc078e8af9c99210337325ff5aa152872c98714", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b2fe4d22a5426f38e014855322200b97b5362c0d", + "reference": "b2fe4d22a5426f38e014855322200b97b5362c0d", "shasum": "" }, "require": { @@ -1079,9 +1083,9 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.1" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.2" }, - "time": "2023-03-27T19:02:04+00:00" + "time": "2023-05-30T18:13:47+00:00" }, { "name": "phpstan/extension-installer", @@ -1129,22 +1133,23 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.21.0", + "version": "1.23.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "6df62b08faef4f899772bc7c3bbabb93d2b7a21c" + "reference": "a2b24135c35852b348894320d47b3902a94bc494" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/6df62b08faef4f899772bc7c3bbabb93d2b7a21c", - "reference": "6df62b08faef4f899772bc7c3bbabb93d2b7a21c", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a2b24135c35852b348894320d47b3902a94bc494", + "reference": "a2b24135c35852b348894320d47b3902a94bc494", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { + "doctrine/annotations": "^2.0", "nikic/php-parser": "^4.15", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/extension-installer": "^1.0", @@ -1169,22 +1174,22 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.21.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.23.0" }, - "time": "2023-05-17T13:13:44+00:00" + "time": "2023-07-23T22:17:56+00:00" }, { "name": "phpstan/phpstan", - "version": "1.10.15", + "version": "1.10.26", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "762c4dac4da6f8756eebb80e528c3a47855da9bd" + "reference": "5d660cbb7e1b89253a47147ae44044f49832351f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/762c4dac4da6f8756eebb80e528c3a47855da9bd", - "reference": "762c4dac4da6f8756eebb80e528c3a47855da9bd", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/5d660cbb7e1b89253a47147ae44044f49832351f", + "reference": "5d660cbb7e1b89253a47147ae44044f49832351f", "shasum": "" }, "require": { @@ -1233,7 +1238,7 @@ "type": "tidelift" } ], - "time": "2023-05-09T15:28:01+00:00" + "time": "2023-07-19T12:44:37+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", @@ -1471,16 +1476,16 @@ }, { "name": "spatie/array-to-xml", - "version": "3.1.6", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/spatie/array-to-xml.git", - "reference": "e210b98957987c755372465be105d32113f339a4" + "reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/e210b98957987c755372465be105d32113f339a4", - "reference": "e210b98957987c755372465be105d32113f339a4", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/f9ab39c808500c347d5a8b6b13310bd5221e39e7", + "reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7", "shasum": "" }, "require": { @@ -1518,7 +1523,7 @@ "xml" ], "support": { - "source": "https://github.com/spatie/array-to-xml/tree/3.1.6" + "source": "https://github.com/spatie/array-to-xml/tree/3.2.0" }, "funding": [ { @@ -1530,27 +1535,27 @@ "type": "github" } ], - "time": "2023-05-11T14:04:07+00:00" + "time": "2023-07-19T18:30:26+00:00" }, { "name": "symfony/console", - "version": "v6.2.11", + "version": "v6.3.2", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "5aa03db8ef0a5457c316ec580e69562d97734c77" + "reference": "aa5d64ad3f63f2e48964fc81ee45cb318a723898" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/5aa03db8ef0a5457c316ec580e69562d97734c77", - "reference": "5aa03db8ef0a5457c316ec580e69562d97734c77", + "url": "https://api.github.com/repos/symfony/console/zipball/aa5d64ad3f63f2e48964fc81ee45cb318a723898", + "reference": "aa5d64ad3f63f2e48964fc81ee45cb318a723898", "shasum": "" }, "require": { "php": ">=8.1", - "symfony/deprecation-contracts": "^2.1|^3", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2|^3", + "symfony/service-contracts": "^2.5|^3", "symfony/string": "^5.4|^6.0" }, "conflict": { @@ -1572,12 +1577,6 @@ "symfony/process": "^5.4|^6.0", "symfony/var-dumper": "^5.4|^6.0" }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, "type": "library", "autoload": { "psr-4": { @@ -1610,7 +1609,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.2.11" + "source": "https://github.com/symfony/console/tree/v6.3.2" }, "funding": [ { @@ -1626,20 +1625,20 @@ "type": "tidelift" } ], - "time": "2023-05-26T08:16:21+00:00" + "time": "2023-07-19T20:17:28+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.2.1", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e" + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", - "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", "shasum": "" }, "require": { @@ -1648,7 +1647,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -1677,7 +1676,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" }, "funding": [ { @@ -1693,20 +1692,20 @@ "type": "tidelift" } ], - "time": "2023-03-01T10:25:55+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/filesystem", - "version": "v6.2.10", + "version": "v6.3.1", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "fd588debf7d1bc16a2c84b4b3b71145d9946b894" + "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/fd588debf7d1bc16a2c84b4b3b71145d9946b894", - "reference": "fd588debf7d1bc16a2c84b4b3b71145d9946b894", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", + "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", "shasum": "" }, "require": { @@ -1740,7 +1739,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.2.10" + "source": "https://github.com/symfony/filesystem/tree/v6.3.1" }, "funding": [ { @@ -1756,7 +1755,7 @@ "type": "tidelift" } ], - "time": "2023-04-18T13:46:08+00:00" + "time": "2023-06-01T08:30:39+00:00" }, { "name": "symfony/polyfill-ctype", @@ -2173,16 +2172,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.2.1", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "a8c9cedf55f314f3a186041d19537303766df09a" + "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/a8c9cedf55f314f3a186041d19537303766df09a", - "reference": "a8c9cedf55f314f3a186041d19537303766df09a", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", + "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", "shasum": "" }, "require": { @@ -2192,13 +2191,10 @@ "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -2238,7 +2234,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.2.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.3.0" }, "funding": [ { @@ -2254,20 +2250,20 @@ "type": "tidelift" } ], - "time": "2023-03-01T10:32:47+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/string", - "version": "v6.2.8", + "version": "v6.3.2", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef" + "reference": "53d1a83225002635bca3482fcbf963001313fb68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/193e83bbd6617d6b2151c37fff10fa7168ebddef", - "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef", + "url": "https://api.github.com/repos/symfony/string/zipball/53d1a83225002635bca3482fcbf963001313fb68", + "reference": "53d1a83225002635bca3482fcbf963001313fb68", "shasum": "" }, "require": { @@ -2278,13 +2274,13 @@ "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": "<2.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { "symfony/error-handler": "^5.4|^6.0", "symfony/http-client": "^5.4|^6.0", "symfony/intl": "^6.2", - "symfony/translation-contracts": "^2.0|^3.0", + "symfony/translation-contracts": "^2.5|^3.0", "symfony/var-exporter": "^5.4|^6.0" }, "type": "library", @@ -2324,7 +2320,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.2.8" + "source": "https://github.com/symfony/string/tree/v6.3.2" }, "funding": [ { @@ -2340,7 +2336,7 @@ "type": "tidelift" } ], - "time": "2023-03-20T16:06:02+00:00" + "time": "2023-07-05T08:41:27+00:00" }, { "name": "tysonandre/var_representation_polyfill", @@ -2406,16 +2402,16 @@ }, { "name": "vimeo/psalm", - "version": "5.12.0", + "version": "5.14.1", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "f90118cdeacd0088e7215e64c0c99ceca819e176" + "reference": "b9d355e0829c397b9b3b47d0c0ed042a8a70284d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/f90118cdeacd0088e7215e64c0c99ceca819e176", - "reference": "f90118cdeacd0088e7215e64c0c99ceca819e176", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/b9d355e0829c397b9b3b47d0c0ed042a8a70284d", + "reference": "b9d355e0829c397b9b3b47d0c0ed042a8a70284d", "shasum": "" }, "require": { @@ -2436,8 +2432,8 @@ "felixfbecker/language-server-protocol": "^1.5.2", "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1", "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.14", - "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0", + "nikic/php-parser": "^4.16", + "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", "sebastian/diff": "^4.0 || ^5.0", "spatie/array-to-xml": "^2.17.0 || ^3.0", "symfony/console": "^4.1.6 || ^5.0 || ^6.0", @@ -2506,9 +2502,9 @@ ], "support": { "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/5.12.0" + "source": "https://github.com/vimeo/psalm/tree/5.14.1" }, - "time": "2023-05-22T21:19:03+00:00" + "time": "2023-08-01T05:16:55+00:00" }, { "name": "webmozart/assert", diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index b453d2e1..a3b81d46 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -441,31 +441,35 @@ }, { "name": "doctrine/deprecations", - "version": "v1.0.0", - "version_normalized": "1.0.0.0", + "version": "v1.1.1", + "version_normalized": "1.1.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de" + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", - "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", "shasum": "" }, "require": { - "php": "^7.1|^8.0" + "php": "^7.1 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^9", - "phpunit/phpunit": "^7.5|^8.5|^9.5", - "psr/log": "^1|^2|^3" + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" }, "suggest": { "psr/log": "Allows logging deprecations via PSR-3 logger implementation" }, - "time": "2022-05-02T15:47:09+00:00", + "time": "2023-06-03T09:27:29+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -481,7 +485,7 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/v1.0.0" + "source": "https://github.com/doctrine/deprecations/tree/v1.1.1" }, "install-path": "../doctrine/deprecations" }, @@ -760,17 +764,17 @@ }, { "name": "nikic/php-parser", - "version": "v4.15.5", - "version_normalized": "4.15.5.0", + "version": "v4.16.0", + "version_normalized": "4.16.0.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e" + "reference": "19526a33fb561ef417e822e85f08a00db4059c17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/11e2663a5bc9db5d714eedb4277ee300403b4a9e", - "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", + "reference": "19526a33fb561ef417e822e85f08a00db4059c17", "shasum": "" }, "require": { @@ -781,7 +785,7 @@ "ircmaxell/php-yacc": "^0.0.7", "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" }, - "time": "2023-05-19T20:20:00+00:00", + "time": "2023-06-25T14:52:30+00:00", "bin": [ "bin/php-parse" ], @@ -813,7 +817,7 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.5" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" }, "install-path": "../nikic/php-parser" }, @@ -1017,17 +1021,17 @@ }, { "name": "phpdocumentor/type-resolver", - "version": "1.7.1", - "version_normalized": "1.7.1.0", + "version": "1.7.2", + "version_normalized": "1.7.2.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "dfc078e8af9c99210337325ff5aa152872c98714" + "reference": "b2fe4d22a5426f38e014855322200b97b5362c0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/dfc078e8af9c99210337325ff5aa152872c98714", - "reference": "dfc078e8af9c99210337325ff5aa152872c98714", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b2fe4d22a5426f38e014855322200b97b5362c0d", + "reference": "b2fe4d22a5426f38e014855322200b97b5362c0d", "shasum": "" }, "require": { @@ -1046,7 +1050,7 @@ "rector/rector": "^0.13.9", "vimeo/psalm": "^4.25" }, - "time": "2023-03-27T19:02:04+00:00", + "time": "2023-05-30T18:13:47+00:00", "type": "library", "extra": { "branch-alias": { @@ -1072,7 +1076,7 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.1" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.2" }, "install-path": "../phpdocumentor/type-resolver" }, @@ -1125,23 +1129,24 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.21.0", - "version_normalized": "1.21.0.0", + "version": "1.23.0", + "version_normalized": "1.23.0.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "6df62b08faef4f899772bc7c3bbabb93d2b7a21c" + "reference": "a2b24135c35852b348894320d47b3902a94bc494" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/6df62b08faef4f899772bc7c3bbabb93d2b7a21c", - "reference": "6df62b08faef4f899772bc7c3bbabb93d2b7a21c", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a2b24135c35852b348894320d47b3902a94bc494", + "reference": "a2b24135c35852b348894320d47b3902a94bc494", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { + "doctrine/annotations": "^2.0", "nikic/php-parser": "^4.15", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/extension-installer": "^1.0", @@ -1151,7 +1156,7 @@ "phpunit/phpunit": "^9.5", "symfony/process": "^5.2" }, - "time": "2023-05-17T13:13:44+00:00", + "time": "2023-07-23T22:17:56+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1168,23 +1173,23 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.21.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.23.0" }, "install-path": "../phpstan/phpdoc-parser" }, { "name": "phpstan/phpstan", - "version": "1.10.15", - "version_normalized": "1.10.15.0", + "version": "1.10.26", + "version_normalized": "1.10.26.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "762c4dac4da6f8756eebb80e528c3a47855da9bd" + "reference": "5d660cbb7e1b89253a47147ae44044f49832351f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/762c4dac4da6f8756eebb80e528c3a47855da9bd", - "reference": "762c4dac4da6f8756eebb80e528c3a47855da9bd", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/5d660cbb7e1b89253a47147ae44044f49832351f", + "reference": "5d660cbb7e1b89253a47147ae44044f49832351f", "shasum": "" }, "require": { @@ -1193,7 +1198,7 @@ "conflict": { "phpstan/phpstan-shim": "*" }, - "time": "2023-05-09T15:28:01+00:00", + "time": "2023-07-19T12:44:37+00:00", "bin": [ "phpstan", "phpstan.phar" @@ -1538,17 +1543,17 @@ }, { "name": "spatie/array-to-xml", - "version": "3.1.6", - "version_normalized": "3.1.6.0", + "version": "3.2.0", + "version_normalized": "3.2.0.0", "source": { "type": "git", "url": "https://github.com/spatie/array-to-xml.git", - "reference": "e210b98957987c755372465be105d32113f339a4" + "reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/e210b98957987c755372465be105d32113f339a4", - "reference": "e210b98957987c755372465be105d32113f339a4", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/f9ab39c808500c347d5a8b6b13310bd5221e39e7", + "reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7", "shasum": "" }, "require": { @@ -1560,7 +1565,7 @@ "pestphp/pest": "^1.21", "spatie/pest-plugin-snapshots": "^1.1" }, - "time": "2023-05-11T14:04:07+00:00", + "time": "2023-07-19T18:30:26+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1588,7 +1593,7 @@ "xml" ], "support": { - "source": "https://github.com/spatie/array-to-xml/tree/3.1.6" + "source": "https://github.com/spatie/array-to-xml/tree/3.2.0" }, "funding": [ { @@ -1604,24 +1609,24 @@ }, { "name": "symfony/console", - "version": "v6.2.11", - "version_normalized": "6.2.11.0", + "version": "v6.3.2", + "version_normalized": "6.3.2.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "5aa03db8ef0a5457c316ec580e69562d97734c77" + "reference": "aa5d64ad3f63f2e48964fc81ee45cb318a723898" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/5aa03db8ef0a5457c316ec580e69562d97734c77", - "reference": "5aa03db8ef0a5457c316ec580e69562d97734c77", + "url": "https://api.github.com/repos/symfony/console/zipball/aa5d64ad3f63f2e48964fc81ee45cb318a723898", + "reference": "aa5d64ad3f63f2e48964fc81ee45cb318a723898", "shasum": "" }, "require": { "php": ">=8.1", - "symfony/deprecation-contracts": "^2.1|^3", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2|^3", + "symfony/service-contracts": "^2.5|^3", "symfony/string": "^5.4|^6.0" }, "conflict": { @@ -1643,13 +1648,7 @@ "symfony/process": "^5.4|^6.0", "symfony/var-dumper": "^5.4|^6.0" }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "time": "2023-05-26T08:16:21+00:00", + "time": "2023-07-19T20:17:28+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1683,7 +1682,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.2.11" + "source": "https://github.com/symfony/console/tree/v6.3.2" }, "funding": [ { @@ -1703,27 +1702,27 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.2.1", - "version_normalized": "3.2.1.0", + "version": "v3.3.0", + "version_normalized": "3.3.0.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e" + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", - "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", "shasum": "" }, "require": { "php": ">=8.1" }, - "time": "2023-03-01T10:25:55+00:00", + "time": "2023-05-23T14:45:45+00:00", "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -1753,7 +1752,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" }, "funding": [ { @@ -1773,17 +1772,17 @@ }, { "name": "symfony/filesystem", - "version": "v6.2.10", - "version_normalized": "6.2.10.0", + "version": "v6.3.1", + "version_normalized": "6.3.1.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "fd588debf7d1bc16a2c84b4b3b71145d9946b894" + "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/fd588debf7d1bc16a2c84b4b3b71145d9946b894", - "reference": "fd588debf7d1bc16a2c84b4b3b71145d9946b894", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", + "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", "shasum": "" }, "require": { @@ -1791,7 +1790,7 @@ "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, - "time": "2023-04-18T13:46:08+00:00", + "time": "2023-06-01T08:30:39+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1819,7 +1818,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.2.10" + "source": "https://github.com/symfony/filesystem/tree/v6.3.1" }, "funding": [ { @@ -2267,17 +2266,17 @@ }, { "name": "symfony/service-contracts", - "version": "v3.2.1", - "version_normalized": "3.2.1.0", + "version": "v3.3.0", + "version_normalized": "3.3.0.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "a8c9cedf55f314f3a186041d19537303766df09a" + "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/a8c9cedf55f314f3a186041d19537303766df09a", - "reference": "a8c9cedf55f314f3a186041d19537303766df09a", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", + "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", "shasum": "" }, "require": { @@ -2287,14 +2286,11 @@ "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, - "time": "2023-03-01T10:32:47+00:00", + "time": "2023-05-23T14:45:45+00:00", "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -2335,7 +2331,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.2.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.3.0" }, "funding": [ { @@ -2355,17 +2351,17 @@ }, { "name": "symfony/string", - "version": "v6.2.8", - "version_normalized": "6.2.8.0", + "version": "v6.3.2", + "version_normalized": "6.3.2.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef" + "reference": "53d1a83225002635bca3482fcbf963001313fb68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/193e83bbd6617d6b2151c37fff10fa7168ebddef", - "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef", + "url": "https://api.github.com/repos/symfony/string/zipball/53d1a83225002635bca3482fcbf963001313fb68", + "reference": "53d1a83225002635bca3482fcbf963001313fb68", "shasum": "" }, "require": { @@ -2376,16 +2372,16 @@ "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": "<2.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { "symfony/error-handler": "^5.4|^6.0", "symfony/http-client": "^5.4|^6.0", "symfony/intl": "^6.2", - "symfony/translation-contracts": "^2.0|^3.0", + "symfony/translation-contracts": "^2.5|^3.0", "symfony/var-exporter": "^5.4|^6.0" }, - "time": "2023-03-20T16:06:02+00:00", + "time": "2023-07-05T08:41:27+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2424,7 +2420,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.2.8" + "source": "https://github.com/symfony/string/tree/v6.3.2" }, "funding": [ { @@ -2509,17 +2505,17 @@ }, { "name": "vimeo/psalm", - "version": "5.12.0", - "version_normalized": "5.12.0.0", + "version": "5.14.1", + "version_normalized": "5.14.1.0", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "f90118cdeacd0088e7215e64c0c99ceca819e176" + "reference": "b9d355e0829c397b9b3b47d0c0ed042a8a70284d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/f90118cdeacd0088e7215e64c0c99ceca819e176", - "reference": "f90118cdeacd0088e7215e64c0c99ceca819e176", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/b9d355e0829c397b9b3b47d0c0ed042a8a70284d", + "reference": "b9d355e0829c397b9b3b47d0c0ed042a8a70284d", "shasum": "" }, "require": { @@ -2540,8 +2536,8 @@ "felixfbecker/language-server-protocol": "^1.5.2", "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1", "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.14", - "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0", + "nikic/php-parser": "^4.16", + "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", "sebastian/diff": "^4.0 || ^5.0", "spatie/array-to-xml": "^2.17.0 || ^3.0", "symfony/console": "^4.1.6 || ^5.0 || ^6.0", @@ -2570,7 +2566,7 @@ "ext-curl": "In order to send data to shepherd", "ext-igbinary": "^2.0.5 is required, used to serialize caching data" }, - "time": "2023-05-22T21:19:03+00:00", + "time": "2023-08-01T05:16:55+00:00", "bin": [ "psalm", "psalm-language-server", @@ -2612,7 +2608,7 @@ ], "support": { "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/5.12.0" + "source": "https://github.com/vimeo/psalm/tree/5.14.1" }, "install-path": "../vimeo/psalm" }, diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 2059fa41..3d504b02 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -65,9 +65,9 @@ 'dev_requirement' => true, ), 'doctrine/deprecations' => array( - 'pretty_version' => 'v1.0.0', - 'version' => '1.0.0.0', - 'reference' => '0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de', + 'pretty_version' => 'v1.1.1', + 'version' => '1.1.1.0', + 'reference' => '612a3ee5ab0d5dd97b7cf3874a6efe24325efac3', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/deprecations', 'aliases' => array(), @@ -128,9 +128,9 @@ 'dev_requirement' => true, ), 'nikic/php-parser' => array( - 'pretty_version' => 'v4.15.5', - 'version' => '4.15.5.0', - 'reference' => '11e2663a5bc9db5d714eedb4277ee300403b4a9e', + 'pretty_version' => 'v4.16.0', + 'version' => '4.16.0.0', + 'reference' => '19526a33fb561ef417e822e85f08a00db4059c17', 'type' => 'library', 'install_path' => __DIR__ . '/../nikic/php-parser', 'aliases' => array(), @@ -164,9 +164,9 @@ 'dev_requirement' => true, ), 'phpdocumentor/type-resolver' => array( - 'pretty_version' => '1.7.1', - 'version' => '1.7.1.0', - 'reference' => 'dfc078e8af9c99210337325ff5aa152872c98714', + 'pretty_version' => '1.7.2', + 'version' => '1.7.2.0', + 'reference' => 'b2fe4d22a5426f38e014855322200b97b5362c0d', 'type' => 'library', 'install_path' => __DIR__ . '/../phpdocumentor/type-resolver', 'aliases' => array(), @@ -182,18 +182,18 @@ 'dev_requirement' => true, ), 'phpstan/phpdoc-parser' => array( - 'pretty_version' => '1.21.0', - 'version' => '1.21.0.0', - 'reference' => '6df62b08faef4f899772bc7c3bbabb93d2b7a21c', + 'pretty_version' => '1.23.0', + 'version' => '1.23.0.0', + 'reference' => 'a2b24135c35852b348894320d47b3902a94bc494', 'type' => 'library', 'install_path' => __DIR__ . '/../phpstan/phpdoc-parser', 'aliases' => array(), 'dev_requirement' => true, ), 'phpstan/phpstan' => array( - 'pretty_version' => '1.10.15', - 'version' => '1.10.15.0', - 'reference' => '762c4dac4da6f8756eebb80e528c3a47855da9bd', + 'pretty_version' => '1.10.26', + 'version' => '1.10.26.0', + 'reference' => '5d660cbb7e1b89253a47147ae44044f49832351f', 'type' => 'library', 'install_path' => __DIR__ . '/../phpstan/phpstan', 'aliases' => array(), @@ -211,7 +211,7 @@ 'psalm/psalm' => array( 'dev_requirement' => true, 'provided' => array( - 0 => '5.12.0', + 0 => '5.14.1', ), ), 'psr/container' => array( @@ -257,36 +257,36 @@ 'dev_requirement' => true, ), 'spatie/array-to-xml' => array( - 'pretty_version' => '3.1.6', - 'version' => '3.1.6.0', - 'reference' => 'e210b98957987c755372465be105d32113f339a4', + 'pretty_version' => '3.2.0', + 'version' => '3.2.0.0', + 'reference' => 'f9ab39c808500c347d5a8b6b13310bd5221e39e7', 'type' => 'library', 'install_path' => __DIR__ . '/../spatie/array-to-xml', 'aliases' => array(), 'dev_requirement' => true, ), 'symfony/console' => array( - 'pretty_version' => 'v6.2.11', - 'version' => '6.2.11.0', - 'reference' => '5aa03db8ef0a5457c316ec580e69562d97734c77', + 'pretty_version' => 'v6.3.2', + 'version' => '6.3.2.0', + 'reference' => 'aa5d64ad3f63f2e48964fc81ee45cb318a723898', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/console', 'aliases' => array(), 'dev_requirement' => true, ), 'symfony/deprecation-contracts' => array( - 'pretty_version' => 'v3.2.1', - 'version' => '3.2.1.0', - 'reference' => 'e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e', + 'pretty_version' => 'v3.3.0', + 'version' => '3.3.0.0', + 'reference' => '7c3aff79d10325257a001fcf92d991f24fc967cf', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), 'dev_requirement' => true, ), 'symfony/filesystem' => array( - 'pretty_version' => 'v6.2.10', - 'version' => '6.2.10.0', - 'reference' => 'fd588debf7d1bc16a2c84b4b3b71145d9946b894', + 'pretty_version' => 'v6.3.1', + 'version' => '6.3.1.0', + 'reference' => 'edd36776956f2a6fcf577edb5b05eb0e3bdc52ae', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/filesystem', 'aliases' => array(), @@ -338,18 +338,18 @@ 'dev_requirement' => true, ), 'symfony/service-contracts' => array( - 'pretty_version' => 'v3.2.1', - 'version' => '3.2.1.0', - 'reference' => 'a8c9cedf55f314f3a186041d19537303766df09a', + 'pretty_version' => 'v3.3.0', + 'version' => '3.3.0.0', + 'reference' => '40da9cc13ec349d9e4966ce18b5fbcd724ab10a4', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/service-contracts', 'aliases' => array(), 'dev_requirement' => true, ), 'symfony/string' => array( - 'pretty_version' => 'v6.2.8', - 'version' => '6.2.8.0', - 'reference' => '193e83bbd6617d6b2151c37fff10fa7168ebddef', + 'pretty_version' => 'v6.3.2', + 'version' => '6.3.2.0', + 'reference' => '53d1a83225002635bca3482fcbf963001313fb68', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/string', 'aliases' => array(), @@ -365,9 +365,9 @@ 'dev_requirement' => true, ), 'vimeo/psalm' => array( - 'pretty_version' => '5.12.0', - 'version' => '5.12.0.0', - 'reference' => 'f90118cdeacd0088e7215e64c0c99ceca819e176', + 'pretty_version' => '5.14.1', + 'version' => '5.14.1.0', + 'reference' => 'b9d355e0829c397b9b3b47d0c0ed042a8a70284d', 'type' => 'library', 'install_path' => __DIR__ . '/../vimeo/psalm', 'aliases' => array(), diff --git a/vendor/doctrine/deprecations/README.md b/vendor/doctrine/deprecations/README.md index 22f0cced..93caf83f 100644 --- a/vendor/doctrine/deprecations/README.md +++ b/vendor/doctrine/deprecations/README.md @@ -19,13 +19,16 @@ Enable Doctrine deprecations to be sent to a PSR3 logger: ``` Enable Doctrine deprecations to be sent as `@trigger_error($message, E_USER_DEPRECATED)` -messages. +messages by setting the `DOCTRINE_DEPRECATIONS` environment variable to `trigger`. +Alternatively, call: ```php \Doctrine\Deprecations\Deprecation::enableWithTriggerError(); ``` -If you only want to enable deprecation tracking, without logging or calling `trigger_error` then call: +If you only want to enable deprecation tracking, without logging or calling `trigger_error` +then set the `DOCTRINE_DEPRECATIONS` environment variable to `track`. +Alternatively, call: ```php \Doctrine\Deprecations\Deprecation::enableTrackingDeprecations(); diff --git a/vendor/doctrine/deprecations/composer.json b/vendor/doctrine/deprecations/composer.json index c79e38cd..f8319f9a 100644 --- a/vendor/doctrine/deprecations/composer.json +++ b/vendor/doctrine/deprecations/composer.json @@ -1,22 +1,28 @@ { "name": "doctrine/deprecations", - "type": "library", "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", - "homepage": "https://www.doctrine-project.org/", "license": "MIT", + "type": "library", + "homepage": "https://www.doctrine-project.org/", "require": { - "php": "^7.1|^8.0" + "php": "^7.1 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^7.5|^8.5|^9.5", - "psr/log": "^1|^2|^3", - "doctrine/coding-standard": "^9" + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" }, "suggest": { "psr/log": "Allows logging deprecations via PSR-3 logger implementation" }, "autoload": { - "psr-4": {"Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations"} + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } }, "autoload-dev": { "psr-4": { diff --git a/vendor/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php b/vendor/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php index 1029372f..07cb43b6 100644 --- a/vendor/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php +++ b/vendor/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php @@ -8,6 +8,7 @@ use Psr\Log\LoggerInterface; use function array_key_exists; use function array_reduce; +use function assert; use function debug_backtrace; use function sprintf; use function strpos; @@ -46,8 +47,8 @@ class Deprecation private const TYPE_TRIGGER_ERROR = 2; private const TYPE_PSR_LOGGER = 4; - /** @var int */ - private static $type = self::TYPE_NONE; + /** @var int-mask-of|null */ + private static $type; /** @var LoggerInterface|null */ private static $logger; @@ -56,6 +57,9 @@ class Deprecation private static $ignoredPackages = []; /** @var array */ + private static $triggeredDeprecations = []; + + /** @var array */ private static $ignoredLinks = []; /** @var bool */ @@ -68,21 +72,27 @@ class Deprecation * deprecation. It is additionally used to de-duplicate the trigger of the * same deprecation during a request. * - * @param mixed $args + * @param float|int|string $args */ public static function trigger(string $package, string $link, string $message, ...$args): void { - if (self::$type === self::TYPE_NONE) { + $type = self::$type ?? self::getTypeFromEnv(); + + if ($type === self::TYPE_NONE) { return; } - if (array_key_exists($link, self::$ignoredLinks)) { - self::$ignoredLinks[$link]++; - } else { - self::$ignoredLinks[$link] = 1; + if (isset(self::$ignoredLinks[$link])) { + return; } - if (self::$deduplication === true && self::$ignoredLinks[$link] > 1) { + if (array_key_exists($link, self::$triggeredDeprecations)) { + self::$triggeredDeprecations[$link]++; + } else { + self::$triggeredDeprecations[$link] = 1; + } + + if (self::$deduplication === true && self::$triggeredDeprecations[$link] > 1) { return; } @@ -114,18 +124,20 @@ class Deprecation * deprecation tracking is enabled even during deduplication, because it * needs to call {@link debug_backtrace()} * - * @param mixed $args + * @param float|int|string $args */ public static function triggerIfCalledFromOutside(string $package, string $link, string $message, ...$args): void { - if (self::$type === self::TYPE_NONE) { + $type = self::$type ?? self::getTypeFromEnv(); + + if ($type === self::TYPE_NONE) { return; } $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); // first check that the caller is not from a tests folder, in which case we always let deprecations pass - if (strpos($backtrace[1]['file'], DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR) === false) { + if (isset($backtrace[1]['file'], $backtrace[0]['file']) && strpos($backtrace[1]['file'], DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR) === false) { $path = DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $package . DIRECTORY_SEPARATOR; if (strpos($backtrace[0]['file'], $path) === false) { @@ -137,13 +149,17 @@ class Deprecation } } - if (array_key_exists($link, self::$ignoredLinks)) { - self::$ignoredLinks[$link]++; - } else { - self::$ignoredLinks[$link] = 1; + if (isset(self::$ignoredLinks[$link])) { + return; } - if (self::$deduplication === true && self::$ignoredLinks[$link] > 1) { + if (array_key_exists($link, self::$triggeredDeprecations)) { + self::$triggeredDeprecations[$link]++; + } else { + self::$triggeredDeprecations[$link] = 1; + } + + if (self::$deduplication === true && self::$triggeredDeprecations[$link] > 1) { return; } @@ -157,31 +173,35 @@ class Deprecation } /** - * @param array $backtrace + * @param list $backtrace */ private static function delegateTriggerToBackend(string $message, array $backtrace, string $link, string $package): void { - if ((self::$type & self::TYPE_PSR_LOGGER) > 0) { + $type = self::$type ?? self::getTypeFromEnv(); + + if (($type & self::TYPE_PSR_LOGGER) > 0) { $context = [ - 'file' => $backtrace[0]['file'], - 'line' => $backtrace[0]['line'], + 'file' => $backtrace[0]['file'] ?? null, + 'line' => $backtrace[0]['line'] ?? null, 'package' => $package, 'link' => $link, ]; + assert(self::$logger !== null); + self::$logger->notice($message, $context); } - if (! ((self::$type & self::TYPE_TRIGGER_ERROR) > 0)) { + if (! (($type & self::TYPE_TRIGGER_ERROR) > 0)) { return; } $message .= sprintf( ' (%s:%d called by %s:%d, %s, package %s)', - self::basename($backtrace[0]['file']), - $backtrace[0]['line'], - self::basename($backtrace[1]['file']), - $backtrace[1]['line'], + self::basename($backtrace[0]['file'] ?? 'native code'), + $backtrace[0]['line'] ?? 0, + self::basename($backtrace[1]['file'] ?? 'native code'), + $backtrace[1]['line'] ?? 0, $link, $package ); @@ -205,16 +225,19 @@ class Deprecation public static function enableTrackingDeprecations(): void { + self::$type = self::$type ?? 0; self::$type |= self::TYPE_TRACK_DEPRECATIONS; } public static function enableWithTriggerError(): void { + self::$type = self::$type ?? 0; self::$type |= self::TYPE_TRIGGER_ERROR; } public static function enableWithPsrLogger(LoggerInterface $logger): void { + self::$type = self::$type ?? 0; self::$type |= self::TYPE_PSR_LOGGER; self::$logger = $logger; } @@ -229,9 +252,10 @@ class Deprecation self::$type = self::TYPE_NONE; self::$logger = null; self::$deduplication = true; + self::$ignoredLinks = []; - foreach (self::$ignoredLinks as $link => $count) { - self::$ignoredLinks[$link] = 0; + foreach (self::$triggeredDeprecations as $link => $count) { + self::$triggeredDeprecations[$link] = 0; } } @@ -243,13 +267,13 @@ class Deprecation public static function ignoreDeprecations(string ...$links): void { foreach ($links as $link) { - self::$ignoredLinks[$link] = 0; + self::$ignoredLinks[$link] = true; } } public static function getUniqueTriggeredDeprecationsCount(): int { - return array_reduce(self::$ignoredLinks, static function (int $carry, int $count) { + return array_reduce(self::$triggeredDeprecations, static function (int $carry, int $count) { return $carry + $count; }, 0); } @@ -261,6 +285,28 @@ class Deprecation */ public static function getTriggeredDeprecations(): array { - return self::$ignoredLinks; + return self::$triggeredDeprecations; + } + + /** + * @return int-mask-of + */ + private static function getTypeFromEnv(): int + { + switch ($_SERVER['DOCTRINE_DEPRECATIONS'] ?? $_ENV['DOCTRINE_DEPRECATIONS'] ?? null) { + case 'trigger': + self::$type = self::TYPE_TRIGGER_ERROR; + break; + + case 'track': + self::$type = self::TYPE_TRACK_DEPRECATIONS; + break; + + default: + self::$type = self::TYPE_NONE; + break; + } + + return self::$type; } } diff --git a/vendor/doctrine/deprecations/phpstan.neon b/vendor/doctrine/deprecations/phpstan.neon new file mode 100644 index 00000000..4ee286b8 --- /dev/null +++ b/vendor/doctrine/deprecations/phpstan.neon @@ -0,0 +1,9 @@ +parameters: + level: 6 + paths: + - lib + - tests + +includes: + - vendor/phpstan/phpstan-phpunit/extension.neon + - vendor/phpstan/phpstan-phpunit/rules.neon diff --git a/vendor/doctrine/deprecations/psalm.xml b/vendor/doctrine/deprecations/psalm.xml new file mode 100644 index 00000000..ad76e32e --- /dev/null +++ b/vendor/doctrine/deprecations/psalm.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/nikic/php-parser/grammar/php5.y b/vendor/nikic/php-parser/grammar/php5.y index 2920dead..77e4fb7e 100644 --- a/vendor/nikic/php-parser/grammar/php5.y +++ b/vendor/nikic/php-parser/grammar/php5.y @@ -1008,7 +1008,7 @@ array_pair: | expr { $$ = Expr\ArrayItem[$1, null, false]; } | expr T_DOUBLE_ARROW ampersand variable { $$ = Expr\ArrayItem[$4, $1, true]; } | ampersand variable { $$ = Expr\ArrayItem[$2, null, true]; } - | T_ELLIPSIS expr { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; } + | T_ELLIPSIS expr { $$ = new Expr\ArrayItem($2, null, false, attributes(), true); } ; encaps_list: diff --git a/vendor/nikic/php-parser/grammar/php7.y b/vendor/nikic/php-parser/grammar/php7.y index fc7862c3..2d65d484 100644 --- a/vendor/nikic/php-parser/grammar/php7.y +++ b/vendor/nikic/php-parser/grammar/php7.y @@ -1194,7 +1194,7 @@ array_pair: | expr T_DOUBLE_ARROW expr { $$ = Expr\ArrayItem[$3, $1, false]; } | expr T_DOUBLE_ARROW ampersand variable { $$ = Expr\ArrayItem[$4, $1, true]; } | expr T_DOUBLE_ARROW list_expr { $$ = Expr\ArrayItem[$3, $1, false]; } - | T_ELLIPSIS expr { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; } + | T_ELLIPSIS expr { $$ = new Expr\ArrayItem($2, null, false, attributes(), true); } | /* empty */ { $$ = null; } ; diff --git a/vendor/nikic/php-parser/lib/PhpParser/Node/Name.php b/vendor/nikic/php-parser/lib/PhpParser/Node/Name.php index 17bd1c0f..f0a564ff 100644 --- a/vendor/nikic/php-parser/lib/PhpParser/Node/Name.php +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Name.php @@ -6,7 +6,10 @@ use PhpParser\NodeAbstract; class Name extends NodeAbstract { - /** @var string[] Parts of the name */ + /** + * @var string[] Parts of the name + * @deprecated Use getParts() instead + */ public $parts; private static $specialClassNames = [ @@ -30,6 +33,15 @@ class Name extends NodeAbstract return ['parts']; } + /** + * Get parts of name (split by the namespace separator). + * + * @return string[] Parts of name + */ + public function getParts(): array { + return $this->parts; + } + /** * Gets the first part of the name, i.e. everything before the first namespace separator. * diff --git a/vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php b/vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php index 351db9ed..a4306710 100644 --- a/vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php +++ b/vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php @@ -2627,7 +2627,7 @@ class Php5 extends \PhpParser\ParserAbstract $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, 552 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, true); }, 553 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; diff --git a/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php b/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php index c6b9abd0..cede4419 100644 --- a/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php +++ b/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php @@ -2818,7 +2818,7 @@ class Php7 extends \PhpParser\ParserAbstract $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 592 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, true); }, 593 => function ($stackPos) { $this->semValue = null; diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/StringValue.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/StringValue.php index c22eff07..10b1f516 100644 --- a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/StringValue.php +++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/StringValue.php @@ -15,7 +15,7 @@ namespace phpDocumentor\Reflection\PseudoTypes; use phpDocumentor\Reflection\PseudoType; use phpDocumentor\Reflection\Type; -use phpDocumentor\Reflection\Types\Float_; +use phpDocumentor\Reflection\Types\String_; use function sprintf; @@ -36,7 +36,7 @@ class StringValue implements PseudoType public function underlyingType(): Type { - return new Float_(); + return new String_(); } public function __toString(): string diff --git a/vendor/phpstan/phpdoc-parser/README.md b/vendor/phpstan/phpdoc-parser/README.md index 2d2f6c82..3b321b22 100644 --- a/vendor/phpstan/phpdoc-parser/README.md +++ b/vendor/phpstan/phpdoc-parser/README.md @@ -15,6 +15,8 @@ For the complete list of supported PHPDoc features check out PHPStan documentati * [PHPDoc Types](https://phpstan.org/writing-php-code/phpdoc-types) (list of PHPDoc types) * [phpdoc-parser API Reference](https://phpstan.github.io/phpdoc-parser/namespace-PHPStan.PhpDocParser.html) with all the AST node types etc. +This parser also supports parsing [Doctrine Annotations](https://github.com/doctrine/annotations). The AST nodes live in the [PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine namespace](https://phpstan.github.io/phpdoc-parser/namespace-PHPStan.PhpDocParser.Ast.PhpDoc.Doctrine.html). The support needs to be turned on by setting `bool $parseDoctrineAnnotations` to `true` in `Lexer` and `PhpDocParser` class constructors. + ## Installation ``` @@ -91,12 +93,13 @@ $phpDocNode = $phpDocParser->parse($tokens); // PhpDocNode $cloningTraverser = new NodeTraverser([new CloningVisitor()]); /** @var PhpDocNode $newPhpDocNode */ -$printer = new Printer(); [$newPhpDocNode] = $cloningTraverser->traverse([$phpDocNode]); // change something in $newPhpDocNode $newPhpDocNode->getParamTagValues()[0]->type = new IdentifierTypeNode('Ipsum'); +// print changed PHPDoc +$printer = new Printer(); $newPhpDoc = $printer->printFormatPreserving($newPhpDocNode, $phpDocNode, $tokens); echo $newPhpDoc; // '/** @param Ipsum $a */' ``` diff --git a/vendor/phpstan/phpdoc-parser/composer.json b/vendor/phpstan/phpdoc-parser/composer.json index 30b879b7..f1c648e5 100644 --- a/vendor/phpstan/phpdoc-parser/composer.json +++ b/vendor/phpstan/phpdoc-parser/composer.json @@ -6,6 +6,7 @@ "php": "^7.2 || ^8.0" }, "require-dev": { + "doctrine/annotations": "^2.0", "nikic/php-parser": "^4.15", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/extension-installer": "^1.0", diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php b/vendor/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php index 32d1a04a..2b9c10ec 100644 --- a/vendor/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php +++ b/vendor/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php @@ -8,7 +8,7 @@ namespace PHPStan\PhpDocParser\Ast; * Copyright (c) 2011, Nikita Popov * All rights reserved. */ -abstract class AbstractNodeVisitor implements NodeVisitor +abstract class AbstractNodeVisitor implements NodeVisitor // phpcs:ignore SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming.SuperfluousPrefix { public function beforeTraverse(array $nodes): ?array diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php b/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php new file mode 100644 index 00000000..3a93f5aa --- /dev/null +++ b/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php @@ -0,0 +1,35 @@ + */ + public $arguments; + + /** + * @param list $arguments + */ + public function __construct(string $name, array $arguments) + { + $this->name = $name; + $this->arguments = $arguments; + } + + public function __toString(): string + { + $arguments = implode(', ', $this->arguments); + return $this->name . '(' . $arguments . ')'; + } + +} diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php b/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php new file mode 100644 index 00000000..f30812cf --- /dev/null +++ b/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php @@ -0,0 +1,43 @@ +key = $key; + $this->value = $value; + } + + + public function __toString(): string + { + if ($this->key === null) { + return (string) $this->value; + } + + return $this->key . '=' . $this->value; + } + +} diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php b/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php new file mode 100644 index 00000000..e740567d --- /dev/null +++ b/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php @@ -0,0 +1,32 @@ + */ + public $items; + + /** + * @param list $items + */ + public function __construct(array $items) + { + $this->items = $items; + } + + public function __toString(): string + { + $items = implode(', ', $this->items); + + return '{' . $items . '}'; + } + +} diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php b/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php new file mode 100644 index 00000000..d2dbf2b6 --- /dev/null +++ b/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php @@ -0,0 +1,47 @@ +key = $key; + $this->value = $value; + } + + + public function __toString(): string + { + if ($this->key === null) { + return (string) $this->value; + } + + return $this->key . '=' . $this->value; + } + +} diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php b/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php new file mode 100644 index 00000000..84f7b18b --- /dev/null +++ b/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php @@ -0,0 +1,36 @@ +annotation = $annotation; + $this->description = $description; + } + + + public function __toString(): string + { + return trim("{$this->annotation} {$this->description}"); + } + +} diff --git a/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php b/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php index 856cc3f1..d20746fc 100644 --- a/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php +++ b/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php @@ -3,6 +3,7 @@ namespace PHPStan\PhpDocParser\Ast\PhpDoc; use PHPStan\PhpDocParser\Ast\NodeAttributes; +use PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineTagValueNode; use function trim; class PhpDocTagNode implements PhpDocChildNode @@ -25,6 +26,10 @@ class PhpDocTagNode implements PhpDocChildNode public function __toString(): string { + if ($this->value instanceof DoctrineTagValueNode) { + return (string) $this->value; + } + return trim("{$this->name} {$this->value}"); } diff --git a/vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php b/vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php index ccae6bef..86ae8239 100644 --- a/vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php +++ b/vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php @@ -30,23 +30,24 @@ class Lexer public const TOKEN_OPEN_PHPDOC = 15; public const TOKEN_CLOSE_PHPDOC = 16; public const TOKEN_PHPDOC_TAG = 17; - public const TOKEN_FLOAT = 18; - public const TOKEN_INTEGER = 19; - public const TOKEN_SINGLE_QUOTED_STRING = 20; - public const TOKEN_DOUBLE_QUOTED_STRING = 21; - public const TOKEN_IDENTIFIER = 22; - public const TOKEN_THIS_VARIABLE = 23; - public const TOKEN_VARIABLE = 24; - public const TOKEN_HORIZONTAL_WS = 25; - public const TOKEN_PHPDOC_EOL = 26; - public const TOKEN_OTHER = 27; - public const TOKEN_END = 28; - public const TOKEN_COLON = 29; - public const TOKEN_WILDCARD = 30; - public const TOKEN_OPEN_CURLY_BRACKET = 31; - public const TOKEN_CLOSE_CURLY_BRACKET = 32; - public const TOKEN_NEGATED = 33; - public const TOKEN_ARROW = 34; + public const TOKEN_DOCTRINE_TAG = 18; + public const TOKEN_FLOAT = 19; + public const TOKEN_INTEGER = 20; + public const TOKEN_SINGLE_QUOTED_STRING = 21; + public const TOKEN_DOUBLE_QUOTED_STRING = 22; + public const TOKEN_IDENTIFIER = 23; + public const TOKEN_THIS_VARIABLE = 24; + public const TOKEN_VARIABLE = 25; + public const TOKEN_HORIZONTAL_WS = 26; + public const TOKEN_PHPDOC_EOL = 27; + public const TOKEN_OTHER = 28; + public const TOKEN_END = 29; + public const TOKEN_COLON = 30; + public const TOKEN_WILDCARD = 31; + public const TOKEN_OPEN_CURLY_BRACKET = 32; + public const TOKEN_CLOSE_CURLY_BRACKET = 33; + public const TOKEN_NEGATED = 34; + public const TOKEN_ARROW = 35; public const TOKEN_LABELS = [ self::TOKEN_REFERENCE => '\'&\'', @@ -72,6 +73,7 @@ class Lexer self::TOKEN_OPEN_PHPDOC => '\'/**\'', self::TOKEN_CLOSE_PHPDOC => '\'*/\'', self::TOKEN_PHPDOC_TAG => 'TOKEN_PHPDOC_TAG', + self::TOKEN_DOCTRINE_TAG => 'TOKEN_DOCTRINE_TAG', self::TOKEN_PHPDOC_EOL => 'TOKEN_PHPDOC_EOL', self::TOKEN_FLOAT => 'TOKEN_FLOAT', self::TOKEN_INTEGER => 'TOKEN_INTEGER', @@ -90,9 +92,17 @@ class Lexer public const TYPE_OFFSET = 1; public const LINE_OFFSET = 2; + /** @var bool */ + private $parseDoctrineAnnotations; + /** @var string|null */ private $regexp; + public function __construct(bool $parseDoctrineAnnotations = false) + { + $this->parseDoctrineAnnotations = $parseDoctrineAnnotations; + } + /** * @return list */ @@ -160,17 +170,21 @@ class Lexer self::TOKEN_PHPDOC_TAG => '@(?:[a-z][a-z0-9-\\\\]+:)?[a-z][a-z0-9-\\\\]*+', self::TOKEN_PHPDOC_EOL => '\\r?+\\n[\\x09\\x20]*+(?:\\*(?!/)\\x20?+)?', - self::TOKEN_FLOAT => '(?:-?[0-9]++(_[0-9]++)*\\.[0-9]*(_[0-9]++)*+(?:e-?[0-9]++(_[0-9]++)*)?)|(?:-?[0-9]*+(_[0-9]++)*\\.[0-9]++(_[0-9]++)*(?:e-?[0-9]++(_[0-9]++)*)?)|(?:-?[0-9]++(_[0-9]++)*e-?[0-9]++(_[0-9]++)*)', - self::TOKEN_INTEGER => '-?(?:(?:0b[0-1]++(_[0-1]++)*)|(?:0o[0-7]++(_[0-7]++)*)|(?:0x[0-9a-f]++(_[0-9a-f]++)*)|(?:[0-9]++(_[0-9]++)*))', + self::TOKEN_FLOAT => '[+\-]?(?:(?:[0-9]++(_[0-9]++)*\\.[0-9]*+(_[0-9]++)*(?:e[+\-]?[0-9]++(_[0-9]++)*)?)|(?:[0-9]*+(_[0-9]++)*\\.[0-9]++(_[0-9]++)*(?:e[+\-]?[0-9]++(_[0-9]++)*)?)|(?:[0-9]++(_[0-9]++)*e[+\-]?[0-9]++(_[0-9]++)*))', + self::TOKEN_INTEGER => '[+\-]?(?:(?:0b[0-1]++(_[0-1]++)*)|(?:0o[0-7]++(_[0-7]++)*)|(?:0x[0-9a-f]++(_[0-9a-f]++)*)|(?:[0-9]++(_[0-9]++)*))', self::TOKEN_SINGLE_QUOTED_STRING => '\'(?:\\\\[^\\r\\n]|[^\'\\r\\n\\\\])*+\'', self::TOKEN_DOUBLE_QUOTED_STRING => '"(?:\\\\[^\\r\\n]|[^"\\r\\n\\\\])*+"', self::TOKEN_WILDCARD => '\\*', - - // anything but TOKEN_CLOSE_PHPDOC or TOKEN_HORIZONTAL_WS or TOKEN_EOL - self::TOKEN_OTHER => '(?:(?!\\*/)[^\\s])++', ]; + if ($this->parseDoctrineAnnotations) { + $patterns[self::TOKEN_DOCTRINE_TAG] = '@[a-z_\\\\][a-z0-9_\:\\\\]*[a-z_][a-z0-9_]*'; + } + + // anything but TOKEN_CLOSE_PHPDOC or TOKEN_HORIZONTAL_WS or TOKEN_EOL + $patterns[self::TOKEN_OTHER] = '(?:(?!\\*/)[^\\s])++'; + foreach ($patterns as $type => &$pattern) { $pattern = '(?:' . $pattern . ')(*MARK:' . $type . ')'; } diff --git a/vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php b/vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php index b6db8a2c..f97c260c 100644 --- a/vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php +++ b/vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php @@ -245,22 +245,14 @@ class ConstExprParser */ private function enrichWithAttributes(TokenIterator $tokens, Ast\ConstExpr\ConstExprNode $node, int $startLine, int $startIndex): Ast\ConstExpr\ConstExprNode { - $endLine = $tokens->currentTokenLine(); - $endIndex = $tokens->currentTokenIndex(); if ($this->useLinesAttributes) { $node->setAttribute(Ast\Attribute::START_LINE, $startLine); - $node->setAttribute(Ast\Attribute::END_LINE, $endLine); + $node->setAttribute(Ast\Attribute::END_LINE, $tokens->currentTokenLine()); } if ($this->useIndexAttributes) { - $tokensArray = $tokens->getTokens(); - $endIndex--; - if ($tokensArray[$endIndex][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) { - $endIndex--; - } - $node->setAttribute(Ast\Attribute::START_INDEX, $startIndex); - $node->setAttribute(Ast\Attribute::END_INDEX, $endIndex); + $node->setAttribute(Ast\Attribute::END_INDEX, $tokens->endIndexOfLastRelevantToken()); } return $node; diff --git a/vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php b/vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php index d3eed465..7b56e3bd 100644 --- a/vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php +++ b/vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php @@ -2,15 +2,25 @@ namespace PHPStan\PhpDocParser\Parser; +use LogicException; use PHPStan\PhpDocParser\Ast; +use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode; +use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode; +use PHPStan\PhpDocParser\Ast\ConstExpr\ConstFetchNode; +use PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\PhpDocParser\Lexer\Lexer; use PHPStan\ShouldNotHappenException; use function array_key_exists; use function array_values; use function count; +use function rtrim; +use function str_replace; use function trim; +/** + * @phpstan-import-type ValueType from Doctrine\DoctrineArgument as DoctrineValueType + */ class PhpDocParser { @@ -31,12 +41,18 @@ class PhpDocParser /** @var bool */ private $preserveTypeAliasesWithInvalidTypes; + /** @var bool */ + private $parseDoctrineAnnotations; + /** @var bool */ private $useLinesAttributes; /** @var bool */ private $useIndexAttributes; + /** @var bool */ + private $textBetweenTagsBelongsToDescription; + /** * @param array{lines?: bool, indexes?: bool} $usedAttributes */ @@ -45,15 +61,19 @@ class PhpDocParser ConstExprParser $constantExprParser, bool $requireWhitespaceBeforeDescription = false, bool $preserveTypeAliasesWithInvalidTypes = false, - array $usedAttributes = [] + array $usedAttributes = [], + bool $parseDoctrineAnnotations = false, + bool $textBetweenTagsBelongsToDescription = false ) { $this->typeParser = $typeParser; $this->constantExprParser = $constantExprParser; $this->requireWhitespaceBeforeDescription = $requireWhitespaceBeforeDescription; $this->preserveTypeAliasesWithInvalidTypes = $preserveTypeAliasesWithInvalidTypes; + $this->parseDoctrineAnnotations = $parseDoctrineAnnotations; $this->useLinesAttributes = $usedAttributes['lines'] ?? false; $this->useIndexAttributes = $usedAttributes['indexes'] ?? false; + $this->textBetweenTagsBelongsToDescription = $textBetweenTagsBelongsToDescription; } @@ -64,10 +84,44 @@ class PhpDocParser $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)) { + if ($this->parseDoctrineAnnotations) { + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { + $lastChild = $this->parseChild($tokens); + $children[] = $lastChild; + while (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { + if ( + $lastChild instanceof Ast\PhpDoc\PhpDocTagNode + && ( + $lastChild->value instanceof Doctrine\DoctrineTagValueNode + || $lastChild->value instanceof Ast\PhpDoc\GenericTagValueNode + ) + ) { + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { + break; + } + $lastChild = $this->parseChild($tokens); + $children[] = $lastChild; + continue; + } + + if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL)) { + break; + } + if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { + break; + } + + $lastChild = $this->parseChild($tokens); + $children[] = $lastChild; + } + } + } else { + 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); + } } } @@ -105,6 +159,7 @@ class PhpDocParser } + /** @phpstan-impure */ private function parseChild(TokenIterator $tokens): Ast\PhpDoc\PhpDocChildNode { if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG)) { @@ -113,6 +168,26 @@ class PhpDocParser return $this->enrichWithAttributes($tokens, $this->parseTag($tokens), $startLine, $startIndex); } + if ($tokens->isCurrentTokenType(Lexer::TOKEN_DOCTRINE_TAG)) { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + $tag = $tokens->currentTokenValue(); + $tokens->next(); + + $tagStartLine = $tokens->currentTokenLine(); + $tagStartIndex = $tokens->currentTokenIndex(); + + return $this->enrichWithAttributes($tokens, new Ast\PhpDoc\PhpDocTagNode( + $tag, + $this->enrichWithAttributes( + $tokens, + $this->parseDoctrineTagValue($tokens, $tag), + $tagStartLine, + $tagStartIndex + ) + ), $startLine, $startIndex); + } + $startLine = $tokens->currentTokenLine(); $startIndex = $tokens->currentTokenIndex(); $text = $this->parseText($tokens); @@ -127,27 +202,14 @@ class PhpDocParser */ private function enrichWithAttributes(TokenIterator $tokens, Ast\Node $tag, int $startLine, int $startIndex): Ast\Node { - $endLine = $tokens->currentTokenLine(); - $endIndex = $tokens->currentTokenIndex(); - if ($this->useLinesAttributes) { $tag->setAttribute(Ast\Attribute::START_LINE, $startLine); - $tag->setAttribute(Ast\Attribute::END_LINE, $endLine); + $tag->setAttribute(Ast\Attribute::END_LINE, $tokens->currentTokenLine()); } if ($this->useIndexAttributes) { - $tokensArray = $tokens->getTokens(); - if ($tokensArray[$endIndex][Lexer::TYPE_OFFSET] === Lexer::TOKEN_CLOSE_PHPDOC) { - $endIndex--; - if ($tokensArray[$endIndex][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) { - $endIndex--; - } - } elseif ($tokensArray[$endIndex][Lexer::TYPE_OFFSET] === Lexer::TOKEN_PHPDOC_EOL) { - $endIndex--; - } - $tag->setAttribute(Ast\Attribute::START_INDEX, $startIndex); - $tag->setAttribute(Ast\Attribute::END_INDEX, $endIndex); + $tag->setAttribute(Ast\Attribute::END_INDEX, $tokens->endIndexOfLastRelevantToken()); } return $tag; @@ -158,29 +220,144 @@ class PhpDocParser { $text = ''; - while (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) { - $text .= $tokens->getSkippedHorizontalWhiteSpaceIfAny() . $tokens->joinUntil(Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END); + $endTokens = [Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END]; + if ($this->textBetweenTagsBelongsToDescription) { + $endTokens = [Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END]; + } + $savepoint = false; + + // if the next token is EOL, everything below is skipped and empty string is returned + while ($this->textBetweenTagsBelongsToDescription || !$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) { + $tmpText = $tokens->getSkippedHorizontalWhiteSpaceIfAny() . $tokens->joinUntil(Lexer::TOKEN_PHPDOC_EOL, ...$endTokens); + $text .= $tmpText; + + // stop if we're not at EOL - meaning it's the end of PHPDoc if (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) { break; } + if ($this->textBetweenTagsBelongsToDescription) { + if (!$savepoint) { + $tokens->pushSavePoint(); + $savepoint = true; + } elseif ($tmpText !== '') { + $tokens->dropSavePoint(); + $tokens->pushSavePoint(); + } + } + $tokens->pushSavePoint(); $tokens->next(); - if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END)) { + // if we're at EOL, check what's next + // if next is a PHPDoc tag, EOL, or end of PHPDoc, stop + if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG, ...$endTokens)) { $tokens->rollback(); break; } + // otherwise if the next is text, continue building the description string + $tokens->dropSavePoint(); - $text .= "\n"; + $text .= $tokens->getDetectedNewline() ?? "\n"; + } + + if ($savepoint) { + $tokens->rollback(); + $text = rtrim($text, $tokens->getDetectedNewline() ?? "\n"); } return new Ast\PhpDoc\PhpDocTextNode(trim($text, " \t")); } + private function parseOptionalDescriptionAfterDoctrineTag(TokenIterator $tokens): string + { + $text = ''; + + $endTokens = [Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END]; + if ($this->textBetweenTagsBelongsToDescription) { + $endTokens = [Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END]; + } + + $savepoint = false; + + // if the next token is EOL, everything below is skipped and empty string is returned + while ($this->textBetweenTagsBelongsToDescription || !$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) { + $tmpText = $tokens->getSkippedHorizontalWhiteSpaceIfAny() . $tokens->joinUntil(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG, Lexer::TOKEN_PHPDOC_EOL, ...$endTokens); + $text .= $tmpText; + + // stop if we're not at EOL - meaning it's the end of PHPDoc + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) { + if (!$tokens->isPrecededByHorizontalWhitespace()) { + return trim($text . $this->parseText($tokens)->text, " \t"); + } + if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG)) { + $tokens->pushSavePoint(); + $child = $this->parseChild($tokens); + if ($child instanceof Ast\PhpDoc\PhpDocTagNode) { + if ( + $child->value instanceof Ast\PhpDoc\GenericTagValueNode + || $child->value instanceof Doctrine\DoctrineTagValueNode + ) { + $tokens->rollback(); + break; + } + if ($child->value instanceof Ast\PhpDoc\InvalidTagValueNode) { + $tokens->rollback(); + $tokens->pushSavePoint(); + $tokens->next(); + if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { + $tokens->rollback(); + break; + } + $tokens->rollback(); + return trim($text . $this->parseText($tokens)->text, " \t"); + } + } + + $tokens->rollback(); + return trim($text . $this->parseText($tokens)->text, " \t"); + } + break; + } + + if ($this->textBetweenTagsBelongsToDescription) { + if (!$savepoint) { + $tokens->pushSavePoint(); + $savepoint = true; + } elseif ($tmpText !== '') { + $tokens->dropSavePoint(); + $tokens->pushSavePoint(); + } + } + + $tokens->pushSavePoint(); + $tokens->next(); + + // if we're at EOL, check what's next + // if next is a PHPDoc tag, EOL, or end of PHPDoc, stop + if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG, ...$endTokens)) { + $tokens->rollback(); + break; + } + + // otherwise if the next is text, continue building the description string + + $tokens->dropSavePoint(); + $text .= $tokens->getDetectedNewline() ?? "\n"; + } + + if ($savepoint) { + $tokens->rollback(); + $text = rtrim($text, $tokens->getDetectedNewline() ?? "\n"); + } + + return trim($text, " \t"); + } + + public function parseTag(TokenIterator $tokens): Ast\PhpDoc\PhpDocTagNode { $tag = $tokens->currentTokenValue(); @@ -312,7 +489,17 @@ class PhpDocParser break; default: + if ($this->parseDoctrineAnnotations) { + if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { + $tagValue = $this->parseDoctrineTagValue($tokens, $tag); + } else { + $tagValue = new Ast\PhpDoc\GenericTagValueNode($this->parseOptionalDescriptionAfterDoctrineTag($tokens)); + } + break; + } + $tagValue = new Ast\PhpDoc\GenericTagValueNode($this->parseOptionalDescription($tokens)); + break; } @@ -327,6 +514,297 @@ class PhpDocParser } + private function parseDoctrineTagValue(TokenIterator $tokens, string $tag): Ast\PhpDoc\PhpDocTagValueNode + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + return new Doctrine\DoctrineTagValueNode( + $this->enrichWithAttributes( + $tokens, + new Doctrine\DoctrineAnnotation($tag, $this->parseDoctrineArguments($tokens, false)), + $startLine, + $startIndex + ), + $this->parseOptionalDescriptionAfterDoctrineTag($tokens) + ); + } + + + /** + * @return list + */ + private function parseDoctrineArguments(TokenIterator $tokens, bool $deep): array + { + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { + return []; + } + + if (!$deep) { + $tokens->addEndOfLineToSkippedTokens(); + } + + $arguments = []; + + try { + $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES); + + do { + if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) { + break; + } + $arguments[] = $this->parseDoctrineArgument($tokens); + } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)); + } finally { + if (!$deep) { + $tokens->removeEndOfLineFromSkippedTokens(); + } + } + + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES); + + return $arguments; + } + + + private function parseDoctrineArgument(TokenIterator $tokens): Doctrine\DoctrineArgument + { + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + return $this->enrichWithAttributes( + $tokens, + new Doctrine\DoctrineArgument(null, $this->parseDoctrineArgumentValue($tokens)), + $startLine, + $startIndex + ); + } + + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + try { + $tokens->pushSavePoint(); + $currentValue = $tokens->currentTokenValue(); + $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); + + $key = $this->enrichWithAttributes( + $tokens, + new IdentifierTypeNode($currentValue), + $startLine, + $startIndex + ); + $tokens->consumeTokenType(Lexer::TOKEN_EQUAL); + + $value = $this->parseDoctrineArgumentValue($tokens); + + $tokens->dropSavePoint(); + + return $this->enrichWithAttributes( + $tokens, + new Doctrine\DoctrineArgument($key, $value), + $startLine, + $startIndex + ); + } catch (ParserException $e) { + $tokens->rollback(); + + return $this->enrichWithAttributes( + $tokens, + new Doctrine\DoctrineArgument(null, $this->parseDoctrineArgumentValue($tokens)), + $startLine, + $startIndex + ); + } + } + + + /** + * @return DoctrineValueType + */ + private function parseDoctrineArgumentValue(TokenIterator $tokens) + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG)) { + $name = $tokens->currentTokenValue(); + $tokens->next(); + + return $this->enrichWithAttributes( + $tokens, + new Doctrine\DoctrineAnnotation($name, $this->parseDoctrineArguments($tokens, true)), + $startLine, + $startIndex + ); + } + + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET)) { + $items = []; + do { + if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) { + break; + } + $items[] = $this->parseDoctrineArrayItem($tokens); + } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)); + + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET); + + return $this->enrichWithAttributes( + $tokens, + new Doctrine\DoctrineArray($items), + $startLine, + $startIndex + ); + } + + $currentTokenValue = $tokens->currentTokenValue(); + $tokens->pushSavePoint(); // because of ConstFetchNode + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) { + $identifier = $this->enrichWithAttributes( + $tokens, + new Ast\Type\IdentifierTypeNode($currentTokenValue), + $startLine, + $startIndex + ); + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) { + $tokens->dropSavePoint(); + return $identifier; + } + + $tokens->rollback(); // because of ConstFetchNode + } else { + $tokens->dropSavePoint(); // because of ConstFetchNode + } + + $exception = new ParserException( + $tokens->currentTokenValue(), + $tokens->currentTokenType(), + $tokens->currentTokenOffset(), + Lexer::TOKEN_IDENTIFIER, + null, + $tokens->currentTokenLine() + ); + + try { + $constExpr = $this->constantExprParser->parse($tokens, true); + if ($constExpr instanceof Ast\ConstExpr\ConstExprArrayNode) { + throw $exception; + } + + return $constExpr; + } catch (LogicException $e) { + throw $exception; + } + } + + + private function parseDoctrineArrayItem(TokenIterator $tokens): Doctrine\DoctrineArrayItem + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + try { + $tokens->pushSavePoint(); + + $key = $this->parseDoctrineArrayKey($tokens); + if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL)) { + if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_COLON)) { + $tokens->consumeTokenType(Lexer::TOKEN_EQUAL); // will throw exception + } + } + + $value = $this->parseDoctrineArgumentValue($tokens); + + $tokens->dropSavePoint(); + + return $this->enrichWithAttributes( + $tokens, + new Doctrine\DoctrineArrayItem($key, $value), + $startLine, + $startIndex + ); + } catch (ParserException $e) { + $tokens->rollback(); + + return $this->enrichWithAttributes( + $tokens, + new Doctrine\DoctrineArrayItem(null, $this->parseDoctrineArgumentValue($tokens)), + $startLine, + $startIndex + ); + } + } + + + /** + * @return ConstExprIntegerNode|ConstExprStringNode|IdentifierTypeNode|ConstFetchNode + */ + private function parseDoctrineArrayKey(TokenIterator $tokens) + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_INTEGER)) { + $key = new Ast\ConstExpr\ConstExprIntegerNode(str_replace('_', '', $tokens->currentTokenValue())); + $tokens->next(); + + } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) { + $key = new Ast\ConstExpr\QuoteAwareConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\QuoteAwareConstExprStringNode::SINGLE_QUOTED); + $tokens->next(); + + } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) { + $key = new Ast\ConstExpr\QuoteAwareConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\QuoteAwareConstExprStringNode::DOUBLE_QUOTED); + + $tokens->next(); + + } else { + $currentTokenValue = $tokens->currentTokenValue(); + $tokens->pushSavePoint(); // because of ConstFetchNode + if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) { + $tokens->dropSavePoint(); + throw new ParserException( + $tokens->currentTokenValue(), + $tokens->currentTokenType(), + $tokens->currentTokenOffset(), + Lexer::TOKEN_IDENTIFIER, + null, + $tokens->currentTokenLine() + ); + } + + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) { + $tokens->dropSavePoint(); + + return $this->enrichWithAttributes( + $tokens, + new IdentifierTypeNode($currentTokenValue), + $startLine, + $startIndex + ); + } + + $tokens->rollback(); + $constExpr = $this->constantExprParser->parse($tokens, true); + if (!$constExpr instanceof Ast\ConstExpr\ConstFetchNode) { + throw new ParserException( + $tokens->currentTokenValue(), + $tokens->currentTokenType(), + $tokens->currentTokenOffset(), + Lexer::TOKEN_IDENTIFIER, + null, + $tokens->currentTokenLine() + ); + } + + return $constExpr; + } + + return $this->enrichWithAttributes($tokens, $key, $startLine, $startIndex); + } + + /** * @return Ast\PhpDoc\ParamTagValueNode|Ast\PhpDoc\TypelessParamTagValueNode */ diff --git a/vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php b/vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php index 4348ab79..9be7593d 100644 --- a/vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php +++ b/vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php @@ -9,6 +9,7 @@ use function assert; use function count; use function in_array; use function strlen; +use function substr; class TokenIterator { @@ -22,6 +23,12 @@ class TokenIterator /** @var int[] */ private $savePoints = []; + /** @var list */ + private $skippedTokenTypes = [Lexer::TOKEN_HORIZONTAL_WS]; + + /** @var string|null */ + private $newline = null; + /** * @param list $tokens */ @@ -30,11 +37,7 @@ class TokenIterator $this->tokens = $tokens; $this->index = $index; - if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== Lexer::TOKEN_HORIZONTAL_WS) { - return; - } - - $this->index++; + $this->skipIrrelevantTokens(); } @@ -103,6 +106,21 @@ class TokenIterator } + public function endIndexOfLastRelevantToken(): int + { + $endIndex = $this->currentTokenIndex(); + $endIndex--; + while (in_array($this->tokens[$endIndex][Lexer::TYPE_OFFSET], $this->skippedTokenTypes, true)) { + if (!isset($this->tokens[$endIndex - 1])) { + break; + } + $endIndex--; + } + + return $endIndex; + } + + public function isCurrentTokenValue(string $tokenValue): bool { return $this->tokens[$this->index][Lexer::VALUE_OFFSET] === $tokenValue; @@ -130,13 +148,14 @@ class TokenIterator $this->throwError($tokenType); } - $this->index++; - - if (($this->tokens[$this->index][Lexer::TYPE_OFFSET] ?? -1) !== Lexer::TOKEN_HORIZONTAL_WS) { - return; + if ($tokenType === Lexer::TOKEN_PHPDOC_EOL) { + if ($this->newline === null) { + $this->detectNewline(); + } } $this->index++; + $this->skipIrrelevantTokens(); } @@ -150,12 +169,7 @@ class TokenIterator } $this->index++; - - if (($this->tokens[$this->index][Lexer::TYPE_OFFSET] ?? -1) !== Lexer::TOKEN_HORIZONTAL_WS) { - return; - } - - $this->index++; + $this->skipIrrelevantTokens(); } @@ -167,10 +181,7 @@ class TokenIterator } $this->index++; - - if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) { - $this->index++; - } + $this->skipIrrelevantTokens(); return true; } @@ -183,16 +194,30 @@ class TokenIterator return false; } - $this->index++; - - if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) { - $this->index++; + if ($tokenType === Lexer::TOKEN_PHPDOC_EOL) { + if ($this->newline === null) { + $this->detectNewline(); + } } + $this->index++; + $this->skipIrrelevantTokens(); + return true; } + private function detectNewline(): void + { + $value = $this->currentTokenValue(); + if (substr($value, 0, 2) === "\r\n") { + $this->newline = "\r\n"; + } elseif (substr($value, 0, 1) === "\n") { + $this->newline = "\n"; + } + } + + public function getSkippedHorizontalWhiteSpaceIfAny(): string { if ($this->index > 0 && $this->tokens[$this->index - 1][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) { @@ -217,12 +242,34 @@ class TokenIterator public function next(): void { $this->index++; + $this->skipIrrelevantTokens(); + } - if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== Lexer::TOKEN_HORIZONTAL_WS) { + + private function skipIrrelevantTokens(): void + { + if (!isset($this->tokens[$this->index])) { return; } - $this->index++; + while (in_array($this->tokens[$this->index][Lexer::TYPE_OFFSET], $this->skippedTokenTypes, true)) { + if (!isset($this->tokens[$this->index + 1])) { + break; + } + $this->index++; + } + } + + + public function addEndOfLineToSkippedTokens(): void + { + $this->skippedTokenTypes = [Lexer::TOKEN_HORIZONTAL_WS, Lexer::TOKEN_PHPDOC_EOL]; + } + + + public function removeEndOfLineFromSkippedTokens(): void + { + $this->skippedTokenTypes = [Lexer::TOKEN_HORIZONTAL_WS]; } /** @phpstan-impure */ @@ -319,6 +366,11 @@ class TokenIterator return false; } + public function getDetectedNewline(): ?string + { + return $this->newline; + } + /** * Whether the given position is immediately surrounded by parenthesis. */ diff --git a/vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php b/vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php index 4b429809..645f544b 100644 --- a/vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php +++ b/vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php @@ -70,23 +70,14 @@ class TypeParser */ public function enrichWithAttributes(TokenIterator $tokens, Ast\Node $type, int $startLine, int $startIndex): Ast\Node { - $endLine = $tokens->currentTokenLine(); - $endIndex = $tokens->currentTokenIndex(); - if ($this->useLinesAttributes) { $type->setAttribute(Ast\Attribute::START_LINE, $startLine); - $type->setAttribute(Ast\Attribute::END_LINE, $endLine); + $type->setAttribute(Ast\Attribute::END_LINE, $tokens->currentTokenLine()); } if ($this->useIndexAttributes) { - $tokensArray = $tokens->getTokens(); - $endIndex--; - if ($tokensArray[$endIndex][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) { - $endIndex--; - } - $type->setAttribute(Ast\Attribute::START_INDEX, $startIndex); - $type->setAttribute(Ast\Attribute::END_INDEX, $endIndex); + $type->setAttribute(Ast\Attribute::END_INDEX, $tokens->endIndexOfLastRelevantToken()); } return $type; diff --git a/vendor/phpstan/phpdoc-parser/src/Printer/Printer.php b/vendor/phpstan/phpdoc-parser/src/Printer/Printer.php index bc07d10c..d7feaf91 100644 --- a/vendor/phpstan/phpdoc-parser/src/Printer/Printer.php +++ b/vendor/phpstan/phpdoc-parser/src/Printer/Printer.php @@ -10,6 +10,11 @@ use PHPStan\PhpDocParser\Ast\Node; use PHPStan\PhpDocParser\Ast\PhpDoc\AssertTagMethodValueNode; use PHPStan\PhpDocParser\Ast\PhpDoc\AssertTagPropertyValueNode; use PHPStan\PhpDocParser\Ast\PhpDoc\AssertTagValueNode; +use PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineAnnotation; +use PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineArgument; +use PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineArray; +use PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineArrayItem; +use PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineTagValueNode; use PHPStan\PhpDocParser\Ast\PhpDoc\ExtendsTagValueNode; use PHPStan\PhpDocParser\Ast\PhpDoc\ImplementsTagValueNode; use PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueNode; @@ -95,6 +100,8 @@ final class Printer GenericTypeNode::class . '->genericTypes' => ', ', ConstExprArrayNode::class . '->items' => ', ', MethodTagValueNode::class . '->parameters' => ', ', + DoctrineArray::class . '->items' => ', ', + DoctrineAnnotation::class . '->arguments' => ', ', ]; /** @@ -106,6 +113,8 @@ final class Printer CallableTypeNode::class . '->parameters' => ['(', '', ''], ArrayShapeNode::class . '->items' => ['{', '', ''], ObjectShapeNode::class . '->items' => ['{', '', ''], + DoctrineArray::class . '->items' => ['{', '', ''], + DoctrineAnnotation::class . '->arguments' => ['(', '', ''], ]; /** @var array>> */ @@ -186,6 +195,10 @@ final class Printer return $node->text; } if ($node instanceof PhpDocTagNode) { + if ($node->value instanceof DoctrineTagValueNode) { + return $this->print($node->value); + } + return trim(sprintf('%s %s', $node->name, $this->print($node->value))); } if ($node instanceof PhpDocTagValueNode) { @@ -211,6 +224,18 @@ final class Printer $isOptional = $node->isOptional ? '=' : ''; return trim("{$type}{$isReference}{$isVariadic}{$node->parameterName}") . $isOptional; } + if ($node instanceof DoctrineAnnotation) { + return (string) $node; + } + if ($node instanceof DoctrineArgument) { + return (string) $node; + } + if ($node instanceof DoctrineArray) { + return (string) $node; + } + if ($node instanceof DoctrineArrayItem) { + return (string) $node; + } throw new LogicException(sprintf('Unknown node type %s', get_class($node))); } @@ -491,7 +516,7 @@ final class Printer [$isMultiline, $beforeAsteriskIndent, $afterAsteriskIndent] = $this->isMultiline($tokenIndex, $originalNodes, $originalTokens); if ($insertStr === "\n * ") { - $insertStr = sprintf("\n%s*%s", $beforeAsteriskIndent, $afterAsteriskIndent); + $insertStr = sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent); } foreach ($diff as $i => $diffElem) { @@ -524,7 +549,7 @@ final class Printer } if ($insertNewline) { - $result .= $insertStr . sprintf("\n%s*%s", $beforeAsteriskIndent, $afterAsteriskIndent); + $result .= $insertStr . sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent); } else { $result .= $insertStr; } @@ -534,7 +559,8 @@ final class Printer } $parenthesesNeeded = isset($this->parenthesesListMap[$mapKey]) - && in_array(get_class($newNode), $this->parenthesesListMap[$mapKey], true); + && in_array(get_class($newNode), $this->parenthesesListMap[$mapKey], true) + && !in_array(get_class($originalNode), $this->parenthesesListMap[$mapKey], true); $addParentheses = $parenthesesNeeded && !$originalTokens->hasParentheses($itemStartPos, $itemEndPos); if ($addParentheses) { $result .= '('; @@ -567,7 +593,7 @@ final class Printer $itemEndPos = $tokenIndex - 1; if ($insertNewline) { - $result .= $insertStr . sprintf("\n%s*%s", $beforeAsteriskIndent, $afterAsteriskIndent); + $result .= $insertStr . sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent); } else { $result .= $insertStr; } @@ -636,7 +662,7 @@ final class Printer if (!$first) { $result .= $insertStr; if ($insertNewline) { - $result .= sprintf("\n%s*%s", $beforeAsteriskIndent, $afterAsteriskIndent); + $result .= sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent); } } @@ -777,6 +803,12 @@ final class Printer $mapKey = get_class($node) . '->' . $subNodeName; $parenthesesNeeded = isset($this->parenthesesMap[$mapKey]) && in_array(get_class($subNode), $this->parenthesesMap[$mapKey], true); + + if ($subNode->getAttribute(Attribute::ORIGINAL_NODE) !== null) { + $parenthesesNeeded = $parenthesesNeeded + && !in_array(get_class($subNode->getAttribute(Attribute::ORIGINAL_NODE)), $this->parenthesesMap[$mapKey], true); + } + $addParentheses = $parenthesesNeeded && !$originalTokens->hasParentheses($subStartPos, $subEndPos); if ($addParentheses) { $result .= '('; diff --git a/vendor/phpstan/phpstan/phpstan.phar b/vendor/phpstan/phpstan/phpstan.phar index 3f043c719c2bf287748aa89742f06c0273027c0e..7f766674bc7116e22b9bb64897ab1e4beaa2274f 100755 GIT binary patch delta 474985 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

;){h1=Yx^0+0NI=o+L|( zgZQm9ukJ5?%bkGVV(A=+mKKu(QP>5$#GOeZgvQKHeUI`o+i{2B|12={pJM!f7<|mY z4@fkVCPlP-`#v4_Z5p^i9CGTys$L6@j^=JP<_Dy}@iLnrhCcjjJoo$&|H4*3Na6rY;Y`HupM1|DP0S3i&uP(B zYn}LM(g|jCnN(?Bb(*xIMn$G@3RLoMMUI6O4W+$c>H_|Zue=xhH~ELGjOA2#`^CAlUso&ATNklzxXgd zykdzMeh%K`nZ6Uga)p;4&u2Pu8lyo2lhac3!JuZ;uUG{~X+2hY(ZrZ1-ib0LA->bd zc}62HI+MkN#3G18yLffvH%>Me%{jg4a0=eqt*H+`xclD_w^%{YsPY<~B2@T^ouwc`v}omX?DURY!<> zy?Maw=i&)UYS>WZ_KCnkMbwr8+Bj0w-3BlvEN)73YEs{ayp*wo7}{m*6Z*c98O^9? zO0LQd#2H1APC(C$&aW$;eYF9#4?Mj+lRmE-$~_TZOWkO)=GR}=aHJC=;4{7Y(eTsy zk?=NQdQ9yovhZwX;g%$scM3mE}z@l02<6_QKT8S$WD;Q^7BLs zIx$k@kG3!>!+G3a&|t@6CaWxBb72U&4dSzF7CWlK!5t*WPh+)BOX(HRbY%LFfQAD{ zB#s&y+iOs-K}o%a^h&`-e3;P@g7~HPI-xbLi6`k5IqaS>dYc&62Ue%IUCDVxCHq{(Q8%7EF%z%f2 z+pq7T!X2VhI}SpVd#&W7{?_rkPE}J15P7%GWV)*|e}p0RPz4K`_XcR-wQC zS_3>;)?k4hlgvmXDG{P?-z_&lk7jI3419Qgl4J=nepOp9?h9r0^jPljI5o{~CMwW$ zn77j{em?YyI};07YKDew44BP=PHk+$_qyec#cj6^j2hH6sJbQ27cNV!>Z-9q8c*Q581>&5VzGFof=JB%W#6z{*2&8g4)l zXk=q?6?+!aN(f!!K*Jh^kghTTAF;h&^{5xz4Cc|;gwpja@o=0d+3sS;_UnvjOrhAViFzINKAVVBAr=(*!+)b7Nt7XGr^k=G5wZb4jtD}6s_%yk=t?K$1+Us`4pHX5uQWpzKUNaf?1|Edw1?3c&4{kyUkaJxCCnOMS830BK2_SV zhmVz}WP%)oc>eEj7j|-6%^>VIX8Q0i(n|It!dGcyfAyQN^k=Y0i0nsneOfk=B`(zD z^SuZ-8($xB{NP??Z1pig+KA;g_?Rfbw`IO^hrNC2=VOq z!I|vjHO&Z?|5(%PkH4T%?$vTQyLL{H*SF|9gv-`JPDY$kXDR&R@R4Q%#%^iqlN{NF z_;u2chRo=*oSf5PNSMNy^pOJ)uU?BWWse@>fI>|o^fpBHBlKRUx1Q45Sv}Az=nhhx8Oya|*e#QGz5hWa_VA9qf~Wp|FT_qUY6yq}#Y)>P)?j|)?%Np%~{&v_TZoQgH0bFxQ-DU>-U;NO}g zU6MiUpmV1O`d=*hOSU4`u-V^Ds1I~($=YrE2!H$qBP&P_LOd8B`rj`WO;!y<2iYY1 z5hwS$>LRiN*HPpx&~ZE2kLVd2yIstO@Np*7Wf$VOZqE&WM;3eYL=%3fC;Jiq3-|Iz z$8YtAM>bfV+C>BmU$D(1O*M&;vk@ksecN!75m2@3VPFj zSMD!Yb^F5=`#o6xj1Be^RyJhIN;M7s5W_8e%YGJApxJ`7k;@=@s~+}egC9WaaM_BO zzr3&!oBxlDH#Ddo86o=-m#xiC{iSWaoUag%=6^^x=G7VvW^_#wup62&WJJG|3=taD z)vl$r!dr}Ud?K%nz;Rm9HRMnHW}2rt`n`W2=2s(&-{g!JB3cIoadET`kkohH|f~u7{-DeyZPk zU~O(|nv<525Ta&m$&zX^j6@m!$l7~)`)xp@G_W3)1WNj!)UodOq4?@REuM znP}wPnh+5WnPFRKZlIC(U;sMp`<07-c0A1E|jZ&GjBR^bWN*c>ih)0Y2E7@Nvb#(_ipsmfCZ=U(tW zwrbt~Gug6+eL{YzL^p@54F#{SzG3v)_O(*5Hnf*ut$Jx!sQqD+WL%0>-GssS!n*t> zE*$YMSi$HIg=OuwtPmL$#mmWD6ROb6S>7QOY*W2bjd|9aR3qlKQ3<6aoH6i#fcRZeoGNVHno|rh=f%|Kd zX0jjAy6-(mP4gk^3_qY0?;YWGvtw+FSWMHwtYnYUo_~fJH(Pe6Aq%q83SkcpD#d*o zzIN8N&b^@!UO9&FZ*9YRauvieXQr@|)-bPZhf;6Vpisz5HxxUS!YeNKC z6`ONRCgB6nHzVG5Cl`~Y?oyf?I%$e&i2d$2Wkv&Q`m^%AN^ulk4HGQ#EN%7GKD6{$pF)tk>T=w2QlVU zt!wOLC*Z97xYCvjlMSZZ-)c~{kQUTJ*t|V({;ZzQ2c=Kx$2rTn)ek~T6)x6fTemA4 z)9L00VJ*h3kx?x@Kig@rkrWCiOO~LaowKRpl)r=C3J1wdDLi5?a&-V$# zAKPCosDeMwiDW_TVRWDUN^$>`46^C3KD1U4;jX+fU%Gjo8oq(@FsFyefWM@({o}QJ ztz3Hp3?1=cwG(LF<^R~a>bNSGr+<-i4$XN0l@7ZF43JR4Rur&XKtx3;0lTnUu~-Wp z>{h&X0@v>DzSmCFd+m5ac6N4lpYu0MD3ggb-v>MY5b6cu zr6he2_LhgWpzwSffA5$wyUMmtNoW?I5Es!K1CW*eC)#l)BX&7d>lKR`0;DTr-5N&0 zLh7dD84&Aqjh@KGDd{f~PPDLJ`u97_XYbGAZgm6CkzMn08GQC$_!DNv?ZX-ybW*aH zhhc7Z+DZ(_k>I%5WzrO8w;CGOAJCL!7pCrncMXqdw5lV=yL;dj8AXXj?9^yk!yVuQ zT2I6wcJp15&SG|GIw>-UE{5lw&%WSv`R~<~R`lC`kdjR&irBjy;M?%Y(s?qVjT8=y z()`qk=MD44L1It|P6WjEbxb!XmB~)P7klXtHH}!aTdQ;|#!uD?prTbXj_&2+55)3w znqN@Ke2W{VT=O{o1>`TL`VkxdI<4md@?C8=oG z4O4eo^NsRMkVYIw#H=e@os^N0yMgKKp|XkQWx(AKh1un|gY{QPy+9lko)GdsQ86X_@SyEpSSqU|*reQ=tyu#|w;4t;j8ow?$e>mNb4QmeL|BjJV-rj|qGq z;{8UemxE0GVEUy~2E;`B1uM8c0~xHG2KMQz4Dc|@f_Pl_Z3%A#vS?ZEJFQlBoZtt` zt+*w+wen>lw_Oam*wP|!^Mq1Wh$U+$IdUf(WU`dAfgCFdze0nZMQn2V?M1!~gbdD7 zH!6#GyG_UEhO$~V`wi@s&Qm&K$YA$GAsxwdjfzbkOh$4g%8EF|J=em}Xg@ zqTBP;+;M_ry7YxlB=P-72g-z4ZGHSk-X8G2lxmmxdai$4Zd@68vFL-gq=Xs-yNWo> zH0u@L`zd1=31eri@}_+1yr3JW;{F>bE6T*U703M9^8Mh%P02KMVLorQ7C0`JQYUHv zaj{Lb#?VVk7WN*TMtBVp2|(=d>R4SCx&?M9)v~}L3#3|bR#c@-h0{!hZ+kNFBh`Z zFfI`fu4}C2-KB9K)|JX54y<=Il9$H}Y|(v2Z34pt{bmX&^-KDLSXH46h;u78Sz*lJ78es63!hO|W_>bcL+tQqU?tl%R>PK|#mF=H8&)Amy+y#jlOsyd9mEW~xgMQNBI1P+X z;1f-pjZ5Anv9_&2|0&~p|1Ma4{iq7Wd2joM8QXB{7ng3JRqS@;y+sua?6s0FIQyH} zsytBr?NY3boMjnTHC8HrV*DS@GX;jE^dp9dYvJ4T6~cu&LheHyVplGQ-}!2!RUQq( ztR9>%bMIZ_(hifsMjoj!Otknvf2s+)IXqfIZn(syrY0pTV<(QwqK$`+8=7%aEq-m2 z+mtX;=nDJv;(@J8JVl)Mq`@0QE?dX6|EH@Hhs|MwEWn09I^0#0N_79t*OmoUTP*mj z>Rqrb{i!9y#s#R!iu=Rd@4#-N8KomWj`{|NJ_dQW1cq2i;tp}&#K2KP1%daVg3(j~ zqG=sBol$=<`G!U-zk*3&uF{o1?^W3$G}9BL!%Fg_Y7qP1N-s39)LOPtM$U&aAP$?h zVy(Iz8;Ji_@mXpPM8rq=H1 zsqhhum~>9mF3N^@G^AxVuL1kP>VG%2mugW9h-;i%nsEb6Ne?%J^+U2cKxaD^loRpR zm~L~C*f7b5{zdGZc(NsDwNgIA8uk!Tt}y3kQzpa{=GLe9z+)!a=ZBw(PX7KK*GcRO z4lCmH{q}!xIacawZ3n};iqa8B@9Xc+Ld$>}EYfN$ogpA4Ng0HEY6@|3^44I5r7ZHN zshxC)iX&DzQLBTI74p`9@%(cOWk7u2->w=;ULdE?DQR$`QvVUkgLuueUUk&gf!Q{w zxc;Oh#D3p%LzYn35djfORN`-GT%jOs$1GkgWu z|1-chm20N4l#28Hp-vN+y%pV3Hz^76?y8hT-i=%T`GJPl5ebMv ztE@~E@@4O@Xl(7KG{jy*|NED-A4JMZ-lRbVK(FTZK@47Tt)X#F$bCVcoun#M1LB4j z6RYq6%KT_bM&$xZM|{!)4&M1`8w%qOGmV2jgwhdn9uH@}H%gRTn5(HG>y`FjP{$Cx z?zs(C`YiwYg0h3&9h4o!+52X<lCv+y6LR+1-h2{RzR zp7pqqAZ9P!*{OXZ75TQRWAV(>md<= z__|V^|CHfmFKj_|+^4dL($K!`F{!?DT3p;fMUMZbWW>%7cYP41WX>-DtY(UHGQEy@+^TDWSEKA0P4J*ZN|jVxiE&?+*>%n7c6D?JsbQWM_??#5})K*O0a z`6CRL4YiF}r_QFA2Ug zI7eG2_g2UlMD!x+*XWqZO)wS=deR9(@;SL4LqFSMGmy_mt0^hpKib4Z%eN$A zpANOz569Y{Oj}4FsR_im8EfjGeu3lbo>0W_AJr>HC|N<+-BD6^B(eW8TL zLLLhlET!R;0df7R?>o6p@Un&zlxNf$Vxt{IKOL!@?0hrT`Y%#Mz)j=P!2@%+I2Q@0Rti} zJz~<*qrlWm=BLA#C?n$Q(1%S7dehPkGbWR@c#*Opw$DD(+n`i*PBDr9JN6&%y-YW% z3>g)R8FT$&YN7h%>(j*H$BdGnJqo9rsF_Auye&jE*;utI96Rp;r7&^{RuqVWbb(l~ z6GR?j?X54Y6!PTKFoA7VkLI8FZ`VdHCO#ic&E+aEo>tObDvWriN-sYnN%CDwr0D@= zK%D)3U;?ipuOzHzK9IpeI!WV&xNg5!fnko3iQpEW7L_!Z^x`ARjCjj$TsE&wF$7ZM z=={1YuiX>lI4CMZF0eq73#bCb zV+YRtkLfd_G-&8dA_MX7;j)E6III?)gk*7%h&KOhgJTuMyiH+4{TEe_c-r2qxp5M( zK9(8>sR5-U{xjOTgTQlcR7EI8m1qrQN>^fxeNpC;q%uNFe7He2CQNb5G6uCfJSkRD zV%@1t#52xABlwKNSz|4kQ%@1~j@z~vCq1s5Hj)daBhF0jcid<_upO@83am!yhr3XAvgs*8SroxYNi5RW_zEQ_NU#Lip6zRHJ^5PyvLK)ZZJ<-X8^ zS22*%5$9EyJ(WwmGSM7K&?L%&INP_*UV{)>Iwd5h@kv{S@*oZ{Y01WYHVu}&V7h9Z zQj>=&Y->+h5Ia3hT5dG5E5;3rPyc`R64AtH#L7<9*t_628JR+EIMFR((_7v7D59Xr zQK+*eJ!L>Vp|w3`ka$a^&R(^w%Sxly+nT7E#DPpxy2@@43A3ZUW_@^2x4}~ySIGu;u<7}!!o8< z*|y_5Cn=ldU^%)3vQyNO4rjK^F%))|a)=#>DJ}Mfu(su3c?46-T|(O%%~HhkYnR_e zP6dPK7!)gQDf?3n#CoQS+48Q%OKVkV*Gf7{>4;|gzGNshupZ`Ml-8gm#O|HK`*HCo zf?=?hJ`+ud&mOxB!(z4Am?9l~SF1>8uQ>V9(fn=5$q4SJ4KvYr@(lOi>a)~NbM`~bj0`nnRxLL8(pO1C-7Buu#@`g6vPU@YJ=F8ZxDfYhDbtO zJ?0%8Tzu8GltSoV#7#rGl6CXr8$_D*q$I>ve^=?N)FpR6Ul$h9+mwd*v4$&bjtstL zp9*Fc%(JW+Kd8o#{y}qdX7VKv(rn%Prza*v4TTQzCA(YR%w7th@`&SB+KuIMf$hlpdA~b){J+=sHDrMAe^!K-DD;(~ zm29d7ac$JFa8?E*C$SdRx+0_pQ95G3mv!NbK^4uKsUpU|%zb;6;zO`)uem4%1E?6{ zo*H>2(T3&K$~7`E@VhBxK&*JPnn-<5sKH9rz3dsSN*mZ{DSw-dHHiFMmUEODXwb_` zl^R4>cK2m|5J6YbEQnPrZ)PQhQ|pNHdUU8^C~GPAnePvZS*8q#Pj~)FJ}`y3FXte6 z4JiZS-YZgl1K%7~ENl7v%Nj$HCG#w2W}~l5MG>zw(D3s@tlGJEav!czM6OqPl=nvH z{K)_5{G_L2KN~y1wp4MCpmm?D<0=@lE#M5q!B8P4$(q$(tCkhbzKCB9drBs2Xyb4%sFO8!Nh*`0D*6iJT zQ+{m!5yBYS$}?Ky*?cYe8^mhZ$`|0*O7&#(&eVQmlmkzm!=vf2*tisYD@<9d#Y4Pf zRZn+S&cl_Qj?!%nXAa`#*{x4-lk1S1nclfCocSx|MT2C|kP%C{$pCrC2jXSQ>p;9x zaWLHwz&hA%cQad+UvFTcJ&V}_N(__bZr89UlT3JdL_e!k@NMD*>E#A*M~S3s*Nv{p zLfy?;Nx8%>#Cy3n>2L{Zbdp5#Cb(*e)qJe>U(s2*4}p7KeTp@HJXL}C<%_U`xvC=mlj=gdX7USmo}+_=;ZzPt4hDk*BJwP7>8AyWJ+ zr6bOKUq4nL@{5laEGtS!>{G^OtY#mLNAYLEx z`Vl7*(>;|+q7vfMxW@>Waa1yhMSjiO@+qFz7Oq0%_yD=$5rFRP-tK(lnzhmDRq8+F zsRvl(DE_&AS_j!{5st@0svFTZ`Q9UASCwJ4a-`nWp?rwLin77@s-bPjX19l9^!k*9 zm=lq(k0*I!Qfo>=Z1?vBXNrnOp~;^ICcm5lzxFC6c-pN=V}S_U`IsS;>OtJJLzWad*;#!!=u{8bV2Bq9az=-E=Ug$&*M)djwfrwoW8 z(G%e-fW;!{mXaEm5|hf+V^7M4_|P`@79V;fMDDf^VJsxF9FZz_t| zQqymukUsM4T}#e-(M}oM<;*7D4;a9btYHvbESXQ0Ahv2UQaSd4+eVNs*R=5kucBud z=!IF73$ap1Gjl#=K$_iEhyFK87A3Gj0oo?)TnOBm5QXsR-h=T5R@*WO`#yteMbyn) zP~RYZ4(@4#63~ar$D$SGL;OB^V;Ej*;9A2uKB+I?fryhnDY2AtpQRy}b!J;18bj@h za~W~bhN1U(7f?a6Uai1}7FAQ)lLoI0Gsb~=)dJOnu^(6-vGC#XHUhV^ghhUg5<*s=tF2qy`n77)`yR@N}Kz#{xW zXvFkc&#OBKyh=$XZ-Gp8ApZ9)?x2zHa>O!J4$I)zT4>jqnB;QpcflWmjf(1lo)xv@QLl^BxC(?B;=rPwb*A%vr?i79CvGj0*)_P*f-X{ItTKK!QfF!# z@$+cY28NLX&EX9l6GyIwZ`F^63b;vOFNr7Q?awsWrD!F287MwU6+n~Kd3GpN{_>9n zcv$C484!o{J+~RJC^eLers18ncuGTjI&}60lKwDI%u^`|@xb~UQ@GxHfVNo3V(g_j zfb)-(zDYt4)}U-N6R*~alwBEpKg=NXwroRfXhBpX4g9_r8PXkGVhs+z)kFrOXX)v~ z6wNGuGx0T{SV(b#_jp`sEY~H#OgmQ89#q~SssQn5*flRcfq{{ps%2~8)0g&KTV{l6 zE2w64u&>=lBUhabaYEvxHSvbeeJiUX4x@Y;IAo!U42 z46{qmY#M9LREDD7`Sx7wdq}OM0{pM0S;_I3wGYt!ht^5XTD=WF^1{hFs1W1}zwfcCJT~G=o zt)uEL>yFRYwiudlV4E9)2JT2rAl`Z1l5Tn9;_a3Ym((x4KkrH$WkdWi^3Gc0nnK1P znkqUrvleVN#Py>VgIgRgU|R?C5A3fRAQDZfD#RzOaE*b360`LO!4%D=d4oQ~L9cT4 z8q5`z*c`@9)QX{t7Ar@8WNvIciEf9n)Bs}6zFtj@lFbHG0|n5G(h->mJNDe z6Zn)EhPa6Hj-Df{fxRr#83ioTyalHrk zQyQ5;q#&AA8#~u9I=1qc8|VO-L>Uk($4^!+PbhlYR<5@YZAj6&KDIc`&A?4t7LNv$ zxIk^wUK(W-Ar>F5byP9qxZjbbMs>Y zMsy-RwEMA^jT-^crP6e5RXKl?zeyRX6j|noBZBAO;L}y9Cw~pPsv1%ah(onuPng$i zZBNO8iXrZQxkO{AH%willV2(eov95VqVhNTo4BY#UK1{~^yeFLrOmDDkh`L#Kd>;; zg-ePdgN^(XvYAW$i8RE0lXKVdy$NK4mu;tOxx2Ouq!k2Ngd!E4RVLK+POa=%;VgKX zzqq=Id z-7%~mN_Gd;wteg%+h#~i2-`mc=GsH53-M6>?eM|uS=tE69+-`GDq_nX!@lshFraa3 zmNZRk&Ss~)vEmj;ODd1}FnFs4yO^b|!@Or{Eo2*z3s=d4szN-!aQ+?PUZm1xMTT-< zv^*s{%8D4Av7`j|iWqZ=@e@0#UBm%Pcdq7AtK`LzHDhOIgN-8U-%DKr?)@&i%w`&x z!{YJ9>)hMkysnT55OVDGUb%Zsr`l_&QN+*^pXi+r%;=KZH#wDCa-w-+{mo)AZ_{Ur z#!KZN3M}io08a#Jv6KwB&FJZ2i4NTYiwDG#NQnW2qNc3BP+s_$wy` zHgH(uH4d0}a2lKhiQB@y*E{8+il%Yz3ghmeGL=8|_kCuRKsGW1DiGyj>7IdgjYPPh z+znHflJ3+KL|^vpK0i|eDr{wU=)AegmptLm5@QXulvW*841RQ;jD297p4A)&jLo9D z5lao3^3y1SayIlpl15Pm#G{Xv8b@94J`|q5GHkI=P(H+>vYruK`K8=~=!%i|>VjE& zkuo4UUD@f&m4K3A)Wf>4?22JL6MD^!`tN0pgb~jiQD0``3O;cdFz9 z!KA2umGW;dn_8-F>1dXf{>8RkH4T+MQLTszYj#^`tW|CUbgP>UalSIin87)=&tQI) zdofjlSoUE4d}GtHr_%X%lmYQ)extI+O62If*h(U)NW`sUnwc4EaEa{?!MTbcyrx##J^YEg(7@6w&_G9` z5b@Ke>^c0J3=-g$HayJ`TDFzwKsNMkD8yUg!QI1bi zHHa&smOVD|LEdm54@bnK`aX@zbueadjR9>;?;3bhGl=7!4TU>_265ki52zK*va0hp zyceiVjTvh2Vv8r`(@mnD8XIHPZ^EdE({@F#zq5tj%)(hGUOu|H>FpJv8Dt7XSt_C{ zGUY>lBXM$8zhP>r$B*ja;(@sFubynKhiOTcvJ>39AOIFlF=_lpzi1uAEu{z%1bZYE-)42A<`APjcMjqcCF3Sc6www~F{CL(68(e|l`Um7 zZYrPE#oODyF_ZF|5V^kP@9&=2@0qyTP|QkxYK}`>e;Rhgbz62rv||Enp3aril;#Fk zBBdk#J>v!#f8{kTRA(+vYxS>+g!;10Wx%q?gKD)ZKistu_qK71?rb?td1)rqh&ZCh zOSrC%+Y~5k!+gqtX%J88h%vQF*%~O4AT|sG;_ws;2L*B1-(J&^B=JR=k(7>DY3m6; zj5%qlT6m8(F1U-#3!RG!J7^E@K#7wcw8m33T$bT%R&^a zd@rb}2^qM5QEP}p_i7+4885697cgUQ%Yg%2j1rmPzM>)Lt})YzvJfxvooYhVP07sQ zRzOH4t%o#<|F#u{`Wo#9EWbjz5P6TZHO@fz`|Q)yZzE zs^#CN8w@oz+hEp=ZL6Yfr-ZW%hky2awtx9s8=T|J+wvCO1}K1hC{2jbC)-=|&^hdc z?Bj)-x)YQE(cO78L)M-eA)s4QWxn#na_ z_${P7Y5_4jv{nq6Ve1;mhfvWouj#j`2MJ_ND;oQD^PYel|`%250BlwGfNH4?7p+EVOw z1T0HcV47o>5wk{IhFgFyU?6&?p&sc?5`fri`Y(tTz(<`zuJZ})2l-t;k5zP${xRhx5s%;e@tV{9 z^P!2QQYe|)MI8U*#zUSw2D`Nt#0R;B*ugh%~Z3127m}ub2Ga*{H9e0wmw0SY#G)>R z0|iDWg`1X=vh|!8#P6F%UE)tz>R-UgqwOFR>0n|8;-X3wV36^cL+O(A%*0IL$WY=4 z;@-^hlF;pajUHL5!nNm>*5tCnCtChRl-kI{8B4bDW|Lol=-hwR-F$w5sYaS^$w@<8 z)WjNI6++S53RKxj$wU?6)WZ1{xL=A7?kg>ijN1Tpk1Jfi7?0ICb5tWrp}T`^EI=C zv3wwW)|yK40U%s`Qk}YF7hDade(POhlM{>YL${$85R+``!wutgrkz!%+<_%}#Neu~ z@Jy0NjA&+}mkR>mnxS-`<_lufPWdt_k~S)$_4(oO*cm>m1H2%P$u)p)l1htt_I|h$ zTMlI*YauS%kBCB?{w1uv(6_CD*f&vwZEaDa9)A=9ngEaXMpFxYKdJz+bYpmKB@E2k zqW$1Rz&vsiRAQ;(pjTuCtzpdcto2HmVJ)c=L`{h*@Ep!t@W4iIGVQ3W4b@-@&Hm76 zAFikER33$^c0ac9ky0qyxDvJn;&AoM-gU%~?yMJA3E%xD%(pcds5p?!b{$-@j36=) zbLVw>s_;q9g8|U6jcXwTuBs?Hi2HBWnZ*|?5E45%q#kms9c4gl6WiYrm!YmoA1=Va zEv;x)#V8x>)M`-k{!{{S?x9zkS*hF zYb#1abXYVjotflOVV3d4ROcex+FC$a5xef+FFa}M^#;O}w_d;_kk?N^oh49C#Fefq zPVhAkbFq65VS=@$bi|Wgqzu0JWV|tTlfT`>(e6wc5GVW$y~)aKFQ#hqTT>f_9k@Sz z=-9}LJ$wiE0FYRSWuR#4EGmyU;@dw91(w*HLzaxE42Ub=Yz)LoxK`T^|4go4!9uB4 zesBp7J9<%W#LRNTD)1%`zBJ``!TyB5YrMVk7%inB&Ih?6a6|1nFCXFlAFnjy3f_c0 z1iu!l?ZY2aJDuP|UYSZtxx-NI^{>mN4MStaJRVaTa&2h(me0mIk-d_X4F99-A`XmLYs33H z_6%&XoTFkWG(yx-pL!0c$a&TEg{fY(yBjm1QAcC_oN3N!u`v`|Ie?l%{4{hhdnbcd z0(Vr-qki(NK2N=3&$@Gsv`ot|%&CC-Wku%Lz z##F}>4bJmDJXY)2hX=@vBbpFrcIxcG-t8}*XUGHfD~K|?aMjp9_VYRLuPar6c)wrA zZOV|yVNljuil#I~+nN9DQVk^Xchd2djDbIPjyE)G$xgfi zw$Gxf5#QU5d&--gb{U&Zr8LC#vqG{AWi8l{_ds%AN=FR1{YMFIxG2ni3Cu1jX`oS* z3B<`wJHkzB)Ga9CR;m|a{eJblXq+Fmst8t_nNgWS!xf&G@-M(Hf<|xoK7~Wu$EGb+ zq?WH+G*GEcnfHd;e3;P@NZF>TnlaC(vD&*ukl36l^FqF?D`a);U-n6n4FZp)9GNK@=d) z{A|GnZ8d=iy|<>d^rFg>p3Gw=do{IL!+3bhHM>6?M2ZWG)TU`g{1T3aQ= zc4I%-nub#gh-cgVagM)Wg%!!88sh%0H)TLP@$6?HJ||TRTPmem7k%SCS1^_}-iEGC z#S!KITz?{?l;T#dec}?}4HCuE;77R-e|`N37vPnbBj4$S3;YvEbP&yMH~GN|P2t{v z=;7S{wlclY?E@v*y&|2Rw2De04*JwTl-c4?{Uq<`f0sgnNoolYy;R7T-8p5Fto*-n(!n0=9(spVAF~<5Ii4%AJBM>J#Kabl5z@sLH z#%I^T2w8E;96e*(pHrXlRc9kttAcH}q_zq?Nx-Yu6h!#Vi<eSC^Rhl`n6*}=agP2bVGp$o>48JmfDi-TOEYtGAZK0me zKcJqTl#bYN)kO$_R31fzcH{@OVVQJ|ONuRiL`1YC!>4)K89B-dKIp7f5lnN|xsEWV z%aN6ExJ0*@-MQtfd9QOdX7CX)jhVUhA9WhBopV#V!(fnOcJ4o&g;2`KuYa*m z83w?rG(SHT?-`f5o(Ct72L9Fn>9CMSQ@;^6*Judm+{#T4no?%$u7#QUS^eifeO7R1 zJksM-{7j1|sN+jjJ&0n|OiHEN5gm_bjiiH3ti9JSowF*ie){w8vFKI~V!O0v4$=lH zig@f(>@6eZ#+x)Bh);;050r+lFqoPJ%dN}flI~4uh|>D$aG$eSSIB2Tvee4LY-$y7 z?Hi=q4b+jnO8h;3z0DFboT-5s#KY%}E`h+ipSlp{@}JID^;W^oOVKZlBEZgl0ugCT z)FGZI_~q{&&rm zpH}*bz`edelD#T~W8%?6PXrd#`~oc6N-RR`z1a5&k{slcnAVS8j}kS5TQC2byzQ2# z#%-v#i2i}e%eYwOn1Waxq*@Vc)qC$*sK6`hH9q5OaUji^OJ|O1tS_#C;A8 z;SpM#M=)a@RFid`o5fwD29o=M=CDy+d0jKTL3xEx*#=s(QhA=nd31q?vT6X(p$e>{d zf9d#>utTBnnYq3C3Orj6l5Zmord}booh-x40L6S^6)oV?3l30;2N8d+MC|+6D4D*;zY@hwigt#2BakG<|@cz+p^cK#7w_dDgLgYw$Dv#(>1JZWAStT zVk--py=4~@VLOZcz%6f*ufm6BR0*QS53b$BQXbj+8y+#VpmfBThz(tgosrLftP9Qt zab$D0yr0dvk-;FgD0_j%T;G8zKxDmKSz!s@fTbf1l{m*M{gvN}4^^M|AyI?)edJ84 z0Z~84vZ|6n&ioe+EJ>mRCt4hJ- zfQCx7%wi5+t{0NJuj#tdAkUI&N2I+l0WJiBU@`02Pzrr#SRvy6cR2&txS8+@yx6_C zrd55649o!rtEK5mX#5KP`lljo(X$~8NR;IIC-2lnL2aZ8q8!og;7dUUTg(R;6n#f& zSL5LR7amSytxm-uE24CajXc$jX93pGDXh4G|JcBNG-sVc*qa6LFFN^c8LIXMTpaD_x?kr5% zhpR`eESRBe-*kA3q7e-T;=e5io#VQyc#i4tIssQEqWbfkSI-VluP)R5o~?1ol*_}YMIa9%gDtD=aW~R0>!GZ<>I#g@^a)&x zvF!O!Hjt`CEH%Cxd}E?`{MenW-o zx5YR``#Gm3Cv(n=g_~vV`Oe)E%Ct%X%GD1hU;cY_S7YXeK zi@FPfQTb7>m@D&gb5CAX(Mq`3BX+l%!@~Bg%w|rBj+qt0g(VF7LRmsIJ?@=|?(P7# zY^9bz1Bd3??0;63<{k7p3U44M7~X*!MP(6hnjI?SV*$;Y!)yHzO?;Hn5x3sila9nU zV6zXx)j5AkLhRtzZaqIEfua`d?M4VgzeeeZH+z*gLvL8HoNxk7vkjDn_~6v!7JLMi zW(#&|>0ELcWkPhn6=y+UkKDi%fPu^zedDZn=?ocj-!o7PYzGuE`V92abY58N_=!Pz_ z;+&g-Sz5VGe|#xjujM0w_;65{p4jC8`NDQ^c*@g(WOz%G$U^MYy7O7AxufcvWiRhp zzcz{p%Q*z+MErb+0XDb&R`=L3m2a1?_5?P}GT-Ytu&;I8xmVJWJV)-t_KNIbyXOKgGcdE=^@> zq^HJnD{35NLR@gbWG$x~GTF#JhjA>IQU=6Rw$~@Zw?Dx3sz^}oabSNzsahuHt}$t8 z@%^}`C7B8!UJ5-7-#$Q1aPNt8z#9=KL zw+LS1z{XKNNR$sb;skMv>jUw< z^q@o#Wkqb5x)HvD^ryDD>Vz%3z@t9g%E>^s$cmdfR zz|OCMJDH*dc`#sOX@h{<$_IC%!v)6z6*S_i+)Lkhh+4rGxE9x!k`P_?y*|cSP_zdw zRf+fTuCH}|jOT>`vd2Lbz2Q_0F>lqK!$#$m1KLmH6qn3jM6W~n5SvtAM=`UgXXQ+g zB8ZGVqP0}c&i;WMBj3f=!hSbZZ89<^9{wA9+fsEN9Z>hhH7<@lkK$O$)DohTX7CG~ zZb9-4P*L_O4KQ`)o=pZdqL*jD3P_=At*8dXLv2P4$J*i9(gU#6^rs}m=07W(Ff5KG zWsg5m$BCPjF6-B2;=sawYbUIZtEenug>7#fxHt?u4dSqZk`OJ!Iyv%%HS-w69g1TA zqtDtCd|cjagx5D-?*`4ego+}b>-H}lt>D_k^0sSrrRm`C3S~pAyr^MT9`K|9_@$A5 z!LP0Ki_#ITj>ZiWbmxl=pgWsVI^y#2M^_qF9CNn25Y)zGN=J?MJqY zlVj8jI0jRF}{ZICPV3V(^jwNZW6G=6f07Rqduy}>fHReez>ed*PeMw)SA z=~aI5EvMoS3YO!Awe)1pQeflMJ)OIA{ge#iXeNiiuU4M{DX57ND-4H==t@`)e!&=Z zB3p=hcP`~Yj5&085*M&spw3G5YHS}Xs~+6ILpE4CL2$j|^AOpwxy9haRQ@EEpF?#c zZf$cTNEs~o!ZsW&@sKlR*|TI`_eP-GUUgZk=w!+MT<%)$1tsQ7RU+Dz%6`iCa?l;E zJO+$XD=FB9_Zjiq3$r6!xN!erJOE9hN)TJres)d~1o6^=sEBr6nitIVp|VuB0#%@n zFS}ZDtOL*RYZEYZ8dZ)Mx63*olftB9^e^J-jZ^H9O--Z`^eLVR9J#Q_>H^*wR%{itHDs?+>g_|c5pd?wjrp6^E58+4OA=C`woMpet@Zd41z)apS z8h1XTw!b#2Geke(#{?mR6|<2|tyMvc<*VE)E2MAAhIDZ&w`d-`sjNhGURbDg<=bPC zfR6XBj>0>+b(qfrt)1NRd!PxuDAa?g1ThzsuW@av(O|^UVh@ z>Nb^gcVcHR0BIDM&L|tAL(QR=(fwYBK?m$vb@OKyvh*hgQnsaBh|4T{w=nXT?bkdb z_KIEgSn(8MrIu>jtDaJvb|Cq=p{OJFgdQRj_XAFAOL=fR1iDj_oz4dHTU37S>JPlf zeCHQ;rntW%iL7zqH-%+PS_m;7xIe&IhWN%hx(55(AZ>d~-ahEDz?e?bA93He`1N&hC$nUt`$J?_m>jha*(4q=EE%}xG-u@gib2IjdLwEG zvG7CZ5T&84#adU{=VxHCFH5}e+xE_kS^~2}ET3uRJe|S1jG_7vXIJbGAIUR(WEXp< zP_K82O5#seh@)6|>}4loZXm%$&ifHq{D{dIsuyw2f*HzW4wG-c@iif@g=h+HJiep> z7dS;#6boE$ssqvaZl`U=sn5RUz#JBh!Hw0w_A$(HPIgJvzGquO-g(2!aAMw@ipX5; zOsydHnOxEX@9T5T#zrm%n^lxd*Q9kv4MXe1@|FMMA&7C^M@B^4D!~nz&H%2A!6$r9ucLEI)u7Fji6{b6zLnk4C|d*u~4bHp+vJ<$xBC&`>yafX~_H9n+b~KZZdG zvk*=z^EjhxDf_g>zjuaX`ZcUDida9EE#^ zmB{0#rqV^7UcS%*Lf%;3Q8><@Mr9Gl_ZXat@$cY*g1X()`VUU;lRT7rp88Tg#JMXr zPsNS|u-x-H3rBizUeqv!gB)O6bwL**cW;HduNRd@?9L{G@;s*tQ?>0k?;TvFJf~~K z!l6!;@7$?d#63fEq|QcDg@~?u8~jV@M}dveEis-?oD_dlm<u=(w z+HB=U4uKG<%RsYN7>1mSs$!hi!UQAN<;{>muOCJO5B0R673*ymQN^R$DeYc})2%7NjQR5n!9uaVsp;bSQ$bs9M-9M`32 zY7O!B{ApjfoTnVu*~>nV!9o=ueYQ@S(}sc4%bw7Lx$JXKU%Wht&Z6lpC&TR^{A@Dv z)iXi;Z49xK|8DxJQ$$>T8Hp|C5=n?hrfDn9~ zdX?qXW3Be8u^!g^gpPY?Pz;x?>L1BP1g~(@_o74sZ&gT`h>UBkGCr>jO0h(Zu5_@N z8ME@6A%UPrw34_2xB6lYhiU4}EcX80kw&Ri02&=+py)=boJTH>%S%4d;b)^?+!_F!a6(@6^o5O z;s-CGU(+>Lxf<%%iG}abVTqb+|EEOW`b$chOA35wjGst~HJ14`u9uR|0&o0A$l)0q zD)MU2{!g_F*@-i(tt%V=c;C=jv4%HcBGjS&Av(_(yp}iHFEu8GfBai)HfmhzZcK0J zl+r&&@gs<-Yw}&-NC0m$<}Ek1m9yjh;Coe3R6SzK!@=;Gg?k{!5zFC1LA4cdhsK-I z5$|{uy);(9PROQCDyM1E^1=0l$a1BX1K05lpAJ+DV$75hq1?)W43(v5Ny=B{&L@(NR}>PV-roC?|+U6BeEmi_S(y$@A|SZUt6 z1ALzh8O&rU4li?w%5FEa)#FJyymWjP?30EU;9FVZr2pdVcaNEz*7(U!E8!FrR~wyg zaBY4~0?W#7KQT;2CNGBz1$kT*a*wyNFw$hh1==-c#@ z^?u+$XJ_x9F_-Vx#jE`-s2;?6)9qIyt@Y$KP=$@^C@}8XwaGj-5NXZ%t1d7Kx4vj? zAezkzcHx$u!Uw;LWQ<|GH(OqNY%D7~z^7jARI~hSP!fC<46nvRVH>!HL;*Eo12sM_ zKQ06hO~l>Q360Kh{D3}VBnB}c5I)|t?WCq2n|%qwphV-k=fQLR3{7d-oKp~A(UOWH zdNtERU<(v=hF2wc^lls_BOWW&?Il0rFJ^`J6LQRxkVP z$Fc*da>M}zpOjcBUj`Y>*_cUMet{3^e)_4^1}+0in)O83#dW2!h`o2rFK;BwIjQ*j zS*er6ro{WujN&aQjtVs2Qx~K`wqbe(U1k z;y6)Jt&9)*vm`$v@(O@&?EY$sdaOM$0I^K{)W3OUMLjeQ>_RhWEQrz(*9SE6M9UdI zWf=ws1*`~qrqVu*Pd)gPy^97#UC;{L!H)EFoT#A8&xC4~US-vS{-vo?IjN)%7&$kRXApkPfSr<7zqnMHjb(Eo38ph0OTSszfd*cq8f zj7OYseIu;WzSvuTJTMHVG{hkzeE;F|4+YJsUm~~D>QEL$$JK8g42%s|y&C>zeBeJ^ zu2X_EcJiDcJYEsGRH4xa?zv)$n4*BePNPDYi4EscB(;P1q35J>Tw*Wu)kv(G-*54c zjcdH$%tbyrL}Tj)LBL?1bI-;gss{1OKBtZ(hA=S9(+`43r9J36KS#L`T~5^+%BQ^| z&3gi1g2_?M&?wkW*$_Ri29HAaw^B*^Br|JzIn~fBb(~`1#5&!1?I;}VLW)K&zg-Nw zBkp5wM=c=MEE@nTWI0drkc2b#7^ zpNu2vMM<}Svn~%Q0z$;GUBoJ7+PQEkPf5HznOxmU=6Z%MLtOM?ly2W#QBUnG8bbqEZpgX_*jA54w*{>!;y+ z(GEaC?9=Uz#JNy-RBC&IhQF9v!UEd-IF3H8t4#j9@1YQ8;@t~$PdxPjasJtQSGmcD zf)25v6fhwwnSwpd;*2BAfXCMIok2B=C#kq%O!&|w*{Fa)nBbf6NoaeCyW8`7uO#s& zePO(<*^~hI45+x292o5!#?x~fYRalyH+G{IGZNIcFmZigUaEt0AFVjvk@rVYn1MAQ zggJovi-^v?)}d4b;)OQ(eYl2!8mw7FGU)7ml#ZCS_QPou=SK3GS2a!Oy?JrYSG^F| zkZZc4flz@m@vRzzy6Zx?8BBmprYqy=A&{u4V&0telsceeQ&QWK$mVv2aCO02j7na7=mb?Z;-vd>L z^1(r^%3cKl??w0D&y7#~vEzPR<3+crX+mE!5?MQDp>LQnLRoz^)~*T3h9F-w*^pSo zO$Q4s$YSmT(>9cn5XVHHz96taxix$kP+E^?z^y44;`kqOd2FSDTw_0mI*Vz|e=fVC z(5WojWmOU0e+8V4Gbln^Irs+}R-$vUN#Px^%<<_nSj=tMhIk-PWOMmSItXJO058iW z6FG>-XXU{I)u@JwwFqC8XdKs5R>b_(b@p%xFIJ~!Og}(FvASuL6LI>DEk4G6*vik- z>%#Kxpyg~tEMKbAEk2}JmmIOLu8CTGMz4%~Z=_3(j;RYP_~UZC2E@U0I*q640;{h4 z<2&w+`w$U`^`DfgWEgZ?cEwx6?^UgV<|}?5J4!F%Xy!3ouBGT zD$b^PL=2+SK)B<39PSFEYGzfN17D6(GUC)uhw0cHtt zTmTlir6krr+v3YuWmVz^wR{Wg?$WB=Rl6Fi=im)A_?!!9BB$a{0pX>3oQa4PPwi~1 zOjleb9i?a@0CCUM*eWy?(9D5#qokY%rk1r{T!A`Ot;Uu&(D7#h}Y?1CiH9uHuPQ{c>0&Qli@`-27 ziGz;fm1$);I*|$&&qRZ`)yFAQk;E1%;raOJKyRaos%QpDegpc!S|#!e1|Isr7Zo%z z*u6wB-Nfzr)Th;8qv{I=vS_bbxSx+Uh?Q1Ow!#U$gSdh?r`2G1*L@SvY}hzJ0Qa!? z#KAlyT--xc`Z8j;QAH^Ry{qt<(OB5~q39rbuW}izHU{-Fu0m!kvLSFKgD5~8y773i z4G%Voe6kI0UHVc6#OudyS{nLbZE#YFF3jQUgGSKQ2!*L3N{`9l1+%&IM0W=h2iIpL z5^=a(8eXJTB0y0m?~bi&;=)oQH2fXHh4zr+fxa`X(0( zh;7X4=NV~61?-|ah_;_ul3u!3Ed1B4;7j2RsXSs>$6gJ7vv}lTutQgyJf#}Fhf5O` z;H^JJAr9}WDW!5>jvJH;exxu>7nSM!IkNE?p;Sm5loFTThU+B=l|hF&`X%J3Az>yK zS#`iF6gQtE%|C%rL8gndQ89@cMUtz+i7c-CFc&0tuqQOsk~)c4Dr8KaATh-c^NP)c zG}&$=SQqB7nyRgfQdb{XFuRlz4(!204P1{7($rLW%@1E4?j)!#Pzl!ZYfuR`s+~>e zDlq>P5d#BT&qikVu~wezdqHyr@y%uSH)o4tNPD+|-iT_r-_Pp@1-4q8J0fuz6xH9< z@h^*bL$D(1m}NBV&SrRW5ku_Tx8YEJj!~R$%{E8DcA!YZGa-(T-q?Z9TA)^9l>?5J z;w@zoa}gK*b#S9m%gHVqP^E~YvvE%7D#PyAo1IBK;>>FqPqiS2s|69jmyJ8|&#bg%3Z>SUWlReod$acaQqD)E46P{_u)&LybQ? zeF!^(yp0f0@0Jpio*tLV!yUw3-J#9puL?RsaeAQgB@=fFRf{;Z!q1m{FqN594YrXg zb#buSseH~OWk~}QzqIPeZ33Hf8%1&B{L7BRqLvfFShsP-&`^j)8avzrmS*1Wr`_;?e#eFoG)uI>Q-!42iTdm zqdp*p-7WmZ7jI>IukQpqAdwN{(hHgzmalRu#dJBw6axCtPlDpXqO&`JBQOydokjH{ zmPuNlY7k9H&Tfg5L!8AE=lbt6s4hu<{w>tRS}p)ju2vPK<*~9vf>gG}N|QO#;T#1`NwC$s|J25$yb(B0@8&AJKHwuU~w2;5JkqGZhuQXm_nU@yi`m zcYXZ8NMa0ksQ08A5W9Fsv3I*++jpUp##41LI-Mvj zaj@9;fxjuC7jd)T8I)q<5Pha6a9>?%ukgW>#x(h;|gsOxTM2K;|O zhnd+ro`Ie80vF>L_{&17NKGS__Hc$Pw0QE3v@^*IHn!p!_WSV>8g9nwGhpTSZ{%&F z=a!P#fj*}{R^WmJxg@r94D6r8-AA|2Ez08k5(wqX0P*@Z2KLzEd>=ex+DERVvAjI+ z8Y=NnA`>z2@LaeShLJW(hP{xXv}&I;;`3d2h5H=N*8a`2( zKINhjb#IV@!ci6Z^ z@Hka^YVkp#=((EvI0DWJ+CbPNe1IOTH^mhdLlq$A9Qr;7bhxgev*B>toJc^lcys_> z&$0x{x2*mx@X+jiWqY0!-5iqAsZzxA&okj`C#!WW;7lQoV@V(-sax z69u+ZF*CCQ_>0h@FyJFq5VDfN7Sl5{t5g5I|o_Modn5){XhLg$Mka(7%Y)yfd2M zzk%|=L1+%wrZmLnp^xBs3z%JUix7-;O{Fx%A!}#(@tOB)_HQ$z8L`T>8{WPImZ=yW&J4`amT!dQS4zaXeF-) zJYMSh8qYuaQwGEpXX|w3Gb>U98Cp+7S88+0fY{Mw3ViDZ1D$g>>fBTh&9q281#zdV zb)oY8(HLOs*%f9lUm`Y94TxKV*k(oPu!aL*^hBSF|D~l88#ESzOh;{o;B3)j`0UXb zS49i6lwe5mqY4qfEt(4kJ4`i?!Kv^8Rl{SKVxAczromYyNPt^XOgg-q%gw9NR10F& za%<;e13^yd^zdeNN=4k~aQUnvl5p$J5D+woG9WIW=c?gSo-!XpTE*%5eOW|Td^+uC#_ZH zP)49LJShX~lKhI{v=dih{l3t5N;wviqSH9V(np*QQ`LwEE9X|?&H7~fL$e|?2f2P3 zf@wi4Z;(!XtaIf2HO?n_s}?r|VozGtFVT_@;kiw}jqX23J$Lg(GBXptucESU?Z)rl z%89L-2a(Rrh)BfKQQN@T4ofpD2-1-wVXU0(SrZmp~l@L*$75Y(t2Pw9wf-bS$H4b42WJaq2zW=JlndR@bQ!xYx`KbUnO zB-U)pSm2-Nvv_qT?5@HH=Y9#vy%psm&a0>Q?q5`7f!#R>Q*J4>i}-Gr34BKvS$MA+ zR4Up;2Yy=r#Z2bwg51(lQsJ3<{$z!yR~yD&hAn?8Xq(j7+O?Es>r>r`Cqne*oW*E? zxW%VM8NO~Ns+9Xuy$4*affXdN#d~JaHIzP77vhvtuLpCzgQk+~mVx1fqOH=>zVb!N zuuEsbZrH;Mks__tmvtyaF@nePYh&R5E~*^yE& z2<$H@=a0c#H)0p+RJVqc3xgpyW~a_c6=U;Y|HS{}>#GB*T$=xd!wK>{gtUO2C|Ibd zfZbvjN+=*oi;V(yx2*l3UOUihC+Ib=g?)`H*e&R5=Wk|r&pG?}zTe;dgOB&@J{z;M zGqba^yQ`UW|GN0Mn=4!ThEHZ=lcCc;m_;qOKMff%bV{h{BIE{mX3$I^Z62L}% zNK)K?A0(RlEE1wp#YWl4`mxyba9#=Gteac^Av-&3`YA#e&zukV7iBqI@G%)K6234W zJ)U3qXNd3dra;KhO>w=-?lZAJm_R~1z{0pQc#MCExZc4zlu8ylY2A~fQxllY8^|*u z9&6=2(U{3j5fJ!pQ=J7kSZx*hq3D}z#)dF=nnq2Q_XAprn(yecB_Iw#6nG3zj7#A$ zg6X_Q#3ljm`*9o^yBZEU$j%LP0}82sP&)BIdNx-(l<<>Z5_Ds?ic4i5?oA z!b5ER^7&L;x75x~18I|QflC3AeQ&y?RALekZ3G?JHb~>77c+cq+K24Wfy~W6tg)95 zR7Ar_Y@r{4ho}$2{q6b3z`sY3Nnnqa5WzIbkMh z3vrduct1VALe7|VjL&3wF?4_xx z@Pw-)wrpmf=2nFZjg!;(g-kto8Hi^W?JR}%V>`uu)bfvK+OuvSUIpE*$3H;K*zgah zNavG~q);pWw*HDHdn3{*3(n!ap7py{ezT}c3Y&Xxx}q`Q$IC@L(6YgLCVx;8%b`;t zVwY^)3{{AGH$_d%t5Y5%1#L81a&(5Kw8DYfzJjDP3Tizmu!m*KWL^v62fqsMjB`-0 zn0^iWR{us-fxI6q6$hy*{|wRlab&D6vAevP)+e8bb%Og7}f~O%aoz!GHl>?-B4SZIYCn2tL^wcqH!RNoMg;~cJ z_h9qC4}tkFe)grE9$t(?4H{t$dPB5NpCS_L%WChB3HjB`g+= zG@QtYD+hJ~sSX700aeFw)70cB?HJ*xS=JC27TMmYf z!UvSjMg#ptmrJRDArsi5KiU@;{i2ieYoa&oMB78_^)=8w5t*`0X#NLW1cWH!4t;x! zpTdkxTAjRX1b(-dHwdxM+J&HcWLf{l*5*sf^YURG5eizc6P_X=)eBw^!jfbmp}pJ|DO0 z5v2f`;R;IwQP%!l@?^QdT%cvSLrG*V^CO)HGwS9~!Z7+;3)F@%`q8`^#CzqA*s{(g zrLwiODD7&$imXMah#WBkm*rLAueHLmnmVBNKGqi3#xOBOqig@$;Qfp;KCYm&O1v~0 z(57+B_cfch0kOB+Xgg-O<+KBd)te_Fo;exl%M9PGqrqm2;7N#o4n5GG3Bn>+Cu-#_ z@Yh-qm{89-z6%@F7oBlXXY#KRvs|~q>zmAqiH}QUDn5>9K%AIY2BM(Q)j;_PR;$U; zd@n&11Q)9pWH5aIegH=WPdRxx-()<5zd z95yOK8-Y`^`U1Gr9OV*DRYcWd%_6q`AKwhvB3?c14A(sy{1o6G?`y%I zcZ}w_5E~>^d{2jgjMIYeN0i-v`3`{-&bX}106WfFu@4e3U`;;j-HvG*3uiV$;wpGX z>kiY{IwijYtW*3}Xe`JtZ?KF+H%#g9`2LK8?M~D)E3LSrV5ZJ&A=19F9JU;NitTx$ z5pUSf^kmbv=5m~x;-{c%E~9`vGRL zlM580HS6VYV z1isU;|y+bab2`TWls#ulJ{CB@xpR$rP! z$Rn@?2^tAyt>rC1Y;j`JVK!e5!njx|oH&)Pm4R?Qe)PYsA~+@cZ2D)$Xt&QHqc!G5 zBI>R=H>56JQY#0Bvm#GI?6~*x75oeyiHc7e#{7tFc{*Zp`q@%UNHF7imKU~3^e3!7 zb#oQtm7+aRcsc$tqP}Dzya$UKy3s29Omt9Y?OpMl2{$?*BzQc~L6kcln_O40n!`Z7 z>lF$zxavBX)94QeM&J>$(|E;*XCF*|!(_g}K_~KIwWiIe;}`s=EkI*;8l<$i$L_qF!#FoSDc0YQE^mB!xrm9&9-pO>vJ53NWTII_ zA=35{JTypUp<#o^McTuQK%Cm(${nUI(Sb$YECd6x5l=^4ck=C9CM;lW=|~#afOJt3 z-3Z9Cr7Jr3Vd3DRq4n3|-y@dn8t}o$trngGV`9Tc@M~SfwPVO3cs2-^L2?Y-=%Vy7 zj?(>S60@ve5huyvlQGm=G}(@2ckyDg3l>7kJNJL}Nu$RhV4tQl?86*b3ihTb3(e|S zW;02AX*8INB=I2di>S_S9h-EB8M|)jV4)1;T|<24sGH8zBy}~&uke(%;wH7l=iJXT zoBcu)jg7t={}?ePs3&>b4OCQ4OE8f|&VRC~aU%OjTB>2UOyg|Z5VS#$%o!|~fg|bG z3XxEM^|aDVWA>ho)>}5O2(d6P*PY3Pm207I>vkqsi(-0*`_Y5C!9p<#*xm zc4eq?#9TZkRC`W~X~^SoV$N9YI{LUEUZQ6X-gSA2t-*W0wX2fpo(F z^_|=x9{J~o8M6lvqn-y3Wzz^k#0JMD#;}(Uhw>T_*VONKg6#{;T>#w`ofD3&$5}C{ zFmNzaE~0q9VqZ5Ai2w*y(Gg|M6h&c@P; z`*ilK%xKA+4^#gFo)*6?p7{D8W7%;>fMuKTViB+HORbG88%&lD)mZ7p*6j7`M$B%3 zOO5U(*~~)4F0$pRvEw1Y6IOjPI>;sRYbe|Y6U)m+bnJO@IhzhBdL_ldDgUZl<}jWv zISTInQK^hjEBNP#+r~dFWK9d*1@5!lQBZtCo{l)*?eHK$kb!GJN9Nj&;D-)d@tlaI zPif&mGn#(}k!RzP9GM!)oqP#AD`N4ons;&fx0C0sP#Z$=e1RpEg^<|7w>Lvy$$?CWVbc;s$pK z^B0_^uq6*p({!|@M46XyxCK3w3}H#G8Xv{c-2HL4rZQ=;4jM0k@8TfT9NXAAeDxKGYxOV+9dS@5h(T?i^=h{@+ zh|a4qAv^5Z$|-a%Xo|yBYKhXkS-WLdnP;NE1Y)-fFCDSE^FcUR3)`P^#03-(qIT-x z4{|&u3pQKE^+g@sgMWv3*s;$>oc_%eR}1V8+FVSXt<)JR?^}Tjb#Zw+*I{fuqwJMr zs(s|3F`$FkaT}4mJ5H*|vGZ^}I_@~TryB2{7Z-eK{yQLO9(_P_QALaLZ}F;|o7m*b zm%uP-$s3Po*XGwcbYZnum?XIwUk{;d2~|jZGHuHYM%;)t_y%1s5IdqxH~K)V6&q=A z*y|M$s7LzF-%MM8J1|j6{Me!>CNqD1fg2xnKz$5kfQJd-uf1ZgC|u`VqySBX@$3YSjw{o zC_x&_6E&BL-rHdR}4@-&noBGU|B4C_bga!-gH zMdx4;FBI|Tl%L<&^0RY181AC~W#6JKEw?4t!xp6U2RaT#qsVbi&+2RptuEpm6h%a? z?aaIUW5Xr~zq+tJuN`sv>;6SJ!JEmOCnG6DkvYn8>j_eJ39$7j{sp2(Vd?9P2p78o z5k!G=VBgFbrbt)1gCZ4a(4xBy+s!9mqu?vi;%)9QexK4uZ6V*yKq9u`)gpdA__i#Q z@_qr}{(4mfLK&uk!a>D@n0+%&Vr2X^3dkr*oTDwvyRfw<2b+Ppc41w%h3u{G7oo9Iqi&C?L8`c`^lkp8LBBj||N;pvDw z7MASA)lCP58q4hz-kVy1^5_Q`7$%Oy)mc~9GE=U2Hkfk#dA||6&Wjt*qzE_yFiI8e zkVsw|qFu#j5b%`+fl#8(j|_ZqpH1%mu$Qh7f4Lv3*Q88Ez=F3XJ{@3Ah4TUtQ=C>U zp|hLJnGH5Y@n63g97G%kNh61GucYV~cdX@Dlahrx6fJp--c(*cqLsteD7wa^ z!FHtj_TNPPnSl!<*m!iDh%2ll{w<QJ%br z`tt~mNk>JAJI+0S$EaA4uCa7WHpJJ$e+KK}jr8nt5O99X7W zDHyHqm%XRyS`+uJEJzK1pjQ~D7vip(O{;5K=nvI%x zo(--acx)|J!5=G0G<1K|n!|Q8*`CcD*t5|q^u&MsE45&5?;;3x^iZ&e+NTSw%+TAI zy8zvsqWHY9rX$>|00C3-J zUdLfuf=T#Xn6b%;Ft%c6I#wM?m^&pu6u0t3e}!k8f@D@M+s5-sOFymUmDXSLyp z58QFRbzH-4r6`7_uuWI9_6?!1)Cc2}-Y5OMq>k6ivkO~_4CH%EjY(0$2dkOa| zpu!Kz0$uAqd{|^G^L>fNWXr9c;CveHfj6BB9TO$#+s!jRFyS|N0GLpsl)9|W=eh`@ z^GYiYTG$+cSGTBtGiKQ6M0WcbIvr7!AXYE6#g>svf*=Y9g&K<5GY5_aVlW+s4v=ZH zfagTHx_VK7A zPObtQT1vmhsT=J&qr?xA3*Ml5sm9Ah+~=GG$7@mKoDctP@jQ6tgO+TPQGbtnq%k1* zEiV8ucHGQcMwwMw@q%pqzoJ+?0QjQd%A~$PYti~yD{HpFf%D&t@jhkK4l?(4ZYVeq zM9;&SsiAF|(mv#Xj!;p>9#2}$wO(ABhCTBZ46VCdKl3=#yt}MX^YVrxK1m4-LUIR^ zJIjGDMbmyzh42VAkuL%wUFB5X8G;3f zeIBq~704D9XnM;RK^8dc(br1tAiy{8(iYE$U6y%{kemdziH*W;dHSvPH^%$%5NFKX zkD?7eFZc60v|U;%R%f>Tm&0rDxPjqEH!wuY?)&0uR&118-$J`ZHD{T#ibI>5g zkp+$^jJHiY3rhF4Og7Pk9%HvBo{lPw4kgKlH5$dr>in*ugVB8Gsj$hP@2eYx zoeq@81*3;_9IqDf?}Y>5=0*rRmdDWEh{T$9^E8h*rVCrkG+5Yr@u5ZRnmKtat{Vd7 z2w0!nx+X@m<4vN8G}C?78MY=eoMLFlYeziw0$zopd!p@NGfl6!z^dXWyJAK!BLjEl zpCZ=Ci_p`N^oS8cAVqWJSdZBxc)h9)iGYx7IT7qBonlGQX+%~($|pqH0QQr(2su$b zt0z^KG!Tw>Z3LzkZKMGkx7T3OBET1{&5BFBPYXnPOA zmA$y?-@okN*-SMS*@3vO+8j39#2NbWTo zfgG&qBRCllpSJD)2W=n5!duAwVSCY1`ph#R!V}8_*wSOjRy>9z4nVn0L70y7;6) z%#abK*Ofo2bfh_mcMRXCmZclfSnQ|5$z!7vqzchrtV$%q2T=-48&mS5#juPHG9BiBa!*&|8r7K*$gsxL+kz&XkXCl!; zThkogK%zTmX!_eJ0y+M=xkyjXV#s-LN=Ip&CwDG?pGia-?kR`C&ZL#XoK0U9Fwi&w zbYx-<*lroTe~5kS#m-|hudoj&Hnhl)u@LQw>%f8%!;t!ct3ersvt-8K%UQQzFF-A? z029ngv0y*2uL6(2!KH|u+__B~2uIDm1dGF6ybi=3DfKEaj+(UsIBFYDLab6|L?6^o zJrv6ZeUnD%yvN`_c2ID8f!kGACWVdORneNtKCqI85CpDTj|m!b2uqU|_rm+ERYJT*UI1 zLR7RTvN!O8(p6~tbaM!P7w8e4W;|Ui>UHx!F1j&hXu9$@X1Ej4u$Wq~@(<9xwhBuk zXZiA7tUUvk!$M8po3{t?M>>S5I6^Nd`v=nyaPNT zieUpFV(g_VJPC1hjTNwj!BB<%caY6H@-)QmC+be2BqeEAh4<4^8yj`*HvG_z6!=+xFCU z0OGft*Q1yu9GH~M45lQWjM)C2TN6fDjg^KyB>Vt=9@{TxFzeT}WDKhb;-4VeX~t@4 ziE=u4^(_^ldiD2Dg{xn|8RIo5X?Rq8^oU3nJSEaBc6AlDv5aS9EM&j`3I}a)a^)u0 zUkFThRBTF*{b$e!I@oeYa9t|jMBZQOY7}c%37pBals57A0ezL zg8A2o?+1V@j5?Gehs7nbGYh^v9r4tsUH6!DMGZxcdV={oil-yadD}Ia5#4$Ydf!B; z*L3X63M}X$6jqk9ch?3yc|be{4eh{e7#oiYk^it?`SMJaE6+38i|5zSoQGerNUVJ&IhWky2S??`y3 zgRUsVbA+o=%+$LIc;Z`q>lD{M$h3d!_o@maca6ew?p zka=qtNiTg+~C@cUC` zNjm=pZ#mB3-y&Y~*y&5MW5_v_{QQ>la^E+lcL}<%H66)q$m$M(5XPBQ-p!#u72ridg6lQ?1L9anuH@`h47{!h9_Dc zXZN2J?NM2gspnO8ircj|MYX@nZt910ercY_+6S^6;E99lcnuBoo#; z`}@xUTl0#lp`57)Pm}B5k?ini1n)bd?~;GE;}tm#NzpFo_7I+gIKFwnQzh|i$*YxxgEZc>##FGlF9n+mu{}BrFq`K!`(q``Tcm z8_IV*&;=LD(-2c1HiJi};Wduz1He%i&jC?p@?^x&A?@LkP2*UH9e}a^gQp|*Zr$9H zjU^pxuX8G;dhfY9h(GeXo=CxuIiDuA425ULf+ShPcKAGo5 zJk_=)IK&t5`6-|CMrTeBP9wx+opz64k6F-J8BrcNs}e5(G0EpaJ4T6`kY=N>O21bd z@`|RBgug*B4CkLAo^75tmC=?8hFKsz6o%o>ocT$nhItGe9GNC9rH-#q;@Ume^^LE4Fe%-6GQarc*AXsuD_Lo)d6bkIpztiEV)ypuhx7^S&i073d zP9Cj_QnI90KKlqofygx1m$rtxbMSr`I()ttR4$5bf+xG+kot8DUjs?ul{g|Pez@`J zadGZcSb7XjDglR)T04PuYk5Nu-5w9>V(hif&2)9jc%BLI*q`a7%YLW_nqf)yo&hct z{a*v$eClkXzuUmnBu3pXya+_=7N-wxH8fDN5ADnq2W!xW{!L2}C$XLqT zKuBp7u7VloW5CUTDv{2=dpQ3-@zx=Fzqvh`3QttFF44?Tv*UsRF>Lf&N?N8ka7 zI0JbJi1nLJhS$@lC3ifHmc2YAy(-!7~(8(^m@W%bWrGr zs;kzw6lAwt0Mr#-F!v^RSYs0Yq|9N^n79B!)bA z3rnNQY{T1%_-od{VnT>i;3A^HvMtu<*(_hH6|1VriFs&;x)Hu zgJVV9M`$zE?VyR%57 zN28Gg_Z5KgW~XrHCTA_kXX?*y7pOnc<6!yk=3FChzzMf2TP^4zTv7gQX|WWpL)oor zuZS|8di`Jy(=~J|58VzWi}UC0yYlzgRK;{z4`#G--}Z(@>)R&YU*!PIOY9E9gck+h zp9kPpGqfQ{_%_gJF`U?lE{D^WunKT)%88)S>=d3z$JP7qnJS>`B@%J*F+7rm%O#Ob zop#$gn%IJXouQR8ypS11-uSpH%w*r$%5!b-7Ey8dymO9OA@j6WsFpz0%KOBBJ#c#P zD0rehB1LUM@<*tx_3LD%tZO(SqC zB&K86ofV!P$2RXF0s!s{6gt%L1umsT#h@PA5v~}+d*p$$%1K&YK4O!$TY52d-~+7f z7Lyvy1Z_Xw2gH6u^7qm{5X@tYQ|QaHAa;7TB7^ZRWbt4#=q67`yw!Oqyjg(v8s>~r z+mmr4)%<`>3!VwF|F5rb#GCh(Gi1SNc-k|ls8Gww+{v>ePWX^L$JlqWVvJgndh&^l zxUa2%ML~Sor=%Abi|(!>9?#^V zap8t&khwe?qHF(}Ss3Jk#X8H|?}HMMi{P(X((oZge3EevUcP<{v3DRs^``qPzw(k0 z{m&msGvy&WMyV~OmpmOYJAdaH16%4=#o@z8qL;8kpS~*%$MM!gJ96dR-@lW$~bmm=P% z2;Oo;+qRoc11)y~Ub9q?*M8;dG5mp%aq2R%-57s(@tpCu8E+b5-EUD7l%r%pY9>JY zPw=`BPu{8qj+c0KOX4#Urb^+>Cx)UH@?404Kg$j?y+H?5r{m*5f>lL4il+h3jX1I} z0bULY{G-prlCP0u2;;=mlapR?Ni3NPF{@!-86{TfVib-K?MV=z}4$_ zaV_1Dry~aBw)QtEfZkL$4(I8JRX*h;36k+#np&^$>S&7(bTWuBiI3IX1ht)FMZf-R z54dO={fW8uTD@%32lm6Xe5pvj*l0uKd3}+6%khd42W*E&iK&4O-)KocNo%WuH7Xe@ zX+ub$wboW@&PNdOMe8mP(5$63XvsFcmIZxdT#y}297a?rMxLiiVmC*RG4XL-SB zAZ_&8GKzS|qU9~&-IB|^F!@z4Y+D5jW|Sf7%6_knmr%po@%CDcJOuhk$V#M0YSz z$E}kgQ0bK=D+95lWrb;U=#lDL^2S!{MO{$Sfx6e5Jvf7_2sR>2d3APR-y*)dazu^G z6i&~1)><3sZ#$Nbcy#%&1IF*Q#L+=(Ps^?eWzW`n3^esk-T~xO`U~xL9riIbp3Jk+ zvNwY7!^cY&t%ZZ<#)`k$Y1vtD~B=ZMcZ{C(y zjo5fhyBVZxfu>IOGk8Djibln+h9Q|(5QL#yWJgLz$9?kZ}!kNr%d4)@8(eX3))NHuJ0-q@^dTP;0 zn#x;T&#g#9KpqY(WXdcuTI{4dWTYcm~8DtuHPhm#@;{u#tmPF{Ys%Pe&~EX_f=yaN0n> z7Zy5&gYIC@Gu!ESlhEfDZmtQ#Sr9@ZF9NaY6`M$8t33 zfCc3lG74h3g&AG3JAB^BKPLGZ#K9b%4N+U!8FrkuGJbH9eFj0VNdFHOT7_&Gw%67N z!{l1gW|O?8PqmAaz`_z4ql?4N(&YYm#yB1c(Fp?+*d~YAv+8YJVV`InlaEfs`YpUm zAhO0-hmfDY&v@DFfmMz?7zCkb51U^6Py>X81Nbc!e;|!0fh)gB<>CbmvHlH7rpY@s1$Y z8g?E+4PRNrD|XX|@A?Q4d^j=xZU6LtOiTzF{Vs^K1S-q+YR*ePeOz zit4x2AxFx5F^XV|EQ_N3h6!&&zNx?<5b5&7%kz`51+pEecb)ue2+o8)ya9-#&Sg20 zO%fH%6W>~RD3(w2%h!00q>fdD8%3-=v%$2)AwFL$e5Fj@F2r(? zN9f}ktqBeQQdj3iCvFnYgy=Urpo)Rdd!lw|!UfvJl~?%lCeL_w#FVkUTA-d7rr7Ih z@?iWaoK3y;{dr!*85t3zDtQFMeYpkSyySWRbnI-=`@TFaF+$=fd) z-KrVDfE<^eqz2}gT3F95-W9z!pz_57Y>(GaUJRDlEg0D ziQ-iw_FMM{-13TsG8#Q{yYpZ*F$-b{&xJU8Z<$so$OgNKc14xR_I8H0ag*lff0;BM zJ(iwelDSAymsMkPcV|8C%X^OaR#UCAQAC54 z(GP8>2%Z7)(J6jqOEjRiX zzky5F2lILmA6mFnV^bS4m-gruJ#cs`b5A?LvJtI2#MA4B!Zj;nUN zm}z>^&frF=W8{5_xj5iMJ2KBqqgkwnlMyd@;fOx7qv5e4e16T4M@zn%Y1o1s%{{xK zk$p_Ws@OIWo+E;Ad5WS z;Am^Zi$<&%J76!F@58^BlTYGhV7++;#K+xx*EVLbk{kBKElx2*)K`zm#>QI_@&#HT zvhChM6F^h)8sJjD50Ku1SAe+jdzvhKpZor|?~fk%mpMxbB~JY>;07MXzemila_vc0 z-vEOjC}86T*Yz{YsSeMBc(!V#@1{Crw_ezZ0XzfZn2^uwg$(;JgI*khckj27)q0dc zAJmn}h)>`U7r!6%{yKMzK_guigZFw-soBQ%>4^4&T6qsa&zRlojP%iw%+FA?NZ%(N zzd+C>@1Kqoe1h+TdD9W!M~#@sIQQ`yl{=k9`C53R!eMz|va z;j#2X@ceJ`Je4~sSg*1mK9#|woLkX?xhv(0;B^oU{Gcug@Sa8mix9;+_(s^V1Rg5` zpUYdJCcPBF8;7{VV^U8hRH1xJS3>~)7M=yM*Y@|PX+zzkQ&YL-E9B{jrLX*&|Gye* z+R7CT8=uR6H0Rx3g54I^RsLW4t5{k%O%tt@oije_Fo2;p`IW75Rv6TcLQiC&ldglp zR=8a?MT1hRE2TJUv$h|@s~d}e=(VQ5TjtHYT55z0bDLlWacyeZw(JW$mq8n0O};ON zcm{E@Hk`32&y+5Ig#wh1_~h?dHC)Ir7@AW(HTQn?x_2ZeA@hX<#2`^3=kL-x% zUY!MdKU23i7A5CwhYLDz@Dtfhj-qAoWs28uQ-N|DxVYIy-ir%lb%;%JBww2+R9 zg`CtKGkJ2AhnRRNpc%>uIAQ0b*0@EFie~2wL?5Mf+qvzGy|5xdNQy4JjfkVZ#KM_5 zLm6_$R;)x6*14PNouW;pr1W(M&xB~gob_v%Vn|k#qpoUprU=D&snxK8greIi%IjO$ z=B%mfB-~4Fsc*;|gsA=IMc*l+)rGr&BV#sCMbu3#9%87@%01QiL|F*WgE*YL?0`ek zMiHd%uv*&=FOA|>47664sWZ7beW#AbEZ z!R@yYiHt2E2fV;Y5QRg=eY*zCJVh>ZHL!;`Ste&j!iFJhqZOIs1l%FUc}({?|I#o~ zBzZP)zjBTgfBy)_U?Jdvl7Im7@E!hG-b%!I?;R2-`DD8uaF3pzCm{*zhSi0uP7NIx zTd267j8NTp)|X^Y+nNl0q-7rNWMQ+2mYDrfM+Vb=Yur zv_X_RsY6=aH)SCgeYDC8`yNcRg&Ul4dkKoLaY;yG2NdFXD-g?l4ies;#hT`-4$ueA%;{%eEw#49|7F!b2Wc40nOYHSM_{WH2ia(G{j2xwfXD-4!Z_;==;1+WYA zgvvYv;>|{ISIr@KpK-@NSldA8N!Qqerp%Gm}?^_~~3m9if^e3?%`2jmd*ImRW2_H(Qd*V2pz+n z6IvB3sV|I=URubrA;x)U%@Rs7JnOiLXF)vBOS(tqm)6!N`Hor(Ik!1Fbj6e9eJvKz zcT;FpwsIz9P)pXF=7_!v%YvrhB`DXii4Hq@80lz5yqti+>hMny_l$DgjK|toH{6hS z=&DaN#kyY6bYtfXs%NX{xLc5T55A$As|Ka59z(C|riEC^FKG{4crA!8vYJPj$WF#M zYh4w$bE(=}_r=q5tQF*_yH-+c#*EuL6~b^0BqG2KYI%DzJP#*opcZA);WE8n(_=nVL2l(cdyhB>?YXMtj&K#+@1EOy>auvizE++t?~Ht_28av(GqOgZUp#P7lE4uGmr~cPwGif zCGbTq;zc2TpZ@m&s-`O|3qcqYWGT?^nW8pg31O41VjSa8{j3T@)gQ+6(u{{#$oCa@v7o0z7A^QZ@GUJXm(Y$+d`E6&$KTvB$X$db1 zF;x|E==Y+E0w3GT(rLKxN3m}=>YC+H=Kq0Gc&+mepR^!FV=a{a{y87Vy{4gq*h`jE z&WG~&(20GGpWp48v1zB`(LK{EkH?aisLJ;*+iW`xg zBQ1I;wn;8|dBUr%7}E)DD=lyP8?-Ou)4}{(#0^eE#!)*8bLnI`3?pqsL#u2KJb*%5 zXds-6Vm4@62i{~ypRpQpV;sa^^x+jCy2Z6~_>G!!eiI{4#PF<$yS?}LFgF`5DsL1p z;c%Xgxb54Qy6C6tuh;?{Tdh-oi8YO!$M@M1`1gn#-l<=Z$aI)*Vgo%Y_X;Cs*%tnu zF)?wqTD59RCH!hFQ`(4K%lxWI%@p}ieeBk|0dfNyQ&O!!u(h)}Mva?MKg2heYI@=h}UI9PYIVe{aUk5tf~(XoNTsRz113M<{>xawuOk{}#`hxX|={nL%Kyq!~=J zR-7RayFsZfT*R}Phb--W2Gw=u=E(zp(jyNejh!hn9 z-7=rT{g|zJ3gVTe4R$aYHV>LC_n{BMiBsIu?vjlu0~v4^Zd4Pk@`v4adSZWqPBcjva`(M*0dvan>*1f}vKz#Uc2|X+bvF&%@LbuM( zVK?L#F9Fe_TJ|JnP|)^w7=&#Q+gD*_!=)?(9ki7(IMw`l4Tyv5cLc{Wnk-m@3qLR` z^C3eVQs>n?rm3(FB!NagSD~&!HH*ho?wzY|Ei|Vn43851x)0kH9=uA#zs6^eq}`T1 zfFw4G=2ShfJBHC4n z>1z4=F<3rmN3vYx*1wwGR7j43ACgkmR3Z0YYJ$B|qhq4sopOF{i94?oab?2j3|1!+ z(LFjcbs)Q8B$<;5v2VXN*9A@~dJ5N!%z6Vi12yF(A=>P%0{400l?Tu|<vH9J|jX4aKi!|c>#z`QXXzFF+SP!04{Kv&(jg>#z${q1jFy;17+%( z@x4zmta-7zmNzH+Q+NxcU?6t27B2?TF}6$w%Rpzx8JHb0USpn^X*G}x}8q8>s{kpoqJ&tslL|X_g;I{T^UJIhC z#VdF{oKGby8D)*NVn!r;cG)CM$dcP2y0>sTAinIlv!6*klfu`)Hvxqu62+RW#LP(d?Z0pf07xSS3|ODDzs90B#h;EH+9O703aT&DfOxd><~ zfpeQnh>_)TADLPO?{dQ}(~RMF@~RPsJvwxj%`{{b&!psV<2Bo5ISmo7w_f&x zWgAckx6i~S!o_5C@`&rLDG|X97{6d9dHZ#6m+OOhWr!~yKxo)&P_LLye2U;yvl#NQ z`t!R?Cba1HWp02~qBvJweXKKC9i)XAz-zFz7+we`*Q?!!^XOT;4#f5kmW*P?G8W=$ zc#mxe&w}`F;FNWYu#m-Fv8D9*!f?YAzWrgZWr|;WLu~U z#G@-Vrm?6In%=nIZ$}}u?^6ab%0~=TYvdY#qG=q-3qZUTS4nRo26k2_SL=!P@lCGR z5WnoXJRTP>4Fx!OKqt4+*?l(myr05@=Fg}9mdWzAnU;^&s?dA#WYxx`(GBUKEu#W+0(qu=Uu<{W0HL?9Fo`x=4pxu%$U|A@ZQ5d>&fh zq!(S%A4}O1|HB4yjtz%sf|k4##91>kDwzVC8O?G0>vfEbk4Z{Rh#q7J73l_dizddl z95paH*?6H#Ixh(^>DU>9gm0s7%YQ|jQS&X?u^S`;?e72>ZRN?if4_{3H;#rCfr+4e z_Gb4v>vTNz1CIA7IHZlE<<>WepVL34W-|&gBlSv}z{80HprfOCLlAei&AH49!ns89 z!ysDe22V#kmvjCLlcvUz;Y5$;xe#k*Jh3ne1~yaVj2?JyXgY5TqMPp*(D8U$VSFPC zFXKp7RPbTs%}g6%A3vf8%y27s5=VK@rvJJIkCQKnPVyK7`(Y_w^9#`5+dMy%~P zSC}0^F)%yY^K``Mr=KA%0}j8MM%uS+A_M}(4eAb$l_O=9BP<@mm=;jMuE>UoiD770c&t>&EZ=s?{V)DX<4s3Q8#;9)^8uOooy>|> zyC`;hLjR}_7Zu``70osM8%AK@dKM)w;`mqLa5X&|3v`^lK|oncqEQsFC?(b?pcut{ zI!6tG1*(bU19^dnZ(CmtGwK31rFk@+DE6kF_~^{-b)47FV}6S}skRXykeR%TEe zz92wKE5bXM&H3nNA{BWP4a_7CcS@CtS53+QH67Olq5$~wbf3j6E)EBTGH@N^n1@EE z#w88jYJWtY{+olBgEmQpa>j4|9aWO0gPxR5)I*#puhux^`Qx116vY1BlN+=7XpoJz(hc4b#J~Q! z5@Q@@D>)B&O0h*A@#-kN1BMeC3ed=#-{M@z<~1N5U!wbH(nfOPENgZj$y&U7h*h7==wvDYUVDc1 zJT-dJ^^O7qamdKsc_eZUuZ8rBgR5Se@^r*fj+dj+QsAxl0j;o882@m#C52=quvR$9 zR*=D3-;tMq*zWxYQc_V}6KUw~IXrQoQNN07h_OE^Eob$F#;VFHY@%P&V(;T-hcC$- zta6jT!D|3c3itGhpLM&DtXNe)z1Z^GuOXVG1Y(79hQOYqPYm4ovnWR8qPSLj$&!F8 zD6)MC)T$>{2CF<2hu6+%8tBOC6zClN{!@&~Q!nm=tbQ;M4vSdS#Fo`ixF}=4cddbw z(HEXbQh6%|cJ})!%g_x=lWgS~1@+*W4pG>3O+9wNlz}u&f>zb#6h&+?xDA9({9z~{ z^A>tHabFAv6*2qV9a~(<&~B+o-(-k!tIpFAXHMVHjD)19LKXgp^l#%x)>t4|!5at@ z1cIoEV~Wa4aeGhWp+^&NwCj*BNpLq*UNYR<_g_te?Qvf7=OmSnf-Kn^XVbttp58A3 zS|&0*r45wd<^Naem-zoxDty(1cqgiy6tp}r!}^kOgw-T*7!0#C9K6mu(!hHydbdjt z9plR;EbThxl+VEHEe`+PK;VcD@_>nGdy5Oerg#6of!xyjzj=%b0%N(X1s&5=)`|tu zY4iSdj5ahM0b_&ZQIk+S{TH!evxgJYl=UKHE&bng{~wKzJtm`66nWaK{eB1*FftF6 z>Y)%TV|y>Y$|k&_LP^n!fQJQx&_?lvJBQ#Jra;)mag=<_7 zcWJ!zrKtiEJOP+SjL@r)Z~|h|uk!|wAtO~R@(t&f>#~fpY;Fb5QfUa8tx~=odbig* zxZeuDrRi-mU~{7~Z#&}IR~cW0x*N`exgDRu@I(h(=_Ia|_fOKlV8+On;VSPk zJs@JNW#VvlrJ=YE7}1>Z$h7X3PUx1mH!t5<|@7@*GA?UEB9Qy(nL4mx-h_$DW8OTH-W+1^c zVQ=d7G$4y;+Ly8zP>D5zmhuu_R&Z6kMmEuXy-FB!zxg1Z-b{iWDp8wtUK2VPU8I~b zAQRu?6sM{4rp=|0!u4rWWS?hf$hYJTM!fIPFTuEW@g`fwLR*tK10$}xIeQdiU}!6> zV$)R??&096VR!zE;_S@u>2NDD>TsM3WX=qgCw0i9o^pBE;5s7f8sZu_y zq7!OmxPmW33R60qrz7s#R<@f^Ks-o9J82L%w-FBo z^@}4l$EpGq&*bI5axF9!E9;*EpUOv%)-c?g)`nMsIJUuS=!22b3g>c0Lv`VMI^>D5 z`f_s6BM87|Q4W=O35Y%C{->5Ojx`qiHjW=I&4c^L(9~tDJVjNO@<@(ne9GbmHbG^s zXCK8G1u&a^$llWnl!&p)lMFb=*|EmRpP?M)gjQaMl>q3i2c%Y}Ueo$_Wj z*D1-6HlYU?R0e%x=@B_B+Hlsr6>k&bWlu|8u| zmb7{a-04pJpH3CT=e_BmGQ~aZloWTkSCk(T@h0DpU?p7UAzoZ@G|)(OO9Em54tByH zMSww-xA))_HX6N@M}jB8hzHMx+0d1D19AJo^>8Z;t|)M}P_}keT#PmRlQo7O>h6PFY0F**#T^UGgT)rgEmK2H(mqCvTXfn!FCQqO(G69_w76-Vn+uzG4;_ zwRya9#5VG#>TCsTB(|lz{YgE;)eWNAbt!E6BtZhan)90k*!u19Jf>&vE&x6AjQ0Vt zz}{z^iT%oS9s%b&;`p;<>v(ez$B&zQ30b(UB7SP&sq35w0#u|R=>{22*i=sWTiHq!r8Mqd{umMLXI#r*^^YIDeL+|+U+u4Q%IMc zAj*cuz_!w+xF|_VS!_;gM0Ec+?g9yE2gko=256mKI<#%xvQxK~H6fe|+l1)##MKvN zuoubk)#^#u1D#&F?ZMI!`xH-s{$6M4Qh9Kc!|}>mE#hKgTE<5w)P$#cwsNtJc&cxG z)3X8ASfo^re-g?Nzi5@t%16xpew=&SpoQ+`crIE2Jhu&**Og|O5xZVFor!t~9M3`8 zdXx%hfdgL*I`WC6)Y7)5zib1hS=Xm`cbt+mqYJTmqqCJx!lc4pBTjEtV=1opyol69 zTZxRH6Q-BWaGplIvTJc3&OI+u@>W-w%nZ_6)3R3p&Hc{aZcpYn*0v;bOLR6;6aE=u zsQ*ZRViv6RCqc!{}Gaym;}$OLFO{}atuM9DLTf%%4 zckClZ+w)I#)>0K-GGgi8sc_#zV_?#fhH%CL#!g4v8fck590{e=uT-uqnco~TzHe=w#<&JHUhCG(;Yr!{>vTcG{R@lh_) zAN*6qkNax3XEPQib9s`S7FAj*=HDYe4=sTk9F6=IF)GSg`bWcr0b<=BP0tzCrZtLw zuWUc9j*k5$E7+c$@C~}gjVxEX@zMUWk#0TpwsEE@LnLU(61!^wcrRAt)pOCl&jQ=CnE;DEM1@R zCruA(rFFMPvHU0Sb}R1}q)Q8a0>%{@Ty{;(LS(oubTHhZ2`5iGzhhDsKCevta_uB1 z6jLF*nTSmzC#^>Fi#Ky_OSoGyh&KT-qkF-9p$X6pXK4oi9?^UIwOrwQNLQ1_pFxFv zgeGBI5%*kN^%=RUleC@}jrhDy(7)K=`b7E&6SEU96>;~>;9}$Gy28C>FfniOiH+F4 z{?&8Lrl5pL$_=w2Il){!EPyF=t$)Ee-Yj3OGfCPR=16>M@(i(-AoFU)!dZa@Af&)B zawgVb9ZC0BvnC^c?X%_*uL0B3cZJzWz8NeXQU9`RfAoX!@AKw@Rz6gor6aa3zb)O^ z0AI@A1-{xQB-~f)C?$BYjEMKL&%Pu6Q7{<_+5jW3=)mu=dHqBq#!LT9MS%tQj5_c0F$u2wkBnaJ0Lup zrqysU)>)PQ{0~q)N$v&v9XK!Fv<7ovTzlS>b2uWoRmzaact~s9PV4U0A{C<}fR}1R zaX8F~*>&%@G7H$VJ$$ckr?sPHXF*zP`|X4Y2HMhEZMEz=$WqWs-IxS;C!5z>jeb%F zKC!CeTVD8NM^v~4S=ojw$2iDvDI+u0*rv+#JA0Vbs~=9?Wo$+j`m+Vp(s#EN+)jx0 zIc;5LTdiGbYf zWdrU)irQ(}>54)qyH};Ma9tT^6nC;EHr!gO3BO~L5OZ2zJVZjQRg@QkXp;!cgcD95 zKao%i^IG(mUNDq*GN%7SnPTxcbH)=_A>X}vwIMcqC7cOeVFr6oE4GK*NWl^-9Ve{+PW`nfc%)IpCLUZPd zxvPg2clRNujh|JgU+e_AFrvj8xN5UI&=$U62U7aNL6u$}p#y~m%-adPevuCeV)eKQ z@K)1K=s>)=Ipc-~(C+tFmd;sR*1QVY(lQ!?et3@%i|0eQe9>k@kCT3xF(3Vee&ENu zmHR-bY%q|7wr?b?d}fx4DMLcn8NQQthC50J?HQ#IFE8&^Olu41jlbd9K^%D?J)5o`(EgRTjt?Ut zEr3pvnRx};yqb2PG?vx{?lpA_ilb6L-<4H~*!Jx#2(dH`cDraB$;p5ACsWqio?;APNP`(~W6m!1#nT+x8}9H?$Actm&9y}57+zZX#PcBD%1S?PETbIpwh4EV#=zKO z8Hk^A%XcHkxbq;o_={KoL4lplF!vlV{Igh#%aNwr2H8swb*whT^jq<>$y+;^@LROzO=(AWz|Rf)y`F|$ugN-*XA|x$ zbp!%nBN6wu`Lm5sZ0=Sl)`q7e?w&L3wb02xD|05Pe*po${`owDRY{xNcK0AxX*+Kc z;_=Zxsu)MZgG4xlTa&--!|kPfUIC)h8oL+&kFT$Qs&e_>_8gRsmy%Kh5fcHsK(PZ< zuoWcq92J#Nu>NQbOuN{cpirx4W-h1}! ziC4#^vTU3Z;lT2Z)na+>in;k{&7UcHJ+L%Xi?|{8S5h~1&}$)nr>2ymzsB2NFAdkU z*MKRU!pg>K2ktTr!|>!AY-QH=_^@-1Dfm5lx2B}BS<*%5{yKMx&_gaE`wSy&lmQSi zVjSU|4gd8ZrLko{hpId|zst6#hfXwAglYr~Q;Aso9Y2IMdhT}?p*Y{>czQJ@0hf-` z)@V&x&7mss{7X3~;-`?ul|-8v-Tuhc&pOgh*@B=xwNALs$f+3H(HGJX9;TPmP3a;9 zkkD+m*EV4i^2UfvV!@JK9r2(+OE0tKVJa6vOFN55W9FLT6k{f%!vJ z!X#I7z#|x)yKSMVSeE@g1eLe31BLlgI|w~;ui!LtQ&5r&EH%?E>re;mDWy~ASVIB zgx32e{>>$xGtnxtq|#gFBy9TX^D-eQMJ;CyR|)rH5zKtkWoIw`j|{Gk!zrQ)f8eE! z;2YsI))|7|vXDWj$dpwYE+>?DjLfla3Ol62$n=M;CD|bi zc-*b8Q0ev)RrNXZzha`=bxbVtyzeV7Rzw}WEldiHL zU1eCA{f=-|j>_N{;fkkE;mws-+opC`8S^TVe?~YfO%-4}7ga>&{*~J-JC*`or zNcd=12d5&gv&acj*vp{rw=9RvCT_zVe}>JzFuGkncldN*FLBDPCtmO_)!x%9<_jAX!ieEU4x5c#e>*#5iaI zYH?zB9U|?Odq|{O2vgRL#hX9mSd0!)xwD22k&0p>rJeB2%ZJZs`mkkVgH?WfL~cWg z9v9y^l%}0v{!4w36Xn&hI~R0n$cDWMfzrmvn8#;6ipjBTh+sC)o{!xEMGz( z)M&aK+tONP%^S;Vt?DlL904Q$@EqQ`4pa%}u`gzi&m((nrX_$2%L-IkvX5<~UEB?Y z7+q}43Nb73H2>ugnHN&72sd@{dac)GWb)uG{e;~-`sGHFj@KqEy)Eo!d-F&mr_Kq{ z1BcMagvsff@LkV!RoLMmRc&5=2K)@;Dtr2~LG?s`i^`iR^UevT5Qf=0eI!K|D)^rE2lYrnDS{DHa=!=#-ncV$HT_Fj9|XCc?lfis7I1R_B}^gE=Fi zz;=Y5)T1d=wr>e4cnEHg_z~``RQvB(&Xj`-K<#P6T+ zc|^D>v+#35&#+s1>_qbjNuw~Yo&2A+fp`4qKps~g{n{IiQ@Lyny;)V|HtsUYsBw=W; zA!$cX;%1jE($=CEG? zn!_Uax6qpdxE12QCX9>;Wf1dh-STh*U3a(E_12CBkag`Pb%wBw!4f|`=E1sJurV#< z{QChJk}fM_iWosAwzy-BLQd%0!d;PC7PSq}sbdb|X4(Q@HV^esn#(>D*6o=3O4qrP zZ1#4oqe9z@#1le~_|4`*w|GzTN2-MF%0b#IuhV#IMCZ;IW>DC+k=-YD9fW1}S1{EHO+~(1%q&@~Scv-|HYf#Ao}?rcEi7-y8jRLjDM#g$PI%~^_j=vx zL=lZ_dkFt1NXi0XgIm$~4r4Frk5qET=e#=J-BRec@luAVPa;bF5l=AMHfJ_XSuVQf z&3Gus56ctkCt<{Hzs-96%;+zL%oVQVnOV*MN>i9wCy;NCM5=&LyJGTtTHATBj9{%1 z^B<@Z>wP14sBh49b1@_-Ju#9zgUJAui0*k{Qe9K5#4nxEml>*d)|O%U1LepbM&|>1 zFRUyh9V8IEnzR8@ukT?dpHOXA#-E)~*w90WhcuNvC9Ls;Eha$_3z$Q}i1beD7)(s{ zU_PB78cCg`rU#*0&DK9VEJOooVinvTgEb&9%w8FM2{(G2=BXIif~ZkwQP}aQ74EjmL4ldWiI^s4xe707RH{dDJS4=tPC(7!LZdmGc;VV zH!BQmis&gVQ(a8fO+xD6i)+$;)!+tVGjv!rdziJ}K!V3s?8-|7Joih5Bb-;c*8-hX z2}SP>+dMkT8*d(vUtc8@UwV4`46DX!(zp}moU$m;nOm-rR&3xaFf3NCP6@qh_I1>A zbvXe6FC#<&prd!aZdaGqG8cqXAQSpHb9SNsz%>!t?vyHqy;= z(k#rJsKp1yq^n8TfBCGHdPHPIV`#f|kwQi>y0hc5f9Q?ex0RW1|fY@*4;*WQj82nY{oPwb~fB?Qf$JZK^gV`CY9&(dyly0JSobAnckaz z30*s!FkdzACHKzL>k3iH`VPf%$P)rWqD6R9 zx&If5R_tPL>Ev{QdOtbkI#oxaF}piZYpcAKD;>hzSG~{aj3;N9G27lpB~IOhfs87i z%XjDvyBt7qmhvWKr`*}$ZS|PR8G(+9wMbKF^nc<1c?<2~U3fbbLz)AJiMl}eB*K4@ zj!9x^n*_o>Op9CeclWy|p!*v1ipmo1c5pbZ*Enw=FF|Yk#}|uzJ{V6F6Ia9_%#LnD zV4=nhQHd^GglB4atIudXYo0YoMx(Nj7BlL_8yX>Ti0~kO`S-=EvwDj!48a|wT3%?iuF5N!iE!P+>nCKGksN^ZbFeO3 zF2eM+%fUQWOv(YFZT!&Xx<1zDdUpXz|xMQ5)aMv~Qp&$#YnFFU+76jK4ZW5R;7A+fEy zs>C-r&cRn$|2Af)p0MRdYAsk;Hng)pXeG`NzOM9R)t~H>Rb`%q7j{!pPPl2I`nk?Z zDvVe6{WLgpTUJMy=6~x19h{OY0KelARh2DrY9bsnah0(y)G24t^vSUBZR`Y1gnf>7 z_0}6Lc(zu|Dp>1oRZ>n9gq`+WWpe{@-j=V^3iDvTXphC%1W7mHq(Q3NI!}uGpyd^< z^t1?@2Yp}jC!0#JJ>f9yJ>~3AxbwwUEya0V7@yM<_eK~gJ)|WhjJY^>EjvvvLebT_L9AXZXWll=y`5D z)3>aMa>`dJorDXkADg77GKI95vYDSd;$&7A%rvo5s|g7SPcJ>bt8$EtE}CL<#pF+dhui;Klougs82yWX@~75^Y(Og)&7B4xzTja_k^A zQ@f_NR15n&3BOvax@nnF3w0wNxoX`)-HiW{(n2lb%Dxrh5#7w`$nG~3v{`q0VwT`?ZqW$P-ZasnW(D1tWOcrdINt#3@W|-OHb@&rDjYMc}PBYO49T zrJBODvZkdhN>L6-V?yY%f9D7>2)wq4W@_V-t@+{KSTLO|9AU|uolJ#a5gec{E{LM6 zEOKM0rD82}67JYPXq+D9JkyE|q2|h5%*<3BVf4e>S$}3SVK>)@nkhpdWt54qb*VaU z|7V-eo6BP`Phju6+uj^R{4dYSHIwqQ9t#wks~J%+SP>os zJ?l@UU7$*Ys9Ql0GK=>`wQUO7Ci=QG%2YWl$DXjS-4#2M7FQOwEXvgAR%21MaVxd( zi?!f?>4EY0h5X!Ut%hZ7t+wK#kc2_ve;jJ9uFwDY)>ce8_`B~^0@v24qgrfsM0HfxV3{4{u@#V3Y)JRTb@+0EZ46O+Ft=r) zR>~^r#1k5u?8UYT?cnirmkx!hfEnY(mgmyJN1BM6HUjgu{`dYY#X5KqCl=gMZOK`M z##jeIG;m6wS~$M{fR)a1U9h|+p-l-?3%5K4xgW&b z>?SH{7bq(khqeo*N8;%cUP+KzgxI}<^_RxE*937fMN-2^S+R-II!P6 z)Hdw(5Jl@93tsW=TC@JOg^j zIczkvdSa=jO@;SUl;Lf6Ij3Ymw>!Tzj1z=&!gvi4-KAZ~MTZBR_rn)&N#_bPh@&#Q z%c56ze;*VxB+{HY$6j@lN4`u$;5xKPswnIY^{OQGs$cwMZ()rI7nPr<78%NPRhzg3 zH}2H5Rr8MC2_q7=K=R0D6PCPDYLkxV7A&`m+LBxWb0y)M$V9lfxt-yknZ!!u=Tj_f zW@#{JB*N4Tt1}YQRU-w+Z{<(z`>86$q7 zYbu77I!?Ir%=cM(eexLVPRD3mNttRxPv361;y&Qz1_asI4yH7!)1L<-LPkj1Z=^eUGhk{d~eX4F=^KyZO}? zLdY3QbuhEq()8?w)A+%rWih=`K?W12u7jf!cz14q&%^`5ug5=~*R>)x2F~N>l`ju| z5anmJlO5dDPI@Oju=}yCPi8qm0MgA^&vt6DP1_1%Rk_!P^31)h+L6s}2Mzi)HPl#n zA&<-x`sA>4LPLH8%X7IVsIqafpq--1tE)n76>?&UNJ3|~wUdSIt{x)ikA~$Cf@`g5 zAjB)jk35^?C_F_YJwd|sxPpNsOK!}xzLbp1FcF86vhg@@1N`jM05&ksPb~uP2hh^| zvL&+E*~W4LyyK4hYORMZBTl%n_{P%fs|oRXHM??6GG}h==j130mefEVfSiF!b~e1; zNu>ESk(x3LKige@nl0MZ_(`+d2S1-Gy{R(w+nbB_eSe%WE|VN(t_(sNF@P}XOCH`M zAz9!(t>P!8w1FRT=S)X#s)=$F*6HChRx~uTp=_uYNWMJi{9|dEh+UcW@ zVzOgJ_He4!jg74@UDl`gxxO1B)VzZhlVIa-z^CL&1H9Na;jE563lbw?sc4j=k5BZ_ z8>%{urB?PpTB`d94;mQJ_aor4>icCkk~cS&>91#SnC z&xzdP@O=a_UVXRZE0?O&wrYFse_a3TH;Y&;4$H6Nyp<)^a@q~}A}^1{$_ zVshXlG;9kR$F`O9PsJqqVSdZ@tagDs!B8I&i8sxnTZ*A-U4U?*#m{gnQpJ5Y(rk>66Xi^I7Xwk>Ef)2@@dpFd3dUR`lv1mY=H{V?xETfQwwdxJ^ z6Ke(}3&Fkv-k)gc{#fiKQYrTOzy3I`vr$uAnW+{e5%x?f8A~&aEt@gDZ2D}8bXRlGiBG3Wsu4U;mZg1=dgaK z)yddomAGnQ(F_NUZZ|d}b1K?(9zwTpd()h0m0O(ii*U@ug^WbZmIcpJ**Ff?M)56x zsfL1nLdPS%D|A_$l``NYahq_p>C#&4{T$gSU7B~hYHUF2Vv7f5@F+t89u%a^gt^L< zu`F$xs*3Wxk@%IcdO)e6Y~yTs4vd0M9#(YI+Q8X=rFat!P(UCct2rP-X>a(AE&RPtEUgZNYx zNkyY%yg2tAQcV;S4og_FgGQzlOP)iVPsRfb<5~*l5#HYUI+di~mO0Lnv2+@+etoZm z>uQ8ROh?%{Yc(c{f%Gd0mo9Srs2f#b6V(Wtc{NWSCE}i6XFym|eutM}d8=@)e*-Ee zx(Lm;)W_3*a=>K+PgU4)`y|DVaB}Xy*ykqee0aK4pf_lsooU2f-DvW%xCp7j7E$m_ zxe>Lv8JwDzrB>^>T8&%d;wap=%RG6PD{O{J+~rz`pQHY3H&7@KCpu0Y;ik|o0MSdh ze(jGdw1HsDiaPcCSGbch6NM=g;oK$>6aVa#aN><2g2^GK0qpC3wHNzxXt5P@+pjLp zm8HUdbpz$pX;BH`&kxS#lu>LWSBB;;m>zMB`R-Ty*w*nLS@OQfN@%qB<1ZFf5gP;M z2h?S(M~;_%HDP+was9>GDr29z61QuUF;86R5L~j*u9aaSz0@v+=Qi^ZvZjs@u6?wi zvWT|lFGc(zK!bolyG7x)%6E`MnFxmD%q=yxFjK@_V`n8n(nNS|z}#EHQ01*G%rs}7v9(eO>p-H3 z(7j~H1r~A!%~g$2mtnyJ)aGnX3k{;{{iQcV`*jQR&G1ebofbEbLau%b!mU!ZGCkiD zn+d)zJLq~=hDF{n#+R@rhT{os_$<^E;j^fNg%=Grp^}SL>GFr%k|P{``-v;Nzf%S` z=>o4|^ay<4g>I5$@e+G5y()L`QiP}E1tFVqa2M_L)?hjEIpW0Ljm827feGjfhf&A+1 zBGC|W+t`@-?2@a(YN)p2<^DmUCB;W$!eZ`$5=w`Y+tY6ot1M#ZT6aic)j|2-FLbVflIO!@8{D#o&T}P8P zK-!}q5w||zc=NLrLTm^_V=fvAvCHlQcm7h8+Kv;^9c()DHlkk<5ts)mu{kv~CD`)5 zl9CK~%$~Nr%8S^{+Z{4Cvlrol<K(9mAECVRD( zrnF)X_lLxpFtJttEHXcVToN1gQg`4or9zAMDm28$fk}abYr*gwoDSdklZPluSUI7) zsUC-6-_6)^tt7bsLfJhl=c6tI`V^@yp#)VCZzd78oH!~%k0+Vaj1AeZPtaFaX&(tk zp1csIuWz5ijab|?V{@Y^!j@os}Hi?Zd|n10 zJQkBOT1*dFBQ%CA`4R@)C3&)t4%lJd2PXU2fOjqV(X6#y0HY zcsae+g__J=QVCx^PFDM|;0-YFZKQS*PPW5`#Q6=>hAA@a?vE1P2DNObGtT8$(qT;d zhH}y*d=zhfQFs|YCaSBk`X|G!|2Sf>%jL_z?A;c19lYbNv1h+l85=20Fi0ekglR2z z$LoBHax7p+xPww#rW2;$n{FTu;s;NIrYI|o?f-ZhYIgksTxgPBPAwMuPq>BBLY60- zc=Kg7okLNMDSO~J)|csofiBze)z4At<}7C&=7s>7M0n?9F&ja8`fvn}EjB_H(>iI4 z{>b#=?g|`q*7fg5cckn0ui(b|{d)c5H62VhHZiIrT4MD^s@t)|HGjQ$RV)5{ZD!pT zwiKdOoo(u(F}12IX(KFK>I`#Vs;W6-i7kb^v;2c?tAYYeb#nn;0`G&Z|ot}s=$B*^KCVx?Ic{3W{*5(qH zmMFPQBXnu@?u}%n>X1$uG0WcI;B~pMC#+kkO;1wQc6>~);unp<;XS%0E3x#w#wFO@ z-S7`@%3_3(na9PocGw)Qu0~8rk@3#|kiPL+oWEYPiMt{6`ppKgLymgs--#^!?{f`k z?}2x>=;C-1hY!O969b>xUsT88brdY6)L)tJKT_k?>9C!8ZDC8?YZhO&NsSz zHP3G@E>)7z^FIQk=O>LGVcqoK&qPw@UMw>7jeC{qd+Jine(dc6>2Q*T{dx7D6MFib zKV3S~Pr%#G2i6wZswTYsSNPe`D5SIy(~KGN4UByJT+yx1XPt^yV)@&QO<1FL8dK#N z5=qPm7q8g6U#G{FneSnYdEPY0dH&jPBju6INoZ!eq6vwaAMT9Mq=OpH|IW@A%jo?3K_aD>|xFX5-<4O5#sw$l#h3zrcnMSUj> zewB`Hn;MX)e?I3 z!CSefaOVgM&T?b~EtubA>08iKDtl~eHYUmQXEQUQg2T}+QA8Mj{GOGbb`%_e%)giI z6V9?et#8}&`#~|rX2Ap1SB(BY>eLaPpq?|!>~J$BS2jZU?!|&uI>GW{0}enl`pHEH zVbH+v6FMR)vLnYK64xXVgq00v;cOc%WRo(Dt(jY9cyVQt41y5)t@o)VGz*IRr)Jel z{x+pZx$|0UY?OYIbA)|98lC6E>D)XfK4ByuFn#vl-hJ%{rHcWh6oYAvDhip&h=nD| z+>E|-lv+;ssK$)*dIJ`G3_i*{$qT~v@7iqC^;PUAkRcgYaN>zDg(zW!uZ_SIwwA>R zmo^-Dod{{@sBNa@u~BJ$G=xDTefbS{Kd0`|+JPG0jUZW?aAEZ&Om(#c7M80aAXx`U zs!zci*6-?vnqNYMWd9xj!;pw-Nk|BH0}NNc7qp<7OeZ}0=EwluD5jnbH)J!; zKnAzVEQCiFZR;zoYm~;)h>0Zjb3W8~+eWCWKEKYC=suMzMCrKLAqg$C3HVGZVhkH) zeS~IH2b!|R>!CAQtK>$C1_CqU#!6RKuuL7rPwlqBFZCnWv-CkYNLnQw9!mZ(xWU=; z!N6)#C-Csl&3~ggdbKrBXRfF*m#WZL|`OJ+GkQDNO#pa`Gqa9psipwANuM zCoyjKo`zdky_6zMI3lY9dzXgCNiepR*u{0Q*SUERA-C0Xj;n`JNKSbBPB2(W)mVs# zN|+>&a91MU|DZ-vmty+6@C@_Qb~%WI>mEOUCKS+jITYONF%*1*WESDNc_okW@nONs zKt$G3>3bxiY*6>fS9JpK!Ge>ap_gS@!n1iJ`{@Zt@CqqhQ&IMqZAjtE3}o3NbFd&t zlVu4@rgcB5$D6FxvfX5)O}C0pXM)Y5CyZM|$W0%^Bx z`Xv?73w{_f-w7IHB~0>zaCW!mL#b|I7WmVOuS$*4tMTFnS)&m~=*Znm?t0ugauM@t z_jI|EDucj&!=s<-2vW^2KvGx89ulgao_HiUAG{Ka;4Rrm_mq?n-rHzXp-6fhTKD0) zUs(<<;iJU2zjTgmV?ObmN5M1G8mtp-Hp+)3NSAFAzU=M!fDKBQy{m=Hcf)ZOi_ghP zOVq*v&03=F!Yez25~Zt`$A`&v%go3;$dCR6ak@&*uOcd0!C7)}WiJSqy>5j2hIG>n zL0=IOpMsy$uCJ{oXpCPY-6CV~^G5tlytSrl&261r)Y9SQ-qCxf>3A*H!FHG-?o2A^ zC*+?C@XzTOQ2jU1dZ#;eEgC+q1bG`}v~w-W+aCA9eMXvrFbv|b+Q5~tECCB~ky!uw zZ=#jcqN0je)_s`6rBYi7TdlA9R*!b1!x4J`m$eB*kL)es%W?Uq^)g+Y3YC!tO+z@m zY3^4c_R4CAXPN1kEc8{Xic4tW6E&nZDO0e#uQCM-9(v4(8X+w4&k1Z^ZIFSc5!jJj zQ~U>?M#%`^J>QGQ#hKMaYzEoNpbnw-W;yJdt=E(M7XI2GX(*{g;#wJC9*kYLV>901 zYCo}!vwda?Xjq315DkPQR(x6|X1)DO@ls=sOd^c3YPOZV%TPDvLN*y*S^aOTm+6G0 z91C4)jEC-qNUbJs`qG)^7CPRG6Q(~msY7`M8Q{Hp=6_{$@!N9j=OyqyX@{&}FgjOY z?YTqe!IfY}@53#WBa$Y4-E{bP1O968pS&Hp^g9Fzo&t;{@&}cjfd`c)=#^H@@>rmm{!U z@z;V|9EErk!NAw#8sn zgvosxZ_tH4u$H?P?)=9Z`nGf5WBTb=5v`Q*3ud)V9m$ELhN}2lOkkI4Ac#F@o4OhA zBe`%6hp)1bk_L9E8R`an0oyP`-I8s;hQ*w#6feS?;g>q;)R%YBkWJ2zOUh^{;+ikj ze*B%`dlJN|yWH$0-0`D&U0rk#8#|W~*%~7Jdj5Ia#GxTm=rW9qr4_V*yHQt~Ou{*r z)^b;<4y)HnV`bD-@QFn)mJ8&M80)3S{4SAvlCl)%yYM8V#BRdZ%@eBeRL6EvFVq?V68d(cGK9(XpE3EHg>1F8)tSb zsM^<~F;3-=f_`Bm1D8I&udtx^6}n1F2+gv~8tQ_(Wm3mr=GI?=8*VgkAd#-e;wb5= zmmr03O)(1t+IFnVo10Y`afo`gCzD-rVgWYtC`m>DzH2_o*AvT|glZ3`C`iBc`A5%dsHimCtY@aV$^ou%d$Ie%P zZS;MnDdEt02p^)=l4e4ajt;nHG9KALvnOj`UV0Y$!Sw;nL(1v(H@q<()SOg9v`knv z;(&`TT^tweh~t6*)h{|xe_C^XR)H`-Iv$)rcHEA6mz6?gb6+v+OR*S#=HLhFA%9+1~2X1Ukup6q!nKmu)*60c_ zk|-pcVpol?BlzG7&d&!;ezm2l9zQpDO4*FUQO4f6oi7Mo zM1RY(cIBkaevEQjdtCYPkmh=+f~hQK`f*`%@=KxL`|R=BmZj7t!f8{kd+GR6PYIFJ zJ)uRhB{-}~%ztI0Zo;L5KA>KFQ%f^(LCVcX)M&}h9{{`m74}F&*rZNiYnJSy_OKlh zGw_8>AT0jdsuT=b(QlK4sJbo13V zI+9?=6lVlIBTIsgL){`wlq-=U6QN<{AMaUS)xwr|rt}Z+i|8N%)kJuu>a??Z?+@ZN_1FvHW~mm~J_*m?_?%YDsP9@Aq4C)KSBZtrHgiL!(aZ8I{(p$uO~ zJTy8y6azh89=9UgtYmE=YbN3ep&Aq->L4taa4=n0hl^vYs3Ck=*iN#I@JGp! z4aE_ub53X`;yvOaJ)NY>v#1(ouw8F(+MEu%2bYw4j>W*qnB!i+mPJu!%U6uW$I z-(OU*dJa+sXCp)MV7qpI^X*<&@NG#CK{sLk>B??@XG-giOgU1@2v_d5z>P3E+{G!+ zbdY*=8PuJcQPcMSaQM5%F4aMLN2BZDBy>{Go;vP`!&~=YXZ@6`aNGYJe&dfA{s_61 zOE}>QBEkH!Uy-zN8CdEho%f_Fh{SeJ*s536OK)5@9Vlg*aKWSp>3aQ~`XBsa{jbMc z2)xw>%M;F?c&`%T#Hr`64S+K}V9Kb6f%_89ekIA7rf#4NbuoQ23l>G;W zu=e9eopj zGj4W%Tl!gC#iV0DeLa82>GhE_qW(dRz2Yv_o8wmB5E>j0*3MU21r5$W#2Pu^_#2%L zhMf>@RS^}j zCvniNtkiYF4o~{6&}DLA$z{PjOF4NH*6LCNRFc<8YsX5qWvKzAMbP8qN&9If@y?PFit7^De;$bk;x|8$FAO$z?|Q zwIrEttl&Hj?5>1F6Mck3Mp!k{>5n-}tD!E>P5m(p+_;ogxVKG?9azHC6sD~yGn_-= zGHxMlXt69-bn{^h;|#OY*eh#kg9GtPkBjO3geE3gOTDF!EB?CH_L1&qOO|vMe3RS! z8p4l$Cew8D5#kHhI8~5mE|rubme~oP`CV$RR&Jc;VG!HlQ*&19ERG%9Vkv{)_HeIH zO|W|)=3idjky{9J@06$H2{#|CiA(s>S_vagTLin$uJ52zV0)H!4a;qJDOrSv7AK7O zo74kW;F|?V*Pih8jiZh_B@h=6exYpczv}VAWqhl^w~JHMhK_|Fe|j#(h_H0+@A88d zqpUF=N!MY@DkyScMfY#E-g816oo2w%)(}ReUPKA1O`IG&gc_U|4IcJq2FE|5rVUcH z?{$=jJC~lA{x1Iv{m3?3$*AUh{L<(5GrW#O&jl2cV)Msl@ODR|K6+dpSQC?qen`03 z=5Y9obfy}fE*>wlhT(9#jjiv<2FOXzK9g(`)<1Bno@i;nzp65YCxB~9wh(q5ez}-9 zdQCal!b9>Ym=sL@yO)o~i|7Pt-5HGaPlat z$Mn=+ZI*sI)Pi~6l~0~eM6oXS=RarecT_^&k3&o&4$nulovt{801u|@in3G6A}4i$ zaQn#{a7^g2v{{Gc18#l5!^T5{48_^AEzjsZo=m*e6Pu|LV*DOrTx)8?FKVf_NOQBp z7ji~RwIw{d{zDtug|=m7j)@9Nu-Av=8&+?zo(rz^HCqJRIALf3`&OCq>^ubn|FtVf zptBylg%WIgm9SDqd&F$UdK^(j^Uzlp{LrxTZf4yHn{Qh)RU(>6U*)*BZ+lZ+59+4* z53Z#$rP$4U*?Gd!ng`o;c|_RYD=e91(guFaNz$J6052V7wK2fQ(O;^JxFS1&MV*Yy zMz9^9RgGCncBl)>IS^&Ur%iHth`WRriqFCv^<342CB4RLrWY>bO$hx*QeOOS*+(xu z{2V>aNRoe_G!TyzE*W)N&khKD)B8v3Bt6A z4`Xzs*|7X07<4+1Of?ct8$CRU&W+kK?+3W7;&vqzPiwrwXU=n^u_3(odBHJ~vwplq zHHz&%GEqanv}WnAaPuVit-PA@0FLqZElXB0Rko^j>SvWX_11`O{2=9JJ%rt{bqB4k z69G8;fJg}#`BG65JV1%}{AopX=jDXjv%JH&T0KrqEQCJm51G;_ zT0R;!L|X~w`#7|?^1g#;gs^*q`Ci1bo=S0V@hf4cW09BixPj5MVGWPq=3Q7>k%{n1 z+o*YZ^trsjNZLr25{_BrvYE~KQP_S;CN39Gk)A5yqg9_^y6I?}cdn{3%fFA8G!4FeroDVVhxlBo` zvbvwmSkNg*y#8D4S<7P|vTC;IVuLTLx~#`n`B48(h-UQ_b-EDweR*x8QCsHq-qVSF zjahzfXi2BV$V93`_~2K;y*0=}|3$EBU!dA;f6ABl=xyg7)dp44YY1sZ?Dm~dJF6`y zK$Q?4AF5$WJf=dfe!l0TToo6TrDQ^@w?4Djg(s?5PS7qGsvbivwCw&XtXp3{RyAek zUgFKTfXDLUR}hTR*Z0E`+3Sa@7+$0|1~uAyW(JFYs2aq7Sr0pMzuGWZTwNujZz=wh%AoPawh4Ow|Ic^OJHd!op4FO-Vf~U1JzL8 z;w{X6N3WHBs4LNv|NIse4!<%Zhe+$fRy>t&tI=KcvDI!N9**{5LaHk@VB)A|!oXD5 z)q0Z&H^_+}<@?d6p(1vPsvT3%M{__5dD#lZ zut~SMOLaP1mlZq8yL|v)yiMwBkZxDNhRu?*lDXrool=f zAIYU>f-ya#=KIoGY9I>#xG$Zg>rDWs_!$h;pkD4P^?0~FPi61eNxt8-SdJp$#0LX& zg?oW4W^B$0ysfO2!bxa3tp^TF(Zmlv88M&7P|y;X&xzlJ-(US&tm~9G$NdYgQq9-Jj(=j`C3S&)ej#so+eGzb(!A ze8h~H$)hNHKDx|yle%>1U{!QALa=8fQ0dN@I}kj96bW+b|uK zmXuqB!(L$Y`d%`@gYdUi12~5>!QnPf>t_m@mD_TL2*A=Qve?4zWMeqFn2K)WLGH*G zQBKNJ>Ae!(PtIA!?jBPO0q_UKEQReJ*ew4KmFRLefb4AsX z#Dj{PvIbYA{0>Ia?2~2w(`z}-Ak3(Av*^JHIK~a;-_R|P^$@0MmUSXBTC+Kqq?7j* z<5)Lj7=()SC+Q?aq{nZ_Q!O9SJHq>ILV63^f^-oJ>jV)U)qHeIQQI2@Uu3N=EkEJ4 zpC?`lp7I*EdxkkHxpLJ?ILRwzJlTlaEYGG_ zBQ^>?T|BEYT==$^gECgm8H8=iWnI+KY0Gjfd$}lAq`VSd`91WB9#yfIrL;JsGbydM zr?SkGsw6HKqcM3KjY{7ugbai&{fTMqTgD9-mbyeB=J>S=C_vM@+VA z6#wHzwrVo3Z3skr?uT8=gyQ;|_A0}+x`x?1(Wfg&qzSv#EEZEJ`U6?WMO6sPG3w>a z9ZD5mPp5o@bJqq{A;s!J$(HP#F}{;|NxJ`p4_rI~s2{D_#ZqC`*q@^RxrA9OKcpNG zrcEvzM^k=n24YIVGgNu-t5I7ai)VV|g%uJKM}+iZt~n}kbt)fa&v%MATbMqC(nDGO z;$ZY+SwG<>_nHHV$g#Zp*YHb)V}40&^f}cm{!5%27U5~P-|D>AK>l+T*si9zzx{ zpd`yr9+lS{3e$K6X6)C(2s`GxSKjsx$NXVf_OqW}KXNm$m~)*CI)|W>)O|wb)0;36 z3=U64XI=j(oU~EF%O@M|iEW;@J5=ISzzdK!yi)1=A_@t&+=ex(jAvKtRu@$gHt+da zBf`fQ*P+S_yHvurZ-ogkF7oyg5#9p%Hf(!kt*J7^Ns2ieF7bdw2yDv6 zStsk$M=xbBs!qept-Imc64MFqjJ1Up?NE6#pB?g@|DE`G=)?g>b;U$@<{Ko~bx%kT zz7uJO^P*S?bNa$6;*)HPA^lV%;k$+N5Rs$EFdvhx|43iF40zt>xN?J4O9M5a-HQGE zNAk2b(kizLc}?#XNJs9g5JC(Gc(*o1=@_iEv%PibB;x zb>fT4O)82068;m{KufW>q9#i#KcrX_YI3LF7rRkzYYQuCITddyESHlw;oUvq$LOoA zc5K!Lm0~GB)j}o!Y-K(h@u4o)_25`Tcdhs&L~SSqahz~vH{7Z#6dQZWqbL?~wj^}eo`g?=9F&|VEWSPawT>^ssQ#j*WIJG>$t28(Hq52W;><$ZD)$A{MC( z|K~V{FM^@{nJOO%rq=}Hy58v~C1??JKd}j3(>+{A&_d`O8izHO)F{jXQ~~xx3{x9} zYyZG?C!z`MWA~*nlSNV=UPJw-ysvL0MV(4*-vqhqg;*q&Agn*^qcwTJbWYw zdyVb}9i%A%N{V+`7+AW$8lGZLk_;gnyCl9ICj&h&XKvN;g7$H#HH781IN?!P+Q=by z0eQr(b603)-Q*AV#Xe)fQt2a4!9=$7%I=c1^JdFHw+%~Qj+dtgOS?qa$kC7=t(EDZ zs*G|57K7x6u=ierbM*0HCr%JLWx_qe2Q@?%!U5KO+ZWmdydp^!=y^@B&rB|535)fw zky@BXC@Sg2;EJug(~KZaGTwyjBpor9pK0b3WWW-Yn9nyt)Q@hQO$xG8Yt73;h?ViwCthgPMp$61uc@Z^b^gcY4q?ur?Zr=MMm zxw@b9NC-Xm^uvcbcNCV7Tm#QwuT(g~X5-G?DH3wgh*!FF4}78RU-I8=qtlT%sI^j6 zhtu@~v+LO7@i~Ru$MI;Q?QJ@?f&HZ95q>K($3w5rJX7nHQUjl0AGyzwMm9R)#X_3` z=&|N^JV;{2$&LPyM5Agm#tD;D$OXi>*5hml-7qIs5Qe%hZ^h+Gkn=koR$|Ty`JC2A z%sr6Ig$- zu^MDdLn4tum_4sEo}{Ozo48BLs{-4_*Jb{L{!m83tm^kL$&+xsNtX^C?c@!=Z!?E_ zUygwQ6Lx5oTvTtzRMOUQ;5WS1E3khdY$hZuja6IEF?5*iJLDx%MsNEuM#tlf=Jd3~}VRU%em=O@u$x`wOADsRV-?r2_Cp^=e5wITr zNp&V1HK$RRKPj|ik;7rWI!o>o#(aG=fpoq$AJsstr6y(0%O#Omy&*!{>ad*zL{IDqn|;^m|_3OV<-))_tQ~eDuLM^v{ZD z!j6_Q@M0644a9T&O<_@cKb><_bT07+jwy_;VIW#5+Y0CG3$(ZePaWrJExX9Hf5G*P zaVp7yI4WK;dj~0UI7(ICGn+du6wR?@eENoHN6KO9bJ(4+Xj6NLBt*bR3z4EAjDxs@U*$ z8y}G?;YB~2u_YZ1#CBs4%yOAN$AW}E5qVIQGh;0}8d!6pvN28MG)%>VhKIm{3JnZ| z>qS#r*681-^@!S|lFV#e7WaPwbH0cov%F=I>CNDpq?Qd~jXN8N+hQXM5G8iFk|Hwp z@HDXDF|IgIgIa8Wqd`edz$09Jc^%XtgqT&8WtTG$AA|72a&Ljzu_QeLLYyQ4_xoaB zdw%jjafYSQIdm%NtGXnweDPO#ys2P-s#v+H2{qX}A32DJFx#5=nq1N==H@P`*xnM0 z+z{&c{xB88sdQ9#DE>58%bK(-(pj-=NTS`DW)^nzNmua__->oVj)|$hv?Nb z$w1cB3Y#W95)aiRd8^8nevwCFUTSg3BBuB>A%^GMVee@EQd2(ege?quqzF+;b~6xx z!Whpg?PWn`XzoIQ&IM0PDS)2SS?3(eP?_&siCI62yf+G z#mMffVj%pL6hWHMXnRaI zKU%&oM_1{**y2b7abArsshu2rccz}~4)`U{yFSD$RBdjRmV*1kyGib+p@EHqd!6CJ zwy*MPrwg|FI^ z>Yx0i7B+`oal!Oe48DFfG@!>6=-gEuFI|%1A4*G`S3ct>dU%ZVgg5^6Kh;Lrh?QBrXSu?~(Gla7!EnN&N z;rmaU$LOi|vG?+&-M$!+#-}se>-Fp(U)i(9V128%J;U_Mt^Xj)O}0c_G5k{{7V;C; z@x7;k_#6W5E6i_wHb&f#jC%yu27Q-Lggh9Bu1_dfEwt`;3#oO7;4{S8`ApGq#F;J7 zNXed(gBPmbe#p=>?(fPQh;J!aRWJzQ`dtFE<>7<(gZ0=lvA!H?r*b%a?0UdTuM54t z6?Ppf!ie?Pu~kS0er*S7y;{JC4_fwb4e@hm;m@J5c+}lx&mu19rJ{x;_~0LBvs&(32&f=I65eXVF&p4Rsklv`IJAwOAjOl-YKe!(-DO zzl$(Lke7jYGkdI;L37^GQINut?>=AD>&#;(DOVM+cK!8iK`FMQGE9!q7kQH`WC$YF zTe2hdc;j78@@6N7(B*UWGeUK5m6mqrb!ph02KA-xe}O+VxAPCJUYk2w$Tp|H!%`TG@y6Z! z4a7p_G`yDl7UdV}wK=S?&1TTHz3FDXb#=P31x*b^46`(Rqa~J>XY?wLZz9tsLNa_> zfAAD%1uaiOt&nERM)Y`Ot*nv+6Xvd*l`D2nlF1XwZ)zYS1$2wQVXGN8`38Gx5WF;A z{$3L~09BB_erdsCA-kMWTN@dOkoNqx*hm_)^(Y;9z&nDOsF(M+ps|4!JJaQnokCl3 z#4^IKErap?zgZ!>d8VITA6fnp8FEpVFC})+?=>=L&-uClWvjOH{3PB)%xi2Qj&H8V zC>@y?JBclQ3CSpGH?P|xMB)Mr#HTiX1{kzv;h`X9q$Gu~>FjcI^q9d5-}N^zXXafW z*(-bG%9*gag~11*nuVD}z2E%}dhiL|p(-S?wL4SY#2XmgtQBT7$5%!knHg;pi$J!$ zp+O6FqdV#!ASogAyn88;i~Pc4lHo7bBO<-}+D4%WQ7z=p@8JhEFqpAZ=;ShWp%xBB z5P7L_x}F-}tqdP$No4~wZb&v%HfYJ&cpFzr`nku?6?&KP4RgKaIeE{aTnD^HwB!c= zypAtBkS!%#{YR8-y<&&o|a%5pp^zYOszPA)GdD z*jlmBC}fkNLu(DEWjI!*l#S3jy?!IM@+5?rvX$?s9Xw1s_;2Dj8;Jsh-ixOl6jDM3 zO0|uOjp~c6eSxpcbduqF!dv_5Ec=rmc=-1=E{td-QwZ-a*-=ubg6^rWaW!de zIjE`r18l3GL_QXK*Rf>SsFyrrK)!SwYQY8=1a5F)))yt)czX0(weXu-ktI(r^@`3= z3AT!Kw?__&4bq79gu4z*O4Lb?KUWtxyv5ooW$?r#PHA(ysB2z%r?yvUmyU`PZfQPk z=b!mldcNA6oppO;tC-1*gn{3`R;DxUdbIp>f8?lmNm>XkCfC}`F5OkvA z_?225obHHXwFacr*Zo|DnRq@bt@Ow5)LFufZDT%)SqjyPna=?~_ek7+LY%pqZHh@m z$E+cqkDQf}n8m3);n8*9;p5Wsit@0rFV%nEqU@V@s~&szujCO+zpFN@E_9)lHfnG} zFKtvp$DzG@Yqc7!Mtm%R1irIWYQkmJM~>EK%3a(YOv;7)y@3rSG6;LWOqoX~?j#x1 z4BNCFvyt4a)DRk;JdC5ibdU~{raPy_qhqtiZ95L_MK-0E)V7^icvHQERwq;5(C~Fv zwnJ*@b6x%%F0%@vW9{R$vC*-8i$<9qjv+=9 zeycsB`kz&rNt^jMwS#3T!uqq;b^QMh#Q$ki|D1I9_g#nnZ&Lry_$`#YC%hYP_gI{C zeSKcqF+P62e~n+q1PHi3pGQc_3D=I8gE-xNbxpR{6;4E-Qi2tPbx-Z6r)Q8G-hx5i zCyNs1W=_}W)?My2PaCpzWgc0wlstJyaVf@O?=?dU-E8cu&Wu1|B<;Yg(D%!hIRWxeudQHeq6f zSR%tquqfRuuJ_Ow`UVQA^?W()5Pp7jv^*!mwNrGAc1S{0OgzssNNOLUMc*axI3BCT zvN#-T&U*K)OXy8T)PzgNkukmE2J*r_vMYogzAo1fX5~G?JU&4VBjMZ3%kq^b_<6My zOUWR@Rb4OT(5YfCMh&n=kH{T*F1@R7=w#D~;`jilv?NWr{U*=4y4NRMKO`%J)@<4I z2eOC}6zkfPJP$E%^E#`PdSq>6CiuaAJybU--8w-#I11+vc}Lz#l_a!SW~~0R&wqBr z)neZ)y)jF9gezQuk7d(!LG6Sf|9HXb&aoP8pXgYva97$(ZV`6=xqJr6V_V*tN@#Y= z{oc5ub{|sm|5*DD@TiKee>d&kY|3sr=}QTrrO+XSBy>W6gkI7c5J@8mJ%M0XN`i|y zO1r^|KtiygASAvb3Q~fK3Id6W`YH$!6$>E$-^|?IYzU~|_x*Vua_`QZIp@roGiT16 zDfjlb=>Nl1`LO5CxFqV%O)6l;*l)RR2}YkMb~mAWe}{}L`wyy|qZ z=f=OTc4<{U)^JXG_T@KLo;@Ee$;J6fb8N@Ny`6}oeWI!!d!F_BW5S(!KJz{A8Bo}Hg%_xdn}04eM^_^*XRjHzAt3Tu^q)ax9^@(9e*8Jp}m z{PKrWMEs$6QGOWyb3x=jBOuuGDf`Lr0=?9@uJ=YTJbzoLMb)kxQ#b3={W3`n zbL96_r`-OSY2F^cc{<#1>k$8(g0QTdf>fav&#RW6J#{`K0>vD~J5!ybR0rWU^5AV< zg^B8G3dHsM-uk{17Z<(Dl0#_9NNaJ}(eV~m)P9co)M7?6V3Zn|V4sJxOLz|71vj_I z)K2PzAH|EsdRYtS zY9<1Rk3RP$&VhPa_oXIlmE^Huh!Qp~-N;&9gsq-}_Rk$;8*CBLjkdLRre|_6r+-Pc zi0nDOUq{zFfl8gNJ$R3N2|BsfJ^DeR-5fzb54As|#QT~r(^Ru1^QIT+JaX@aA*`axVr>xpE@xagp-1yRO1d%kk? zi(jd?lS+kcAKTS+t)n?C<3r8%xU#C3q^L^f13fO4SUC2KdXDbBL>WNOO1s2Z2}>Wn6U86{xn3J@-97h6)d&ukq}H3`|Z6)ta;C@&{8tF}p?s zDIoizv$R0u(*mt^Hs|q-)_Q{Ph}<000R5Y4yV$d^`E;$h-MlH-LDiZAnC?w!8HSI= z96?_L@c{ZBmo4&UECPX$QiD3~LKB1OF`c#eXz(*S>k+iu)!NP{Y&@o-?S{Dz{T@e9 zfLQ{R6B{#rLCEIt1B*|$&c?WUt<1Zqr7zr7nma-B>7b3z3tmkC9{QbVB_?q8ywY*l z9Hwj$#LEV_t91#4a*y=d6kwqc)wb3iWIO+&PXD}+Ru+5OF1kEYjNXc^wP%NdBH_@m z+pZW5_Do&=!*}Kp!oO-14Eh zLp!rp5o?a@n$7LmamOvpP?O%;l_KUt1md;pYgXcBt)GnF^>VC8S_|ifM z9N;Nn;M&oI0cCGZrqQfbIy#t!Ai+EoWSp_*+JisiV;-u13DwuDQfxxryFZP^J$TM& z#prp^c26O@EcVRt^>MQ(29aS~!(2pp4Jr_ORy^vbe#e6^A2T5D@dcUlxhe*#P060W zg&OmPcpyFQy7N-oM`WNM9tZ=`pkGMiz+mZg`(hqoM@Q1?pS}ceGW%zCRh(sl8gImob@ME zs_f|-;?`_o8d2Dj>d@%=I<@}nIckVT;Rq;dIHtyy`n{%e|4MZ##OT(2pXlPwJoZMl zY1nf>Mdlz2!^mkU-`cwB6I2@Pd1CInmrUJN977uoeVh4tZGcc2UaI^TocYR|WG!>G z_!APJ@%zljO~pcKcY?Jiw}lE^exHoxv>uzAC@mhF25|aMOGy*dqFU(d@&A6f`Hre9 zPlR}5yV#cT*7n@Yy*%DpT&mv(7qNN1yTZ*vzqy=Gev@b`ytie^qD9!#;rb&BguvN> zdS`v1sv_(e9C$WR$P$Mvg?gU}#$NeRmGS0^@`LnZ7}jItN$U4Xr6{t_RAedac)#n( z4_b&mf1E zt~;x_Z}>&6{voxs*t3Uw`Xg#UbS%30@;GY;PMgJF4^MshDx*D&aI9Kvl_*F2F{!-U z<3cFA7cik%?%4Subk;FCm0&GyGX4f!ygs4@P8qxOX#W9>WLL9P0yE&SO}M%Dn1yF{ ze}L-xE%^|8Y$M*dYGK71Qovnp1h}`{2Ac8k<1<88M82N(MI!&Cs<7<2_Op5OMD19< zH*Rs7!+YHVwd1g-@nYj3HtoQg1H(}sc~KUMFj#GD_FUEU%6+0$IndTbwZ(^l$jGos zwPpkz+&O{Ws)*V1;kQoGo;nQWNNxok>!To*hvc~x5ea5pEp|R z^w(6L*>lf$_g_uDk@M_LK2u;ZHmNY|>DS>oFQx~aXW`a)Ao=DIuS^S3{caK!+Y#V) zaf#|t@CuAeQ|AaBA%c?)gK-w8RRj?iokTks=BbHGp3)8>(+~z3G#F*|LFOQH2eN>&5)Ll%o7@K zs_3Jdx!%#R;AeNzs;zeJRkP4+-L9!KTzP4ggjgCoct0II@yEU zkQkrr*(3j*77IQBD7F^8eA}u&JuphG@w>xtCNA*kG>eH-N}xJ%vW8(h98!9}poC<5 zx{W`)p?;YOJ9%ulQ`>S{PtiF;;Uq9V*mJD-vc^{>E?l(JYY`x4 zRbkJH@2BR9exdIVVK@y^t$cR~>W9zw!?|SBX5B!wOFTFh!Oe(B=R5FL{czDvnu-}E z(9+3))=^Y20N5&h|LZ7S-yo8E53n9XF~423qsIPf*SNMC!(Qk|_$&qs)N=;T&b#Dn z7a&S3AIM7d`NmEk@q*x(J=fi6Z1u<0YNc)Y#!k{bD2kmLgksI#p`v?V62;h48y5TK z9b8l4pD6b3L!#Ih{j4W(Nrv@TXUN&xFrM!2b&M_DiD24!wDPK>&-7@E$V>kO0v$}E z>{+1?oF%OLp$v6biZ_f*2RFkmp>+v=;U-OPj~AB<(tG~08l~^_sKCLV!zO;c#X=2H zLhPh`8J*c7}th4Ht00#gTx{>in&tZ z2MBb{X|Qt9&qpRJ%btJv=+~H+!bEhFIlsTXvGiRQe2-$qM3>D*@>~0tISNzDQLe1V zU5mV4;TXV}CMXB+5vX0&7xmr=DiQXKzW&)2)0tDmc@E&?1%Pp&(rxgIvCz!9Vb7eJ zS8)|DyCH`Mv`s`@>3Y4oqQK^Lj~p0SV8O-igI11IxfOGmaRL>6`L_D$q6##_vGV@H<97WIHY?CAUl z>g})>;TeC?^2Rx{2KJ=t_pF?R|H1T-sTzAeSNS`Y9kLP^8?gYu?AONBvs2`_1@c|1 z82{<%MLFpix!GKy^3{Uu`JhiCK8mSEIC#|zH1s`eb~^C_+A>##WX~=?Uq|%pkd=rj z%zDo%%PiD)3Jbp#bp&_L^u&wULcxU1wASH}Dt)H<(;~u#m%6^SF$kK5R9H)m)-uM^(|h<$}!WW%F@>#el@9QE7%cEv|!F zANk_#{bFMR&kM;=9qLIKvAQj*y^n2K?M1T(Tf1?+T4umiE}4hvOLoAqx&s`70ly=r z#)KC4JBHvGgF50>!#Di7$^-lC*$&(nTXo_$Pn-+yfLA7k6ML+HmdRw6{EIg7H( zx~MVJ*k+8DR~^oY0rvb1Yl$|`P$x{=XQLl&sDA#YdgVRe zzcJreW#{Ee_&^Ikc~A^=wrA9J`%#eJ!O5@kZQo*QFvA;{q}YT+iM=?8RpSfhp(>Jw zQ=0p-wlBl?a^A*>m~&m-;nokM_`A_-ZwTA|sX-lpS7LT~VcH9WMJ;^(uoByYL;kSp z->E1)KdT@wOgy-LzY4mnW3cDdKkOrU^v?9K)B_K&Ti8C`oHtWxJ>a(S>F0!$w4ne@%;Kbs-N z*I2ruK21?AE7*pNG>-B*w7u@WJs6JE;Ub#k1lX+^l0d|sM4Qn{Y-bqw#ugvVx6aa^ zYAxpU@mVuXD#Ox-uQuPc@%<}5icT3O#+ZRMg)SX_HJ!XTi3{aN*n zU$~78%l^HCEc)JsU{#Giz)GraZqOB>7%v`E{m1=i`GP+R7FZPVxvp*$y#hO(Gjlpr z+q@ppcdF`Ev&)uSww+sJkvAw*&Fh5VjJ^MbO@h?kTPmpq2>U$J&p{E^#rbn}k!%k1 z;LFH?ADA(TSZ8)5_pjwwdWL(2Bx6^5cDV##~t6oYJ2D{IWIs7CDI80VM z_DqPjPgYX7nSeK8%|mQ^{sqLnV|+3!6n}=FwL3R0`F?7rcP`f4H+}05*DMgYYE%S^ z1MxAWB9Ct@*zAKn&%!ok!!^!(TV3PI8HgKnhClPY1*zHH)joFPI3~SYmc{aBerk!@ z%IuCe|L#48iJt#^rfMWFJ&(ijK7XthR^|P^>Mm+_LE7T)JK9)qiEVJAn%{hn9nCQv z4qDKj8?Mss7>nUy`|CLtHL$W$Yv5~z8vO8^l@N%A+1d!x%FZ&lFCT2LS<0pTR5w-F zwP^c8K9g%%s)%^WX&%IPq5h*$WO0ypLCaeh9B?Jp0Zv-{K~$nDs?Gb?GU19K3t1n@D|e5ajO?R?H@xLx+2s=nKF zbXm9ff!L0%MvZ(pxFJ5{e%yC6WnOxr82j0WRhTVc&xhta6bf-)_*gaK7nyBK55|QD zW`bisQEl^ADDqyvTL;X0I=yM@XUrY?Ox?irJKD-SyRS8K1$v3Ryie6$_aCTax9-oW zyS{k2Pd-&|rk;m#??*Zd6&viMa#I^G;Y;BxJB!l>vJWd2iz$CUnuNWAxY`yqUu9mn3_w9!ps`>7PVe99sKQ)W4%krvjsQqRb z>h+4%)!)pz8^R4H3)fA&@fbcgVpb~@lYA4>i;C5aOHTkPYeDwhapZ+Y!4xOF<4@K4 zECFZZy*B9DawgUofA+!khKnm7W|E2JJ$egXIQ1SdHABuCcAJ?Bq=7e8Z=*95tRikl ze_^u|epBn=gEmNNnE9}|h&R1DP3?ml9O2$>s=D7I@1e13-birxT-73V>*CjA)Q&b5 z$@;*30fNdiV^o_FejUf?-<=mAc4YP)t4^!Y$L~v6(voT+tueo-QH-=-(5>I{RS|rO z?i%9Rc{^)~5c)nuoq#_C4Y=voFiCi3(f;aU(_z^3#df*w7I>{qTl3#QrD7im{Xn#7 zu<2k+?5|i;@oCtk*0r;B2p8?{&emi2%O9O#bH;a8Yd`TxT=G#q8CTe_srtbHbzCG= z|5nuCz2Y=~xlz4DU@1D~(RgDaop@5c@1he@E>8DbMDN()6P^`MYWni_+XHz#8};3n zZpJWWdr^T+&SW zhSB$;2^;XodxLtqHWCWE_|lIX#BDaf?dCl`dr>z3%J6vPF->L95ADtk7BLpUh=nc% z$;&_4t$u<7$(~fO0EeLaL&B^Wdmi*zok)LeP!I0mRG*;`bJJ>#UCLuk)wpv+wl$N$)R^>lwc$W?j&vWE3pHE%+tssZ5`GhKQt zX*Q0r64$la3<9FepQak?ZF^E>+r0ld(_|2iDkz`L1@!l+Yi_XLa&_f2pbYTToK3ImhG`+DBm z_qDOaO7L0$0PVVI->yH`h4Y?;-{*h5xYc;wrYBFxw}k;-d;eLZhmAOvVGR@6{l%}2 z8NIATkq~>VdA;nHXDn8)MM;L!HsirK2jh?G^=kb<)vlttvoX#llq1~_D${pue$_bB zR)pJG%-{IyW*s2>=<0ASF0VitCMot@@YEB3867oUx!C(_LRYdI6ImvE7RQt?G6@Nm zUDb!o0(BU)?Ib|i^T1~}gG`{#X3*lo_8acBYg&FZK?a#2Cuh&eg`bf_sUx&rdN-9r z_FVh%#fG=282iPQG7AJxn7cQ`W&3Ua%3?`5#SX-aB?vu>((rk$qmUi(Dt z2p>u))=CcJ&{3z0eo7tFCEO))SnEkCCE9Lud#M(o^?FBnZ}LLzS{pKiXl+LRP0fPl zV8=Dwov8(L=b~Pr_vDx~W!esVf&S1KyJ5wsa0zvc?S=abKG)*zyRp5%+G%az-gn>8 z$~Lz7*uR-in)kFRlyFGvFR>5drstQ?sgv5Ey+_{D#yeRpEi}5k?nj3G+LXQSA8TJ9 zvvTUa%$oIDWpr<0WF2=wc?ynoPPFA$?SIL9+e`4=R25YUnH^fT&t=rzO zd>rucs==Z8*#%gi_tg4Q@1N|C;|h!3pV)VB9AVKiH0)Pi8;1zO`mHjiUp;Ry!7Jvk)vbBk4l|3WmIbH#1Z4CjU1Jl zFl_4BQl1(+W@7y0QK=J0%}5;|J8{$$kvb(VHX(J?goLTH)Kofo;lExTqZpH!;tM<~ zdqvsB1q+KZvxC84@EoP%n`1R@@pB4A&CHp|D=1`pYEf&EW#(;s{D`>JDPwyX_{*r7 z>dUl=>dVC8QA)@6@l^#EE-aK2q)G}?l~eX3H6HSu5*pNY~0cHopPE2CCWP>j8!75@n@gaKUG zid|S>(Ndh84mAiA`ok;Zc?W6}-HvV}HEw-*=3Q9_3H17+lJ*qVfI@(vpwW-jbP%t% z&qryz#@#{eU)LkGJ(Kkb70&t};?OHucxIDW3to-a<~9cd&jp z1!UC`DsV4~cNbYO^eZ(#BUL#GqN=>^6rHF__`MK|s@z3PV=qK$x?0r3`;L0FDzCB} z!tx2d7lpgCt|T>?Tbt|CKjH83@9`^FQ-^3e+|>>WgE?AXzZ9nOR@y&WNuhYmO8%d1 zq%tWoPUEhGACA&E*Z251LKCm4cSswe$=8wR7XiNYGv|-fgqP8|D;g)qh={q_CBw1B z9oAP__1!p4UrJo<=xE2&M=6cn;xxfZ%(vsP%Za5cr2rYE=)WJQ(JABHMr-uSj`QOH z!c*$c{db%u>$Ccnl|wWi%~dXZ5Uuf0&VM&VxXLGHPICh;aUGseUv8g{_)GhBVZ+a8G1(;__L4t>>FVaX0ewc59d5u ze`Vr`RDO1DakL7UkyE0+mnnNvp+U;6?$Med|9=q=doEJrtt7;c)Yw(b=n<`{pV1>m zLj$a#1{FW0#c1$nn5O=xwBecuQk0Di!!@%53V4{TG@YGC;PRZn&QXpWo-}+){KOfflV+iTXZ8bi$;%1Fj>HYq2OdWZ-&-d2o z|8=?a`r(>!ivCnIm|v$GiHht+${f4la2tx2Djh$KMvGK#V0CML2lX^%6n-`Y{=i)_ zCe0b6>2E0$8-_}8IT48t?0j^T#!krq1uq(3R%5TE&WqIeTB4!RWi>kGr?-XyS`U#r ziG(Mw+{wqt;Ryvf`HH^hXiY~;1hU8|$yN%$VjJG=O<6_Com|?<93770C@q&FHJ&P` zj^H3tc|tcFy|A^JBNTt6J1RvW(1v+6eF{X-*8<)}xdxo>7C3#`K^=RgU9Cb*$EG48 z<`fm=F;!C)ppEvKpp@QFGcOBDb|LDqD^Y&jKb7B&dUQ!Op%aA?#wPq7O{Rs29W2ad z3i$V(M8&Ht_fsd)$}{{-d0VwPRaPFjmvasg2AP!y}_KKCpDV!HtJ9Y1A-OrutRb33NbVBb7;Zn4sL5xPDb61k&>M zaE+um!lH~-);<}jk+j@4mgXIh=MHToh`#*3ApL;8<)N)U0eddN6jgj zaPw77iB?+B7#-}*AWA#ITjaG9z1Cc=q`mMh3U<6W6#Y$DF%8)CbwM*^7tKk}%;qfJ z!EsP4+O}|aVcoSotg;?fuZ{B9O-Nr7m%UVJ*Sw~T_U+3{C|6;CRK~s9weN(S{Cgl3 z8FxX-GAxlQ>5xVwe1tup4~K_QhhIA7>!hKukKBqYuOp?eEY_Z4v)WgnHOrEkz+-7W z869t`Ids5FxeD|;fnIMyY!Y*O(G5vxJzw~@hRy=cWb2fUe`0iXH7Ry0gtE$Y3`|=L zriLz}Uruk$T*_6#Y_^!Uo!HiJne*B;NgFKl(ub1$WY&_u+#h_opX8k@y(?>mIRn>&Cgy8!);N7I|0h> z(``xXsnV)eryNdXCQyeO!dAQxiMeXUDOR@%t6Ke-h=}y8ER15qa!V$r=b7CCL6Om# zpS?6Ti;-&M#)xT-nvb%I#%d_60rO7<)j<&v=rLF)8<}2`4*YlXOf8V)6(WJHuuCdy%yqsj*XTK@GZf5Q0+U5Ri9fL0%sAH^wW`=-!^ZdwVFS zUxvQwEkT(ltqg-2`zw1;-5Q7aX5Eceww+-U@Pj{t$j2W<0SkBBl_3ChRX*RrhJ^Ay zBhbMT>R1>^q^AH`k@D^zY}hD-z0fMoM}}jn&;DxL*jxp8^hzV(Z7c?CPub)uE4u*@ zZ81V$!S7)fzr#>8gx>t4#zUEh*TJnL@=s@&OWF7->-YK}YC9@VR79F*QK?5+45a6c z8rQodryj1=)BcmSZc53=V^Ga`kgkr>hSg|^W!I(e&on=LHzPRXuc8=sz$ovXA! zfB_V9s@6w|gnR~CPnj~FhJAWBK5eJ4%gU5;h_svP5DAf1hSs)asNf_V2IYsw;hGpB z!i1YOZFyrlpjDdCQ1;5g(NP+oEp-Sk`9`;{l`JgEiRW9cu`a=aW6J%o=Drq|Lnn&& zfMIXFsY$Kqzl(C3@xiLoOtu$R6*$njqnaO|#%FFR{=PIhiqF(M{vgWT2j2st^{`#=r+G$F#&{-4@X z8SvR~O@y7QF{}7wQwMh;*pV+vOc8?=7nP@E`ZWx~G6-R@2&t==#SL40Y*2-@C4C%h zp@?a6{pHXBcS4U`DApDyfXk}{ zg;=GxcAR-~(#n#@oh2q`7v?Ti3LuV-oM#&bK)2Vzfc60f*LIb1u)v@&^E-r>8(@*l zCBrO2PG&YdCoz4EZsV@R^B6g%^XBNYYmd8O$S%Se+yVeSF{`>wDr2VI+3AS#d?4fsWpCILDFoZ9^ zf+2pR-2X(4gM9c<_z!C9;6J6!ErJmd#r(EU^%l8SIr+G#=vuD_Y!#P--#xJK+xje! z=v5@x7*w~nmM?(2Ugx$-@5K)9+Vt{+Cy@*6SEgvTz@Nu zW{SC9W9ML*Y_?MlJ??=gp(uM%PQk)r%TjDU=lOTYhTa32Nz~@i=pV*42a`cCH_hM3 z%+%XkVecWbNR_)*KrXTWF>@gTkGa3JT4llI-&Bm&i_#Uu8MVMAGhH7 z9@6UccVu#khb>OeQF`|o4HrVJE>)aIl#AJahc0)Nw6G_C(~N3AF-z65)IC_dQxcX% z5IOrh9^2g_YO-F;>iw%`)ZI}_T3J`)(RQpf-L2YMr}k9t+FJg1;BI3#OYR{J)gs)J z*x$-SmA-`u`@V8Wa<0ju9Sas_7cDgf#BKm2MqP*u zP@*yOl$1@FQn)Ce9~g>F8*lSDqewsAdo&^r7S=+kM6Q#P!KNTsW%&uXy0!~#X;rA! zwJ04=u~AN<+*r`IjDa$K+<1 zMD4oZHHp7k4=c=3POToR>8#vd&emzpVt=8tA=(s|%*w_(LMGpt&7BHU=x-%Z2JpgZ zP-8!IJ+XGgsPbgXMKs}ZnzLHh&~%&!e~W5!Gc`6lH@9GNc5xw2CuA$9o@a|oJaWdt zB^6vbfYvc>wrC~M4%>Kq7HC=_J2{1w)vXYJ2Mh6=krg~S1o62$1sHTEYm*BW=4VaC zXD!$&ttrG}(aLtBz}DX5(9f?{4P`4|d@mkn&`}L=VeKoUK+%AIcct*H5$L6@@qBGe zD^S*=^!&{15xEPCu>fH~(G*P0w8&}Q+$EX<<0fDKVe4!h4NSNQQr!hnL7P0FqH)J- z1C^gyMAaOXbF9D~yFq%E7Vln zNl~26<6vs++f+hGxeZDSV2lTfOP6tIUyJ64zo%l(DIS@Fxmz0gp~1-_H8x*Ksbq7t z)*()7%gZP?k?zfu!$hPF^V%FcG| z6;DRYn%zXBguTv&volY_*0qoD26Vkwc{U8O@}dcpbVy;YM|2L(ZeT#V9|uPA({t5; zF|#url$a*C1G;e{$J_v|dEULINxQQ z6|fc~tXO8C$^$jF${`TYE6v{wF()1M@=05lm zY7ZVK;a9L?jlXW@UqkV$H7^yAt$8n7?eW<2!HEUcmGF`=CN;N&tA7-fZf7!5dq!fT z{{G|<5d33!cT_IBW1EJ%Ndb#-(QI~!s(H(u;5Nh$^cOUOP&&;%ZlHqfMPMYRZ(@_=%|#<0pKJDP_Ub0SE|02hNE?+<8M?RFBzzErDQ`t z#$|M(Mi=-4l^DwTSOx3UkCJZbj~0p?2sbMW^2GAV*$)<{}P%aNQYEh58~&gMvKj49o8 zpw2X; z1zh515Y;9nxiXB=#y`7Rg6)gSaN_ASI4Z-1Hme1?P}tB6FVg3N@{yPfSMs|mFm<8E zSxGMRR~eXQ{2HBmdNA?>jp1D#DCuiKUT2)x)1CDBsJyvS#=;;-XRc)u)vVOw18Y-J zsl0g*&($eOUbJp5Q0q5HGNo;j?2HAI9I3@9btC;yNO9=kB!4P@S{h)yGR==xJ}nKT zVhyhLVmrwn|ZmcgH&jvKr-N)H-CXUO#ZMrkNVXk0hFgMiE* zm=wq$gQ+<>$%7KQWjN5yViPMZRZ`~#97#VsNl&w?q%HC?|I69h{yD|Q#z7{|faH6n3Ki`_f5v9`GvIJ~ zYbO5e7?Yu+|FRY`0goU`2lrf5oP+XF88S7^kh+s@Oopd9!LrOrENkg)dd`UM8 zSgPZ3pm=Pc+=acpLgD$4SK+gggE3*1oiVUHfL6XD^;CaojptXom=c0aFAU6<{Qi^S zLFKPVJs2#ld{>%5`-_5I$si@$@^rfOpA4_6{ZfcD9Vbn(1W1eDkcJu?6P=8WNnOZE zkp@w8wUkbQp2=ErWNpFtpm49`j?~}=EY1p)yjQX(&D{#vgm2MX>Rb&Dt(m0%9(}30 znxpN+zHXk%FqDrf*`-6M8X_d!Mg#jiFI zpKw$fMRof!M$r|f4S+A9{8LFC>1H($>7SQyGvtm8Jyq+IWh#F;!%@K1?UD*uZXhlD zB&jbQc@Z5X|0OhQ*e>+st1sYZ?Z-)O!nnn}1hsA0F5OQpr=gDtwZifQQr$~X)Y&^b z`O^0bp+ERJj$+oMzqagx*3`WqJx2Q1GVH1O40I*Drjwe%>4MrqkrA>(nrO_M=SosF zq)`5PMl`V`bI~CBVKEp5_8yD@FQG5|XTpCpHdP+za?k9L#-pOrd{)Yz0$xCQmPwH> zO0xx~rq|HA&pK(V&Z0}0F&cZ#?L?I?fpGX{$;nth8{ag5KCxd}RQXGg2Q7aEbzzxw z<#4^tyV<(O8-2 zLWO(BIv5KJY-ruvQZJ-a7@NXQY*z%T9S)QS8Al;bfQMu&d3=nz`)f8h;zp)(sW~5u`R`1 zgbA#EJ3|K=p|tf>h97^aug6Hb@@*-~ShvuI3eUn^IPZf!&U+KKpz#2-?%bytodDXK zoTX&eX+x>$3kY~=6HIT*0YHWBmue{WGcd?I3#z4K#U~gm7dg<0n@Jw5kTI;(gXSKT zwlZ*7l*P_W-eJbdQX4vPI->_i+`JFURCzuFqg53yX$Y?ed0?`qg14kNfQHe;)k1LN zsdAr`z+gMJasq;VsInfljya8Q$a7r@`vsktzr`Fx3$Vtfg6rrc`e*SLeH7-#+{L+^ z8op-Z7E?2Hc%88!MNhX=p+c1nFhGItNHGMIcE%qI{Dt~9?}hHE0`{i*O=w|eJWl=u zLk=`ODWMKGk0jj+3S{*Oqn6#QH@+aWkmq_({0qWh@}F~!l@Il!miMJcsNsF7kWT)n zT2rdNngLVqoh&M3tX?HyqZ%6fuZR4p@_lKrvEUI;!4x2)MJ398l82bzd@V{>KICN# ze=txKtX(BKqY38>Y79*7i#F*=h8lPsS5K(@k!yCs(Tpx!v#D^KG)DBR<_4&cvcQE_ zye18%s~=|cv5>2>AXK#6`00{^eO`uo0Rd@BL16QA*wv)Du)_%pV0;(|HO+xr!v|gb zw5P;zu&Yj`QeagUM$puB=|OzoMZ(8!71;O*fwD+Hw-+r3hXrnAs#H#S$R&A z)PV{VRKY9`hzV}ZYv6&6SFIIo+J_2p$Ei631_&jw>G54)gXoq5Os14HDUu9n(l9FA z3XNmU!i&H4W>NBFn;1ZusPDXxB#O%3Nb17{O?i*Xy_vi2K>6uVcf%ye@Y`t+ zOv_|RG9J@+q7~ENZ&fBh!3rm%V_nWhuWgtHu+fu{c5W41BVNjJ8v1(URB&}X9g4`) zP{NL8pOFoML}C`~4;-hi_`VIC0X{@CI<&4FgBCBbE&~~GCc0ASJlK8yRyP?6d@=!z z?ff9dm>)9WXgW;+2!6VoCmc>R`%(Pl87m%#5ZFwlDwXNtlhSr->>_&`4c~Pl`yQyV zZf9~RrSz1;jrCtjbiAt^OA~gX&uV+f;nebcvYwiAGHodE{!Cl?F$iESxZ}U2n>-ot zI$Bwf=}O_ja(~LNg&%RXCRs<`-2ipqD__>PJHnThZK<%U>_D}_@>GVgBPU17_T(;R zjK;z*11Pzt+#BdSP+2e-144h{TY_O1%waOam>&fJnlJ)ZZ!~<3q2tO>J96qS_eY8i zt$iiA1J(7Ehti3clSA5;Wg8{91A+4k;=*uDd*f zNdY|TDYY&cj&m@R)oYL%fAjAur;z@|j~L?v9y#1fva)$dX7q)(OQnjg-UaZH)#7EKf$C9w}?9tTjQxJekT5xU=ZFDakIP zsNM=&n*NMI(ehlmh-&jtalCb)33+llmG#j03&f2{avw4blVxLWlN(*ilrfd*muy1^ zI^b%tjU!Dz3uc46=ngny(l}f035Q&cq8qd2fh5~yI@9qy)UkOLn%WS9cu!h;;OgB340D#kQ zz?YOqpb(qOa=8p*0u7J&vZ^v-mr(rBh`12TgsW(lOw2Q7*Je_l*gJ_@S~(20+%!O z>I-ub*VRPWd59cm4EZBS6z9C`jF!jI#HdVfRt@ks7(Wa9L1C4!WG9O2C-*WYTyvsb zH!~cJl|S1Eu>n9rvcJWz=4;)ktiQYf9}SR4(Yi2nh|RZQP_+Z(LDbTh_5VTgxTnf8 zeJFpBjIYrSfN8GmhswjBPO@?>I-lR`u%6Z9WjCs}*L0_-@jwOiS}J$YI8x6E z`1xZ32vzGf{Y5S~g>hO3lU>fL0FvWaE7 zO36s+!n!2vR-9~4b&tWI=O)Mzw4xG%ZAbt{j_g>RJcPb`8rpSiD&*E2l<7qQ;o{AX zbhDG)=tc~F4tW5h%bx@Ac3=Zqz-cz#nleG2zoDN>%JTlN)gl3Rng?C6&s zeO`<|o0iBiRsVr`3MhuLm{}-CQ-?x81U!juc)k#62lpZO+cLcQmCC~@Whp?mF2kRv zivgFu5=fL4_|u^TKNA-rqhdKm2VUZMBgzIphFMHZ8ODyJCCK$$0N|%f@Mk)EYhq<5 zJd!EVg(A=hTmcX&LRw{+z!E_-8KZv7@h61=uYJeFP}#?3^vmP`no$G}zE}j1Elcqy z;9(#I8xfRJinrjEK>sNt8Bhi|FGeG9CElu6%6V**bEl20tnP8td<(0&a-2f zOmrGb(MRf7#+C&DNhw1o_vyrXWG5i-?Ib@!b@|Nr6ZMhovOvEC-!ucLa0NroV-QrFA{dc5gL zxgR6PtWoIA+&%)%gI3#T+Oy%lYn2W!mvZC@RoQYSC3FE}6>I@e50spbiebyV056gI{om(y<^4v(gmk#3AkcBa3Ez!~hBgU($Uin3`L znFiKPdr{hEcr@qJ)SpIOi@R_+7?`o}vYm0o6@SwAhKbn95cWoq17Y$6^52Yz*xTV4 zlmq6X^Un{3aWA~wf%3v(1`|Rdv!!A3NaKO4L6p{8UPg7h%tD@PdIYJhiBzZ6bwZW8L7 zB%|hVdmtB<5q27*`S#AJ>Tk1Pn<~4&ruXWCro-^jl@7w!}WNAP2xTqxHM!VV4g`wbM zemVHqG#zkZ9g)$Tk&H+bH>y1#wm-78uCyZ!!(C;s%-*y+6`odj8n|gnh0d+W1h1Df zQ4G$ho+>h-`YThxS%U!duC+G8kX{ETzB7 z!H;7U_~9j1vNjQKo~UWVbg0X5S2(J?0UKt(x4Tf9>?>-ZAB~Q+YdX*)O`^A^LYm$) zxV-hxp$*{FvUDxQjR1>qXk@C!aa{U?sf}(X6iDfu=|mG#Q3^jDsB#AQ zEK33K`5EX$N*BnDk9ElPq_uu%a7>1HSx>5+iSZA^IUj?#lKS(IXH`dZm8%;N32dA% zFQkA6!6E0GGtj*=?8&YN5Pds81$MT&gw3;yFdQfUNLEw zGtrAhWV%t(D~Sd%-QvjS?Mrl~B|4RB6!4`V7fSt&e}!x5Mlq;_A4u#>PcO!VKJOqx zrkve|#nNk3xGUY3jxGVp`UN1>(#M&0F}4^-#%DsD=#66Vm#`GnxwIM>AN;LmkRRrB zucA2S`Q32QXkwsP!{Z$Jzm*8z-duY~st5Tkg)p%CmXBZRVZOj36`xds{aV-af6J%P8|;aIlfZzyYTTr<|4%@+I7(Vhr{awK6-f-{D_ zsseFw!#b&%3Z^7=7MW48h~o^Z0HWwH#Aj+5%JDrB5NTrc?ZzMi34#NuG90mom!DPn zG#cUpsOAZ*a$FhX!e074InkDyE2OzpSb;cH`Fd#H{-0x-xpjGp z6RltiLIzLR3A<#h?5=UiPZQtyw-AWAh=MS>B-(g>83ZjZrIoGp+lYn(&P@9 zWCNcsIk93KbLz7uU|_K~DyL=g>wrES_8y$mluy7^%8$vqs_&f~Y1~}=LZxge^a5He z>P3{i>4Ewv-dW*{Al&JX(DQ~I%JiV9a{xy5FmGqIJ?$oA)l8ofNN3#uS2{06C*D4A zO!1+D69C@wAwodPbxghybyI~DyClV#mK`(Y`do*P-prU}OnKUYZlA##a?}?aCE3MTea4--`^f|FVo%jOVG@7vfzNQ>4_?gH z%gLTqXTe{%6O6IG0V6y-0`+I5Z3-ssu9)WH&BnOp6lTOaIg$#rs3gSFkD~WOasi*3 z3hdqwcj&e&ri3;517u2dhcm&7(k2(Y8FZNL;15=lT@mte`p}6goG@gD>oFc0JTS!P z>rju%8_ANf>4Y;ieU6H9zVZ*i@m>2ikgsITXHGNbAH({l8BFEUkpkR-w%P`Sot+tO zMzh*oUgd<#_i!Hr``!gxcKpc$BOOP!`X(GQUZZk1Fd5?n_WCtAA~s}dF@%&1TuwNcMA&ExXp%GB@)Tcdi(51)&h zmV*Ay6bIVaho1f&{3S3sLv`&)?~`RO@Fku{zrFecMyM^}X!LJ<5JtN4Av$Vuw=6%g zw8`~o(`V2ZD2*fOzQ8iXO}7*S`30bEmt9k^ApH?AKjaBT-0qWwJqS$W_nyHx6V?P& ziGRRdczh;IQ}`JexwpEzQOnn`)DH7fx{0D?KHw2tbf;=&IQB0U`hm`O99<;zBu2+8 z`OqbFo1Vt-3O6!*G{}YSKOwC!HayXl@=svtEw4}oz%Ye|t8By~*Q3WVuBDtpSIIYI zA;QgyZ(S|ZAE%Ih%s&gC13(gmb;|NJ;Wlt=K#L_q-z;|lP;e6CPsB&kXk*eke@bfv zxuv=2SSTHCOkVB5lEUb`K}Bc`f5M-kfdg-D{wi&c4j)5yO2bezrbqR?VmBf;P$fo56Q-OVrLH_HumeO!YnxF7cq`G zk4gz`O*fw3-i2Ch;4&LBAZ9>-R1ZLK*p@381gf=|Og(0ADu4AVI>{{uc|0{<&qTbD zwJD=Oe`038tY%j1nPHCX1^#^&f>D`Mv?~1fkJnR)1tt{ z(J9!aVHOcs*Bcv^j+F2gKmLA73n5SmAzi`0FIdV#e3lpa#gPf!I(OzOtn zZzJfza94aKO`!1crhWnO!$sAgNuma^#zh5<$!~>G^Eaqz*q_p56CtQ-nm$b%mt4%ni4os%hVf44H0!gb4}< zZvGjvQqlc!QL0qQ#2E45JX0XlCpZo^%5DuI=4z=jX#yPG;T%0j2@SbjThfcJL zuGg@XU}}-%K2?{b$#yu`jUBOc)dRMKmurbk>0<$%+8w&c@Ecd`L@}n{Ib8ayg!teUs9(-tGygCh~5>Vd0H2PuCmM>mRX-Ui+#a@4ZIn*E@?Y z6aOPB;%zHWH+2eIW245_cwmnoC0xTA{-&T5wV4ZSq2}nrcE*JFAV|i}gyAOb0-I{L zO!h=8bNxNGwUfY6>Zjr`9(%bTPcnvX=O`9Y?IkP*nRLXSS~{XM7ut*@p{3m@-ZcyM z^?PYC)wD5u6rO65Qk@>X7eu>bk23r2z@E#nvJ+W%;-Y}A+8MV#=T8mi;V8iRx=^4m zMy?$JSVs9F5Mw(Z`ncs@!W_HpI;QoW0Qurw1ZsAkhK4M4g}Zx;jjR_g!96t%(zaCa zIwq^y3&?;!=`O~^q+?(J2H%aEkGfe7(r>>H-z2~pm@An_eA5YP%nklbuPhfqXg3=p zdmctCmiu|LUqzs_nYk`Mu)czAj<$3)2eSrj=j&pe8D*f$E2JRf%wZnn`w*ZaAI3s$ zU?~=An^uA+uT-pw_h4^precGc;Q_n_#%Ew3;snexuvZXqD29@!875-O!pb4`)O{r| zMVG-B-cg1zdBPGbW(GcnqH(M6^F|4#Djes^!X#T`Q#68m52677wJ92(3wr=-*h-8~ zYqEY=?&9>N*s-0LotKeal$}NEAAs8sGzD{`+6RG{msMgMjD{G@Nm1St{ufRIlq`+S z&nd~lw=9;G|=5yAzCJ?%)q8nDBgrk`6@u;uMVSUZn?9L1i_$IdujxlJWl6mKn-ScYwkd~+tp za(ii#Y}Ai-pd*j59cU1#(LdUgzGIsuxkSs#A*$%vn88&(47@)+jOjdn+R^QYFw~=f zCnJNHLOdpPYYz{VsPQ3ms!LNbjpQYi@o1q-*GzoY&cGHGo`EJFN??01=JVL1!kOim zH!nrQ9N%dw@x&_le3!~FX#^@PrAIi3hDCGgs8Vrrq=(rq!#3^jfG<9p%0q%!K70sf z0B=!rupAbJm)-ja7UXLZA-7a-RDCb%ZhMhO&JEt*#NH`fe`HGK8Gn`T6mTh+k1B`iy( zXAUAnm39shPOtNFJcYk$WltYA!NG5Q!wQ=81?C1}uUXkr+{Z}MhrzSXYeLw{vkBI7 zU9T)H9lwA$T;vLD1zN`5=9~xm@jbH~=>0G769^_#!h9p8V&@r{!F1K$Q!qY^^CRq)J|j?E|K=YgVVIWp77kA?(Mn)IK9m zt9mkJ0Q-ftg);~`-+U;=p60%VpZbBQY3^4-{()4wPOhcKbZ~a|XG8%E&8CdBXMhfI z7p$8Q0%;X}vur7>LLSZVO%NrpEn_q#^oJl%_s_x}$}$r$(y)q}0jVE-T>eQ2Eo?1- z4ZlLTSh^TXw|<3`=2n9tq)Alpn5-}wF7yGDX40lC*g7*WXh5vZl%_b+V{4JiWgSq- zco~ifLGUTOU8zSjwQeJV7WJFa2)m!Q!gihp5L$N%B;&sTYt7XNr=CB+)TI`Izs-}O zGhMgIag?xKo=pX@s4uKa92f`p9BK7ps7qZwc;Oj_rO>FT*;x|ZdR9)NiF@F9ZrpI{BiUK~68Dg344-OML~vtyt=3A?<_bu)AY_H5Oe~ zK94@KV>b;0HUwH#*8{UAd&c6=07xscA&uCd|rKL5mL&a}pg8MhS!vGcT#mqc* zFMJLN7Mi0#B!#bnwW#}{e|wpnbtTAHaf~TuHGU?&CBIHX>%khtE>Xi?sN-Y%k)ad= z>6*9MLct!`iGveN%~SV;l^>VWFcTGVn&Eo2b$IAs4hOS`fMZ3!*0qp&qr zSi*i2B1zkcx(z%CuDCYE#Gx_~2Y_$olQ0o}`v4N~8Vm@ULMGi5|tMKRP zgUr8~2Wc!%guu9V;-@W@HK67VJAlghL#X_`6zFb4EqsTZeGq&7yU;pkmK#17O&iK2 z1WD@X+-rE_!j69gB)_i#`p4_h%PugG+uNZ-P-U48?nDdv&W8|rE9}^g3a*^U#oCvFQ(q6Mqc4rF+637)Jd6I6c$A6ZKiE2Q;SeOx-##>=IiVDzso@F? ztm)hZ#PA<<;i&f^bi)hi;0?!6w(&(+-V4oW*u5XJiarA_o_PluC;kg!f#+Z_!nZ&{ z9lk+*!aw4)5m4O(-A;WMUq~Z{9t&20ecDU z?|EF_Mh#~n+Hr>gH@6YWa_N02mE#H2ap#9njHeER$L5#8ieDx0HM|SB=oXY{d567y z0JtIlfxh2XAcBqWgT`M+QKGyF>Z*Sh3RH6h6H=RFKwAC{8k{raa0qI6^KsZ){uAgO zX~ij&MP*=cwxMhP_5pszJOz@2YMA)GOmStVERM>zgOG0{av?8!ntuXs0gt0`5HeTg z3gTECJObeQMzjR}*plu+wEf&;NYkAJ&pd7A3m|msG;C`^HAKI<5^4xl8clC)LNRn+ z8#?$oN+fQAQHx&!ZCU=2yoYX{LOqT(p*flt0fBT4I&%L;d1KYnR@fTbAdjiq1=+TI zf_RwMXIP5;1T(t7R)Ry`ge|9`2**Cb;F(kgCH^g5aNP@==TR!`G%}(-#s;VhWe^Xy zK+qMDTUBc%@7;J>_R!FQ&!GFeKZO|QeFAOR|0#yDKg+>?;b)LX0pt3w(Li6g8Pyp) z7M%hdjwWR++TZ6S0)}p^k5n~aNRLdX zg^kRaGlyKRfQ7K1<;1EXEavkS)JA&+%5w4=HmIyv2M-eGh7hh{xnEs_{XPA|4E)pHEV>^?8~SGF*q&dUBgOP^ICC^X$o!4hwIHtTy4Qn5jGz#Eq-FN z!C-jj6Z&G$dczN(G4y*m`~R`_-eFN)UHkAglmVs>y-kCG0cnE;6qyE7z=|c�DxV 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�vZ7sKON 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 z zxGd!`!K*kLqw}PzJsqRd^Q2)?`*n8MotJ-rNSjMfCkH6A-0@Xvpls76tGlVjKKENeI|+N$nfFh`xN?9LzqOWS3rM-A2%7HVN@Q4pGwwX}Sw{ zw{?9$AdCDPH&jUnQ7>flA=2$KzYlV-_d0h$t=AiNvlo>=w^yTqiBrQE+B2dhsAcxm zI(Fb}4sus@L}2k)>iYn=rF^=PdbI_f>}@oXZ02%BB)#Ha@fZ_y=$Qup!Or2hX58tN z#90kt6w~(uZ`d@I%I>LDv2IZSZC^FYm&*4ABhv(QV>-mCv?KIs!AWj~!%Z+)?a?%H|y1b7So+0@E{?oo?eAz5SS^ zaOx;cfnDI;L&6bu-Yy~cpL-I>cDy~8>%97Ob9%KOVmimb54!J6TB+dQmuH9`knn{s zfEySE!rBd^eOMFbcbm|pxf)SkXFPvd0(EZOfUqTl;BF;@; zKK&#|x(O&XCqm0khwzEZ@P^9G=nSI8!yqM7#?s&bstMib&1zHaQn_bbL&Y){U2I3* zqGpd=m=||{;OnX3r88KCH?D_dd0@K6Q~bT>Ryz!~+jeg8YoBIE9P!?dG0p8CA&d-r z@>{+gX51}`Lva{6H!YLG5LG6gHzeCMx(ZnIbG(kuOY(!7}!C~rA~zBNut`J^*U-wEjF=I_meggs9K_v%9BNjODUdOt=ghqxnzQ?6}wkRLji(3cR zH>mN3us@9l5@}OyG2E^px`@GU?v?0ZWn1tqqhs4X%>i={S(dl5W52`-hEU^|g&54%=#BXFkjUhH-s+%WT-3bNbPr9C!d9cQ72s)CCZTheeQ^q0APJ zbD!Bpa<9Ac1G_Bl&Y=1)O^K!6fBQuVWp$Da!KF;4uqf+Z084ZHAZamhC+U*bz&5xo zzQsPp)Yiydt;G=7!O!fFn}}VESX@B!fmZ&%MN`}|gr}O1zz-QMVrc8BKm=5|!Ju(G ziKtR{`ce7ZSf8N&2beQb-%FNg*89F4@z&LoDpqjIxg06DFYRDAU_Y4YE%RiV{L|?X zAqlJz6%A}N*451Fbav@7YyVB5n8DJEBj6+;CK@XQyE#tT#cZpZaPTIMNo;pHHo03o z5*=Vi1pGUn1U+LJ-{nZR)8Xy_9rgU^;~Ci>4J)w^1s}nWxg_>tx?M^xIj@rYj0boX z%OJsYnMbM)d#8{<83L5rrSSW%uaqfd7|7ik6L#f=hdg9cqV@c~MYGg>d0sFTJW*mg zPcBj~=*VTPdooCk=aS0GTB`W-$Ve6iGT|i-FB|LmBd4P7b;Av1T0}IRo*CsymY1dn z2>jE9Kq~^p8OSQ={LGpeE30a2D`mr!ty4>a>F~^{h^0OPZo0dzH~Y|nZKM5JIcP(I zs{J7P)1av#s>9xoMZx9<9qu-G(dk`=WU969@TQK5;ab1*XOaE#EH^kgHE61V)qHP9 zuI<-vnF{0f6;awj7#gxX`B`Oh6pp~GCHAPUQ2ShrlaLr$V zYuvxuQ*}I3$;LnvKWt+r4b+GbB_(mu<;4+6;H49pE_BS&lR1&{DtM^~3LKoqMtZTH zsdfZ?uf>3oLU=Ha8TR165!sCy&hiq=ELbqoN2c{AYW{S%R)?t8+&+_?xQB1@+Fv>I zDSx|a7*>$2L`b&~7a?~F+*q^*td~+Q~a9wT~l_OA$ZzBL+qIvV*{% z9Dzk%tmH#}n7O|G{U@*U4xj<`#ubIQf?4oMrfHpFNK}E%b^hqK!tf!Nm4K(ZOR$=V zp30Bse*9TeB;28D-yiGAb|8=?s$NR|$NE30dzdqwW>BF zTLq-xIhpMU8J}^6qmOHh7l_x$DnOi*SSJ`bNKU|EyuyB+&dI+PI2g-nJ9&c#fpJfh zU=tH)aXiMepCFKylptD^F~J9Mn$Q#%rAjGA5-)KA(tO_wVT z4;^6dI@JmsAJ$%I>z!M99fZ^W+@=fcdl}^NN~jr_Jgc4GTV*1W#Pom|UTbd#Anh)Q zb}BoGt5SquRr>5e`gxq64=dUciHW%$cZG23*|!x-(3}~=EQ>Je^U?Prn=|^t<4cNz zx&j>X8tl{5-`uB@FVfKekjl9?DgwUcXefSHsae(ldAl`0^y0m-F@kcd#;wdTXRWi8 zZF}w)JJR;PGykq2ao@mU7Y+WGw)mXxb3!+!Eo>ObhIigGx_~ zg=^G=bU)SY(#A?>b8h}L_5@7bEy(U>!?uZb6KA#oDB;Im#zsjZZa$;h9xe5m+6(Le z_y#|-T0?&hGyAc)#e9#*8oQ(|egWqL^(qXb_>Mu+p+g(SA%rFrSFE!In}l_l`6aeV z&k2jIG*0iBrU!Q+g{0c1RIabAa|Z7f0jSAy(=M^$AoY zsegqusZb{b=i+X7+XZfdwIFcO;>M`H2}UA-7Gw#Rejn_-D+CIln>Qj&VGra2j$iTl z_{9UGgo7V^2Ygi`FfoQ?A;JnpMh{B}l~2DCF3HE>df0O|!_x9$B-~Oj^U<?SkuWG=XEINE zXNw`0PA^K*!TNfGmK{gGI(q84#BkQJ1=lslBb)6I{09wu&8LdDSvb4)3oZ_8*v)Oa zdvTHVWvd}p(6a&pgj}oAmPGsBXbfiiAybG5cClLZZmyOu1(hEk4wGJ&d3O5? zC0<_6p6Q&WHi&bso-IpaW7w}~DS&n+4EOcoW9Bjl+WJ~rgkx@#UHZtweGq%jm35Yze=5%IG9Q>BL@2D#2E8{ zYu@pX_3(O;uGFydt8s^N6mEwkNxBe@__OZM!ML&N8~C~S^tJqVR~+YuC+%>emZdLh z!2!O)dmaoM-;c9UaqVV#-&j>mJovvc*b6~1Zf&%4qTX5-3!lPQO0-n_<9Y;5-XE!D z8-N8qf~fn_GYevUtm}BZhg4fes%>bp;uu*6mqyyR{x+)x)32CI$CQfFiib=A5isI{ zC2dli`_oM4r^<(V*N0s61ABmvuMI}L;|ed@I@W_F^`T|I_(KWQ3N3e2$rN~)|6{j~V{;_y#oj;^=xwO< zAK|oU7xFp(j!+@yiiH=`T(mw18Gi;R6-R_z=;~L^;X{DKjg2PRv4W$vihg-0k~Ax= z`DaHImB-h3hKzGwB2||%Sv+^~wvf%|5O6g~Ml>=P_2?Y8U@wdxLN}{_ICT z&uk*zN+9qnL*4|~)K}WXzDIE_R&pdFk&g%VMS?X# zFv>5XV=X!K2Qxd3Gj7piDW$uV0d# zy*O*>(8WX9>j(0r7}ekJlp(Y*3q6=8h4m{%n##wZ%XiGfyLsO3mk$5^dD0O{Rq*WP zP|fPx1&lWu-|z20ma!YrP5PDMP^*NNUR7Gr3bnLj#=bl$RHG{X@0;{kitasspC%m~ z%FN%XF(wcB(9Aq(&F|Y}!R9=v`}b|~^%Z&2DDCevi^{;?o0}(<{=QJ&UY;l2_xm<^ z^lB*Ce_xE;zBf-oY$GSP7l$XMj>+oa$6JZW`*bd~Avc>46d$HW%K}?gZkeho%6x50wCc~Mm0MD}CR!TbGph>Euan(1 zGq(}JDmt#q)KSUSK7F2FJB6-!ZA(zs{XcE_e9#4(?Lyc0U%c0pu0@l#%)Cew65EoP zcflS=3=W{IQDHO<0B+ZmQ(NBn4N%089`R~?|04C?{x2#t&I|D#6xa$U6b$#AQtvAC5=dW8YqY4QNA!H(q{bu_BPfHIe`BK; zjd{HBKK5%4(le1y$JD5SnhYXdv+Kb}8f#UwkhdW^({+{4Z9LZxj3|2juEvb6uKA73 zqc1Q~T`QI~PFJHl8j2#vqDEs^Oq#9Be03XyJfG*6)zxq#x7&o!Zq%>{`s_zQ_W8;{Cdc3U5y0Wpd zf0GxQ2KDX*C}L`iU3+e9ymFwn5su@wM!&AMg^fR|#vo7rKObs5bRNuNY42RtXpy?E zyt>iU|9uzMa$7%82SiH(S_b$Hyo16yuKRYao8I^oGWn)Xd0o9!uSG!Sn=ngDB@MIt z;JSF>Gsi-wX3mZ|?+gAS{n=Sb1HKrtc6MIZ;b&)ktUjlG|Cf47?0P6dv%Su)0sj#IjnH5X7e>W??t9Q)oJ?D=yVU~`(N@w|Wb>BWqt6tU<`~E-X z-UB?!Vv8Gp5|V6sAtWKak%SV`6G9K7B7roL0LdoVlHE{4Lb0F%K~aH(Bp~FdloUWk z`qj%QD#dbbfS}icg;1m}^Zf7gT+E(1b7tnunKNhF?=8-^ zw2<}fC@ydkJX~3|jy$)Zl=aURM_BmiU(Xhcleo*4;-QvQmb0aJs#u6wF)D^SEE{g& zBumPtyNgpLgZjTyCbmGPjaN}#@x*YZ>R)_9oYl>R{=c*c28)OuYiSuP-8V5M-16Jf zQp$-f78cN531L+2RV=xwP7SDNy;pIFAS(Hh9AEa4S8=hwKr}Z>)t!6>`+v%g4AW=% zFqOw7XGglcB1a5D&AI{a#_1$X|!m{?b)R%g51dMCFyKSM`^A&5rHR$yzVbmu{Y97)5Ue*qpl3QC6~J7)o^%r$0+ozHcgR5Cb7gO8m2>z}DG`(99Y|FaR$GT5>v#hj0j9D#JO}L|Ux>X*l z-Uwpzrj(Y8^9gz|gxt25h(iksyiL}5456ky>4$5fA|LOdFSeKT7ntpKl|)lNI~>TI z+fgERfReE0xzd2{==9-^5^cpxI4!+@YX@T!ozNVI_EQSxO8P?5?l% za(9)CrUyTjY?RAJ`2)Og=A0eE5*{l#??UU01sB-Ohf8AZDW(Jqn*l3Jf*e{ri_ef( z&q@9i@=SIwa#xqcQeLm@fow#5w)0NY3g}dENrb~c{}`X#o7x|m6v#9~#;yAo{V*f@ zsznD>@PZNFbjTjxOQ2nuIzEP8tsUQ!E(C=M+BY$e9A4Rj7)szkU2ZvCq4cgX-K#yFLNPW%=}+KFn*}_`3wZPDlK;cccwXQpsG2NDymdra7{>=JBt+-M!0D+RW~+7(Z0> z*|$(cx9w%Hnt`HXbo!h$p?O^_#Q(2X>-a3V$0xwt*yDfpCA#UP4&D8}Ry0Z3% z$8U7uBblyiO9GfjP01wZmL(;<*^SbYUmcXu?9Fa0EU|Z_QxBBjy8#PJW&uNFrix`f zSmKH`*8L^Z?3m%+65k%I$Acw$dzx9C9kxeT^0|j1#Xd8+MO_kUmrTQ!lmx2qnY3xM zjKF#*1&ZhGch9StS)(&>_@yJg?hbI|x479A-$`C}DqaQvskVPr zm`uCwndnFf;p081d04f(BTu8*3HOGz-i^8i^SU{a>h-?9{Qzd7Ks1|b!yiZRdU2wu z!u+gqZeN=H%R~4m8NQi9H8-;Zy#PFN-#lC!#EqeW0CWTB5iZ8p{cDCZ-TV=Z5!FMT zJUQ&ufB~JXRNxwmkEtndLLxlI0fs&kNCYQc#<|de^lUB_k4_)S?q#2n{EWB9B;KpN zah=HpH+S$qI{lhUoawKl;Rhl~f8=`q7PokO&tvrs2YT+Q95ufzI1rh%2#R5iW>phkJ4{q_B^D2zOw~!zMj#$EshQtbc-v zUY#7s`YoM&d-`La44=e489q5H+d3Yfot+;_=cnX~^90r)cvY~oFr3bBD0HSpn!Gp~ zS()R>KABwDAi6uwn7gM)oJy+q6p69Vx;;fnf(Q9%Pm#EKTR0Tv%B`!J>h3QMVKrLhsii z%BkL#pCz^eVsDw{mUZZqb(>eg8&-Ay`?6e#x99V^d_P(+rNEuahU=W!9}xx8%Hn^j zCa=GWUHv)#4{?+HFJ&oTH-oAw%L)dI(+|%V;#T0wPJNLdC`Mg>De+G_QfW9t!|w{T z>PUv73dHH?e=4Q3tB#z^pCSfUyAKtLi=36K^8v4#k}I0Knbwn46MN2f(Y|Iv={5^A|TYB?|j|)T(-xW);$oC7Y#61?P`p$02O&2=GT-E=o`h0{n zx95p&Vs~KCNI{-eN29^Q+{a%1s?bARt^9f2P}LBs2`Cc#?r+tXm(I<_${Z~Te>TI3 z2G(8Et$Op%HPMZ)F`4|nprX5l+f8g(Mp1#yn5sJxiq}^AbHu4mSCco=deO|Qd8kLO zAkZ|O-_nkhz=YlJkbA~zn!(scne5`#oY-zttZVa^DiwXlm6qJmg3<6==eOsH1Gl@D zaN4T}azw-Dw8n!uPQ8cT>L{{{g$fQzyTj%L(c^Syz_(PM)ga_L0JGRsPMg&>!Icu) zCWyP;=7e}b5uCQKZGzPl2Kf5xp{`V`$y2fOujd>W*IrO%A9CFlCRzp;(_H|^_f+OQ zQ#4PUHWUeLK~vE(aVv?71<{oaUtN^cU5c8VHDT`T#Pp)iyGwRup}UJbL~r_+HSLUf z?x-zt6Hger%Lg|Q%8ou!lpyZ2b=8?rbSzVED$C#W3Vu)x*O76>oInCYHpH~z}=ldu9?f_xsEMk@iKSc zddXJAL_9tYkfz73M9SKb7bO(al>m{>EPqVy3~`H2No5=66-J0P<5}|Ja>YKgYU-a( zk8FQRZnkw75(IkCM-RF8q>Wy=;u@tpwV6Gk2fj0BtAty)Llp&o6V{W4d*_O7$J`nx zcGEjIUTl*&MWoG^!&bOfjue0UTt;-W9SmceOp=xXr7RI6Iq0Pe*&&)flH6#v0v?z`e7Z-?e)ZY)g|J;e0 zQ)2{EGHFs?ad8@4v?rx)mfFS>5In1B!Dh*Nk>E?uZ_X3XKoODo(r=sdgu9KTL}`R5 ztv8$Ybl%O4LOrnUAuir{N!;1I^mgu1af9B9(aL*b$cWm97*WYq3dO=Df$C~=RqPe} zyxYVLoWENL-!AAwUu2I5WJ~8M>mWKhe4P_>`!x3zab)~0(cKy6U$)75QqvZ`Ff$M|W}C|5h2(cCn%;hU4gei!5RrZ<~jLp5jm&*$i*unH z3tcrKMqFlEiM8?-rjGAsu-#I{NcgWdOw9AI2lH>Apci)ul)AEc#|o~B^QBcaZ&5E_ z+V*jQ56$_wK#XO$c99@jubJk`{`j~cR9x9vl>|>4L(i?5AO^0S_Q#qDVj-M1re%V- zgyb}8vE}=^#d>r6PtNnW?>K(#Za21(CNx@AwGTtDCWE91stt6iV+ZtR(z*HS}iRo+z*v-L91wSZ)S8v2=n;9LQEY zQc<1DDdnmTE66YW&_=UQept{?97N{aE_C^3(VbN5Qe586{Zih17Y3HcMFW;HyRxTy z6ffyMd6!*r6iZhXzukSZQZ!rdSUk4dWQN@PyGWPfAX!}b!VxhQGX>(nXcM;a|eb}~LIYpw4btl0}qg|Pm#gPxSx)r1_PnILy zLhepXS3ZWj7+;9p$WxU442lcL6Pq9Tf>Df(AT^ZM1X!bS%qu$YX)*dlGx%PQiq79(*xkOF zI5}HwKHPG>>+@itv$zRjDP+x#9RU>jNUe&^=_s5d4lK@tb98a;Hs|Z^IN0Qz7^cD@ z;(-4j#r(XsFw~|txKm-H7R#buySeapypE9G(K6kd5*Ir+;av_L3@!C#OIu2URo3r( z@p$1^%W!4271@2n@KjDFBuBA*M({9fjr!X>*g$#!v#-wH(wpLqInMNQ<1|;cyM6O( z_VHDzl}VYE87XO1Ny({6mAa%feMVJfr9q#eOVgz!r4AW_ui}lzojT*3zI)zU_K*_` zU%edR+J+v@J*i=7Q#gIuqgllco^B4-(3X#m=DE-jhvq^yvbyn z`92ou*!=Vq=KgtelN0Ug(fm7W8%GPA6j849;;QZV%C1+vlOoTVjnl3C-a|=&X2z_% zlTp!1a%cE+20mf>QDZBc(%i7xiAH?5B8(ke-k@@1FJD-`$cftaHE?Rkp7|?ku+=kr z#RDpKdGd+|6&(*;;m$mLR{S!?RPXn{UZG;!wJUae(|M=HAyoI{3KtqTtRa}?m#m1v z^>n93ABEF{w2uR?{bKr>AVMAwHuv0$=Y!d)u*OX;6#LdA*w^*1pN*o!8nales&R2Z z%l3vu=KNK|Y)@*u(V$|(uQsSW*@o7Jl^!(k>QZNxN)0od+3ij%nCqVH4Ilf^gN>kG zc&8z_H~V;BgO?j!-rnHE9=zP}n2IW9uW(~ED_86sM{hSZw6f@ajW;t{`#S2;7|l2s3@*n1DITBRcV`y|<|TQ!6wJ+kUyC$_X~m1_k1V`xK1 zF5zFCV5T)_>}W|}bmGa68rz-Njcbjtpt>&_+Xb)3`d?{$(T$zy)3iLE)j2d(MNpEy z-jjBvuL1D$+yLcz5YSVP!)@aC4-8RuC%z}L%tM4b%quPw%?J)swn=) zmEIH>+tQCBMy+;a^O{;>Mzb641fASC-ZC6lF=MF@%ev7rQAHs1WI0z_-g0Ln1K0fM zN6=#qUEa1dj%}-5>EOf?3~Rmt8qCQxp#-*Y+NE9XOi5uaF6@ur*4&5J^G%&ZmL1!Y zeJ7iCbIq<;y18VvA3bn$O(Gk7YRxJjhJDuJOivD4<*5*psBPNgDt3Hk%eW{)saWyV zu6e$O|4H~0AEHv&6&Vb6_;ws01N7OtRgbaqM;^a+)il0z>sKxLP8nYqRM3+P<(*um zVh-+WGCkPIC98Xeh;Q}A2o2%XFpE?>ytrKV}o0vdnU0ObU z+(V)L%(fp~4x2k#LO(E7AsIbc)62`o^kgSpmWKvVlgsk)?C|AfJp^s+nxAA={eSI%>+fVg@-UPBU z!LO<@G7^Tw`4v&TP z>E0~mljRdttY!1^b8hUH1IpjGHP+8jvDU5iQ&cVgMk&{htpo<(AItIG-wpNdEb5DT zjQJbu>OJ=SyZ)?-n%30EuqO`HPgODe*{)(gzfr$Q#RfcI|Beq!T3-*?`S<(Ohp};Q zFaOSyEj_V3HI$OxULMT8KUa?zZ`vO9``uXb?D{X<*_qP%g(|jq_wws1#g}h(qQfiK zxUgA6>+cI^h4J+%Xkh_929`9l$%nOWYKrk-M<+MIzCk$a%T^aOjaJe1MNKNE*EYT7 z#+EE?at)zH1x*Z`{gG*k?$ z+<%@UM)48f%}Jo<&2t=BW9x!r;-TfAi&pZn%exoc^fuj$_I+ZW7l5cIO-F+snP)Go z&se~kdDFz-Lm!>@q43m&Eo+%KAD`@LoK{a?%|IY9a_qDVBNVA_%>9mOJ`Rul=T{^C zUxoiqVgLDcsw$WBVYbz|Q19oB9|_)7*rOaNZuQM}(?+nDjvGgXQrnfs zcwFH|&x}=01O4ay|XrWrP_EUO|KMkEEHL#`^Xzy349j&FbPm-GT)g-mJa82%^38s|ElBm+j zQp;}F!q*!0XbSh$I+3eJE#3^{Ht~W%J(RR6trxA6Q_a@lNJFNpGbsP6#*^Z; zk^qab%-5=oLb=>nu4&aZ0*xEXa-F(Lp#82>KPdcMs8`nuKVd8Z)UQ%KMW8)dslHG6 z35yA&?=`630i7B^k&98u1qP{-PaD+t2syYFy<|`iqXkB(M_@{RbjT>RV@Q>hm)jGX znn9OlYI;%F6saI?Srt>H>T;v{W{P^YPy@434W*q^)#5qom8t4Rfp6(F^)lfnH>&jM zQiWcau3jjxSd5BSvUa)}dx6&~Jg8VN)f6_i1}~j-Gu0FDpDUG6^ZV6mUxJ0Xv#B%H zr{+-e5uH0bdP;r#5f?qa(5`%8b1uzpE03j`sxlY%(KXc;a>2{$aJH_hEZNz6)XaNz z^XE=5RvWAJ#yNOEl{LF8!Im0cQ@p|1f07;_gPl_rK|3bt`%vBVvR8S#}phe^(o5@snj)Oig9k zA=F%7=B&y$ef*g&JXR5{)Hukqlai=>;rou6l$=}^Oy0Z8yxcoK6V1OJO{bq!gA9Im zk)Mve3foZxQ}X>~0H*o}eonc+3~L8M&+c#5yRlu*m(90#%br^^Ya-0Xpu_iubShuE z`C?g|H5Fef>Zbud*ehi|tlyrpx9(6)G|rie0YDes$_KmR{haytVE6J=YIZ1hWIz5< z_UJ4(-OQQAbB%NEyn9w9t(;Mw<~~}aL{^t4vU{hO-ycSceo^_+jHk-+)#h=|E>!o6 zsu#WVR5{G9sT>zE^DA-5Y-V|+l8R46O>mB8+GXX(>ga%Tg#*pXiFdZo(UINRie9TL zqNv%i!r}4t$AD|Pyex#094i7S=k-cY8tGawnX+z_ySe}h76WIxv6A+Ep$T1G5iC%S z&M{))_eq&2)t)JLV&q!UH`Hm=Tr>kJx=ht7oG z_r6vkhPp$pRa6Vi@Tru z3L(nj+4FBy%#yMP(1{xr#a5&>8w~-s5-S8*kce@6vtouN`Y))sXRzEW$lKjRbGPu5&s*6JnyCWq zn4>0;)(kH5HR8UZOn$`_b*NaXX zaeEqZS|GjhoWYa4RGI=I8&5dA6$#BM&75u$!syEf%tDW5#KV z=tknSKeicq(s(yb294Nm=uLGV8c#tyXSwF05rY^`+u$no0;grVNmb*tF*^|WZ|G2ewtSKX9ShJ zWALG!@0NMC#Aw_p&tHQt2)u;BseKYlh@=3GxZZHxYe>LXrZj>Zp<@9WG1wi|Tk8K; zdQ19g4#bLVc%UX*s0Cc?D}85q=`okNWL{p}iHX zDY8x&93ts~Gw%qo<%r#g!K`&0`7d>#GFJ6Q|$40{UA1) z+Ez+~mkT}mI-JHAstTo#ai*AT?@lgn7aUmO9kZ(l%}@>1Ev1UOppW|dLNBm^jihKc3G(LrgI6>j1`=y(Ta$6xd@Yt zbg=Q8aHS=<6p{i3EK1NsTdLG@46)3u5~(^#Bd!s@KV}H086E1*(g!6=lgPAW%>s*H zI`)Afj+#<5eP~FEJUf2?uU40$nJ6%yOp%%y_;2V55!PJ-%f3{}gPr_0BB^IuP?y>v z(EH3ZX{cv?q?q0&b86j37-Uuh(ji^yy_xA!$9*9GJn%6Zqsh<|3Kaq^h(5}YoG@s9 zG;WY&CY*M3kQ9iRX--t0DS0rSka!%`J&~aqNHdP3j5c+d%?!Z#wjakBo-tSoPI$s+ zgQd3JHbkQnD!y%ql-g^kG}N|#4%Mk2#}bw+w$aBPCyb9{F>5skT^*{KDG06m0)|vO zP%`aP!z9x#7_O-ka^PnGo&6FX@#b)i+B)I>5gKV%NMXJ?LQ*Uj@aRa%EI94UlL$FW zPnW|F-KH5pd084UK<6yYSyF#++UKVX?sWKl#eFH+Dn@C<9WTzZVU%XBbxo6Rv#n|Q zR}l62?V7=~{wsuZ9-}3H!$l1pZCmkuqit(7=5|~0dEXek6!B%&b(wUB?Etq!aNLI{gNx72lIqjufi7zxy zQu~TLsqmZf&)NAJadEl!5~c&hSwR$9pb6Er#>;f4jDC(3B{ zq3MD2ZhvgzcQa9tPZ0vUtU@U+aq7 z=322PM__sCXJtZ|D8;J>CThfj22Rq5+r#T7NpXL_Utx#adTBeSE~_c&zR8j`|MIJO zQj93kh^Go=C6drLOQg{@yi_wsy0~)b!^MI0VX0&)iE3%4TlhN~_NrPlR%onOndDh> z|6}N5nxd_0v;RNn{h)G5Db?jt4L>dyZMWqbG&{dS(kynFd((Fnl1YLVM898yk8#p# z5~xEXMhpPvM(Xz($@y^F+3Q%r+^3bA%M&hYrAd<0rs~c}ohiV6E)*{|scbCeCetk$M#lBIK&6+Mg|rYOZyjRoUW?(}{Sqlym4OMa2(__azFswjK* z6loa(K7aaQiY8C4kUwQR8e^3?*wScU+A>u$*qZMLM=0kNWqyp9rn$|M+Aao_T!0j)jLBWRJ*jOKK52g7kfh}U)u?g&49U@P+AL@6Ao6l> zDgw7ZLy9Ol%l=hx_E|F}2gVZ)%#`M0PW#El*sDt(7XQ^!d<+(G<(fZB+H5*9OB$J@ zYNQEjn7c8M0+iTyVGSa0$66_-@b)kU(4DnXTm@PrK&Pb9w$Q^EVX7aO(ze>piE3s` zJ7Q1GmfTvdr!kn8`@(VY97{c+up8qgyV>Q5bKHA3z)-^GBEY|>uvo1qPtTDynJ( zZmFiv+%1`aM^9rv%DP9BZ?P=`tv7AxiNasGNAhed@5OZO>Wfi{%{6=?^j=M0AsbS~ zU5G2b7zv!O`aUUs03Yz;?vo~*$oZm^B+jyTzQn?5S@%md<+L65OYVu&;vbMUsW@#? z0L-Um0V?kJpk|<4aX-p`P@21V4$xevqBj)5vw0)0kZsfgjkuF}c!3n!ycmd%;*o6K zB26f{ZUxAzM-V(t?I@`~-d!lI^YJr+UJNo~$5R>lyc?$l!BPyZN9)W_m{wxK#K5N(0T7PC{NAie7&%FMKZD|n2Q$1+xB&p&fBH?bT6Qx$JeN@`0 z|5v0jid-InCcT?c(=m@pYw+YKT=RI~8Mut2kHXBVqtM>`rzLr(m*Lp(*(hZiT`H*^ z3B9OhspRX-G$*>UR9ep>A&_P+lL8vh#DE$63Gc*M=rHM7+ZL3?Vn$fE)ue}>6yG2XBgpfm+6HM1C&$5^UTu)~ zq!hl=719L3^PXBEd23G7HcHmbX(t+`5q_)*wO`Q>S~pj%7qvD?lOI^b?G!F$db8w# zIPK$RskBimrLn|W-d!mT!N|wa@0WeCipyOk$wNW}y|qf(PXJAHH28^eI1^_Yh5vvQ zbO1gfInd}#pA1B&G_R66AbGWBi_m%a8B8};YaZ%`=0-c$NGCxGb4wC>B5Vyp&;c(Z zs7OdeA6u>N>XI-ZFSLkJ3>_xaY;5>UUpiL}>oX0*wb)c|CQX`9Hu%J&lvBwlt@;UR z2jkTzG|Pk>c~5E{6@H$0QaUpze@ZfQpLA#>FU{ygm!Fc1i6=~2D-BoB`dYk3%Q{Vl zP|nD8Qe=sHQGw*20prP2da`b&Q}az`;VzfFp()(tks(Tb87M~4~lZ31P+L^XQS zrB*vfRLyqAT)9bV^p4?}zT!7)a)q9Lc(cUPI07aKHyuNVN5G9)dFUxmOJ*^3q%qp0 ztF~t}4wUqa6rHJ`kph|#S*Y`c9q>Z=N{gyT8C~gGi=8jM+#u<1SC+9qE!u(_oFY4? zmQk26t-LHa0%%J33@>usXButz_zU5)-_4_J`~8b8%5<t+U z$8%B$f8sgGl^xm&c}=4+UR9}r+@E~rlC>0B^F-dhr6X!GN+CIhh*!Vw*Mc}5gn&}l8t6e{)eU?)jTi7 z5j-_#9D>w+&r3@Mp776cFqh#kNQ-NpFnB!Vt?Pw7X0FYe@$i%pezv>ZoH^;A(h`ba z91PBZs&X!2lkj}G9bT1(;-;6?{yyi6*(2?yffhl*xfs#Ml}Iq+O|0a8+oKWgLl9UZ zXq?fQ5?URQk8OHkn^2$flGAj>*)XKkEn2#vTZ7)j8S97Z9nLz7H zy$g))bm1i_EmS6bi@BRD22!-X8kHDeWX^&=P2y2J`TM_cY0LMuRv(^OzKufkg~sxReF&N;}n@ z*84rVli$JU$vcWU_j{c&)U?smdjtfJyMA-!wGILQc7z%qDkylNUZ@bI`26|`n*!x3~)ZTtkm@*l8?6(_VoKw zz+g@gCj{P$Cq6(luy6{BbUS7}mcq%L8cKV+PsKp_K=Q|Cq2dOWnHEI5j%hOS`U#FE zYlN+vwD57167T8g{L9s52NyBRZUF82w`5FKISx$6Fv6~Ur%OZ*Y~fAE;q{MZj5?#c6DoX{)af9sL9WaNZPbr42UPMqQlw_;E?uoc2}?Mn?6J3Qsz97*i;hvgtEv z4aWJde=;c#Vd@$;3OpBTKpw)S&rFn}dyn9*-*FYOUBkzS_X}*%e1ti4N7hhR3uNLfw z=XLo;^3R;6nUBI3eGPB>`8QI?%Tv$JM{qLiTS;$7h^3dll~#Y8rafajFPu3eIl^+OQv`1*nkJXlr^jXqrP zq8rj_1W$BbWen$u5jUm7W}difl`()PUR;Hc>y|AKZNMYNyvL3H3h$a(TJg}D%Q^oz zSEG1ggwq>V!z7yRwBl_`o)EUCQjGbC`!`8ZKHqC{Sr# zY36-+MO4?KY+cA(@;rw*>Pr!FBs$2YL2_%w+-%r)?Gd;Oi|FpcJ4j6??ydi;4y~X~j#HTvU^jR*da=rAKW28vAZalnL?TvID7+bXcX; z3I*|3a>dSC@t&^o8k8Pbi+JgjO52Bej>qoxR!?c{a+WF=xl`PLXMQ`5q?s{`iEd+R_iJW~XpD_!VNR^;;ST;%9Su|C=vLg#VXryEhVva9HBE}(T2 z0%eDuT5kXu6gAUa=#R~4 z0>q1Vsd?&Cy|m)3IsS$-)K4o$4rZDg(KDFQo(<3@;Opde;dE!VR0GbJ@GRzN6ckEc zfm$D${w&r{R>Ky2vGmHbm{YN^f+EfG5Gn*n0}L!ll+{~X zBWN77A*BAX+_NQ6Hpy~z2%8tE?P2%VFQzF-oBP*Xj=|bH{+ergu=aKZ1;&j=E}b^~ zulcXEE(~DLFP-+{e^Jl+<;#H3p^8dq@c4X zqirQzQu^1Dcpl{7)wno-`M%%VUu&}j@puC)-Uyo_|HPR{7~+5J2q6c51B|w13bgyb z)rwcGa0nYn_nk)7E`OtSYB{5g5P18Y(TX?1@%pz^Nab&SAw8IKy|AS6`%Y?A(sxo` zy#AH0JAWtHH^0!6^SxHMibHr)()oOR?RTi&+uv)28#sjLDPf9ANA(h}@!fHcaTZ?B z;=SDL(|GQFbPFCsY&$Dei$AFHJBxWSs{^oSu}Do=I0;D7{Q8UoH*nk&%EG+WpnheXCLo zgEEu#`oYPm8OV@Qm2Mma9E3rG0E;l#n3)6#naPz^8Fb}er3Gxmp3)`Jak|RPL4$S4 z`iw#8#?;K@)RYWEYE_CZEiFl(nXCi;Lb7gaZTE3CUFZ zeQ9)Gqz}$W*QXhcX-UaCLy|GIDq~QpesE<{a)u!#O%YiE!@wRCfnO5C)0>?rO}Sb$q7jbbmiUBh`7x3Y&Q1l&a*x27PAApv)?hlpE(tQ}NlJH%r4P?@FnoT_&xxS4YL^Gcz&_>6L@i($bB| zNxHPbDf+>w8JYS@BebqV2V_=O8T1C)?W&$Ym#>t*XrGcmr;n9J*r%k>>9bHsMtWuH z;B=I(Hvkc9kWOD!iTwK1l+>!sjI=c1QRoK^uB=Sz5`j-irm0+M!B3^9>{BwB=I7G2 zPIf8OcDOXsfg8r@^QDo0!!VT2-TO!B2zy8)pEpZGodzeQCC%#_()9R$rO_~`GBe4jOE%RmzK7b4_Fgabq{rVYy@P7{068P+W~oaY z{q$OCm}7cEazZ-s>SY4;D=k%*nU+?ST$KsQgLKJN8HS9cK^gi%pr)r8GWCP-Xnkd( zTD>PueF)<(OYNrMarpSFlc;H=`mVl%k_M$ErQ)B;Ors8mvqpoi3g(HbC8rP4CF!el z=_$%zijWC(bcEX5G`#58fl?jqPg6Uy_eQIaIVztH4x*7`r(LHn#^Txiu@LQ34y`BW zWMb9xaHKYc!oB>x=)hJFXF3z9Euft@y#PYA=bk8fC`y}1H7kQ1Y1eT7P}*>1gEQTT z(k4?|(;DYR`Gpe(CPmcF!3Rw5GtPBYzLgo#zw_Y*O&fy z${eE|-Km?WV(=yyJYMwg|9C`DUFJX)eG{WiXnEmP4+@Ue?xh2j!FVhG{yqM1jp4qn z;b#(YmfIsv`w2BaeZtcwWpH0@Azgj~>TGlKkE0WPwQBjNJ5fKdXs>$s(U1MKQ4~^K z=T8TYMB)?5{k3DM?hZgW?dq?MVJ-u-Z`e`Y`lSvOf7e83`Y0Yw`he0?&2FJ8^1R0d zpj+|U(KLLZb{%=24t1dkLlJo$AE>?8sgI(h4UJh9C~FPtdm0 zs${J%J&}Mrgr|JRVXtgbHsCJu#{-|B6q;L-s9i$dN!lirNlZLlIncK^-OK>$$Hhb- zo_w98eMXUSUZ~!qDcVfy>K#roRc|C|=T3K~x(Rc`>2kmU@7Bvh)9m`t)2Z4Fx#Acj zVLC^;o~m7S%OL>Dt|PWIq%bGR-$U9qHRUQO_p^X&>#T4HpI> znk~!Jex(S>p|p4y!3%@6dZ9I8L$tUjA}O2QIYj$~*dgF?rL^CPvl&cnjOW_#<-h!K^Xg(1t2 zt`@)|R<+gm4Bbz{|TY+to*s)hj^)oBrpdh5%2of+sLTOmI-iIOacPCpM5W7NsA75+CkUQ?HrP;@IcqUk&cV-(3^at#2 zh3%o_59}TjM3RE3VZHT?`fsj!_EK$LV>nl`b*e;F2gzEAP1PSx$Xi#T^x)ZVDUi}^2fPqBbuOCJL1Hl#Hd-Z87{2u)y=A5_=iUq_=kewLwu-uvr11H0>q!{;-Dp< ze?(B(JC*+I^Vcgc2by6&fCG|j{(JU!l_>-WkW^eHs|=#^CsnCb`*~$BP3>!@?eAML zSW%T9vpZS&bq@(DYXf zoTYO1Ud~O9LlC{n- zpa;3O8UmbwzGVUqQJkS0Ume9IFA{&Vu zNyLq|ZA4<}MnkYwA}~dS>T-TShj3xyCgYM#24Po!&0*a7^xA9?w+bd~Hi-MjKoRMq z6dH-I5gDQ^g(`R=sdOm-3c+%F?5*~)!Bt?vik4%Hh|6ox;^?Ujrfhtb>r0I* za0mXlmr+#a?jAS?eES*0owB@O0^~?fdL>K}Q1h%*HI6azOBHqpvCdAQU`LHx%ND6- z5(>D+ea2+hXt&N(FB;t$ohKa+i<*h!XLkrWun&Y^?-G;zJ?6kg{t#o|OT5 z1a~g{jiS2D%y$cAaAb{{*ig5o0gl9m2KMO)`kAT` zMN@VdqOBzZoun77*aa#5o$Y-Ua1q?zeqK@^7X`!;aZ47oOeI?e_1h)&1`;@8iTEO! z3jhd-c>HFjabObh_9{;R5=pgnO@TrZh+Ap~aqGv#?2Y@g4?b@wvCaWJlDXD2K#|x; z1`0`lNe2)7(;xPPbN;!DH0gq&kAenCw0g5D;_Payb*dhv~L}rMWSrUZQy-XVL zemJA$qiffXct{Rl06#i)MCt^9mxyfvZpk3>ddZ*>iU5s+m&DTky~^F#8nmhsEC~kB%&#aBSP#9usnDB_uu87sw|9_R=CaSbIU0*}XP zb^(5h;NZy&m;w-*Hw*)4`a#J|&Cn@crqqiE4K`pa08tTU0+T%8r*z6|PKE=?3CGa4 z^66YMFjZ{w0zXBZH^9enQpAA_T3`A;(xjXa@_5q_CiHLGn}(^vPk^OF(JSY=`a@C4 zf8LZl8b>1mfC{d#!Dw3E1@EkXNqXQMfKw4Y1g8N-MaZ>11~0L!1_s#hbkZ#M=355w zT#3s7%nGhx@#22AF5zs245&@wSDA?)! z{cKGXuqvWQ1B8m$TR=|{Jr#gc!f4$RL@j*$y7aU6ro&5gI3^4*x(E%rbjTpiY-U6i zf0LKWKV%SZ{vkD5F+HHb9FZmipsa{a82~GhRO<+fxTTu|=t|$eU;z*d@GbsS3cy(^ zgvJ1kC9pg9dJBY>KXt@_X%VL};Ij0k1@+J;Z_-OiaG8k#(nJremP(;A0B4CZ`3(46 zC#wIzFkDClR*N_+@RK97c+qovm9gb#zcxW&$k0f3PZ9oTY?19|3j3doZ3o z7(SB%E5Muk9M(7zSfa2LI&)BLRNHSh@ z`HVrlQNo!yoXphkB$sVY;BYeH_%$a4(%!R%p>*VXDRktiUS|!`;$}D|VKZQiI7OL7 zIn&S|q#&0k02fA_i2w-`N}6W$e#Av!oJ}3C^l!UltbmEZ-H3AraU~4A7x8`rhkx00 z-Y`M1T}}f`jHfad#HV09;i(G}Gq7SpC~h%KC22pv6|*j5QJi^ET&EN8V?s?+H&1Q5 zD7jw1$%Imc5Bi+9<5IA_8#VYyg9#8b;dojj#oxf05yuhGWjYrQT*|fr%yODz6dkWCv%~xQ&-^f z-}}+vFVqB}H25frvab;FlObJ506dMjwgECtDBbr0x*fIhC+D9Hp#n32YQ!lP7&YS9 z20TqL1^r^k5^?~e2Jmga7)A*+0M!K2l*y)=`q9Zr7$*z%N~Q(y8qqO7{;M=tfL0^g zH85%dY2k0uvf<6&lmW>D1U6;0jcme=z#0GI1ux#AO|DQS>6W&CW zwC;u>$hwT3{X*#K>W#pX@PZjr$8Z9GjY^rLphpf&DB(FubiW=*N_cDaP$HLn>( z7XmI0cq3XLFBG^ouJqk!rn&+$1_j8HILwWxe4Y)sHkKy()93a^VIz=E8R6%qTr~^L z?O_bD77ElG(am$AJsga}wxkI}=xzsNft=T$zI8C(X-xyJ&0=dBFl>YnszpSufe-mk z3(OxU;|NPGaP-3-++7w50k}pK%K>BnQsbv|hcB&l#WlCOm39CWBP>ymwo5ZIX9jwW z=oUH63|GTDwNpw?vz;Fuc=8rf@S2|Q;B+!?aWM*8y2OP7)<*1H(2}|;IaFv75N+bR z5_-}AH_4g+a1&0`6tI|8ZpLUK8=!7F{dtxL-c>f%C`%oAn-%ak#X=4<-VJZ1s8b|} zTZX{95eMiG9!7CM0oz7gr~$`Dv_)XnL{n2Q+~LDusK@NraqK&xB=MXW# zvGM2o%I2zg(#8AWQ><+DbT6a080T4mZ{x3Q6-U!^e#Tg#9G(iK8&_oqcer%|;BI=F zvMu$OK7qrt0r(~yu*4AR8ekNc>O2(?IHGBA8bEGvpFThumgWSGek1xhVBRRG$BOts zqi}FRK)>m4THBZv;Y@8?@Lb?jplz1}8%OM3VBW;g_#oqGp{ZsZ9C1kt+?psF9&8lv z!GXpxZ`^5nuuZNeiVlGy|OCW<}_1!7Ozvv|HXBvi5^4if_~9C!L6 z(CCL7ik`IaAuL4(ek6qmW_%n+MUvQUNDw#0xj10qh)v@(K;DSHjMIR2BSsdS222{8 zyk?vl6@B=Su9x{LCEg%D0yS9gzbfE9<_u!*0>37hw)Dhs&+m)-l*b>1rCH?#rj59Y z0f>$0O*qsE0Bgjl2Q-dV)06r~OVg-1!HHHz8^!DNNZ^1q{uJ29m?Ibk68h7VeI!!_ zjYHRn?Ep)~09qr?5Ih&~YI@UWStgCbMirc#ohxjza$exr0P(1=H23lZfY|^) z=QH@b1AUERIK@)|YvV5zaq1tK=n|W3iZH|7i0&P<0TkBXI9ArNF9GBR?~wW%hgm0_ z=`U#pNH@_mV}MZ%rg^0RcjH6H2S`KJf_dYd4TaRj;vzC|Yh0-|UJ8mh1kUsEQZIwX zqt8yuL^knVlLZlH+d#=+fM7F zuSfxl8(m+6QPPblK;_&kBPV5|4b(rWwV92Jne%Y+&WYD&>mq*bJB>E}{UA^RQ4Wj(pQ+kkouL8jd(WgBDH~ zGw~n}xHv8p)(Trqly_duKsaK&1iYIlC7Wog0KF027ocv$4Rs5^%{~3Fg~}(kwvn&^ zGs=z1`pgG8;_1i`<2a#Nz`N-~4Z{@B!B#kq)(*s=i-t;`1E4oCrWP&Qh)1Mf4mE}e z0?d#&*d`bTK(V`qNxBC(j<}iv5Y99qFYs=nlx&f7d=uP+Rk?t_5s!9(e8V*qLGNzH ztYM{70O5$12;`esQ=Ny5l#B})IAV+e(3=QT^8ty2Pu0jR2L_H#n46>4w6wF$c& zSUG^d2~;3$#C=CInvJjG0wXBlIe7gWqomLpECWpjd?^c^2bL)7kq5vVvCcra38FEN zW7*96oM#K&YP%_5hQ1MJZP3Kh!nWC##-CQKxZNo3ZgCnwaD0?@U>ovIY{Miu;Ebjl zR}S7dx^V}hm92M35g-==m>e-W03=Qn)!r$YJ?8^1j<9+oP6H$kS7c`e9vmYnlCuCI zM|uXe3ucgYmo(Nn9L}b@q@guxH~139N_<@2%CXWyn$v)Z<4zvgMseSUCjc17gYL_= zZ4A(HY#IYh9C1y-1pp35j669FNH{im0eIs~Y`io9@>eoIy%E>YoCbuOK-yM-McunO z#=e66B9&v^h!GrU9Nb29L!eo3ZNvd!NdSh8O+szHG~s}m!`E2VuP*_)rk7Gb(JOIg zz}JZ5pVNR`rlgbJuM-3W>wDD3B`r_-8l9S@80Jjkh zla~fun{XPLhY4|Du{8T~2pS;V^rF5GLb2M3nDQ>|L)8}DBe_n_2hC^&K zHXsiifOc)OaS$AFx-_HS;HJ}LDI`KoBkB3c(nbkr9QsDw7XmGuo-8po$R^MUHv`lg zaW%@B&44#vbiEw!cWX=VG7*?FDr?^>F>??cJjZ|97|@cBrSAc?F}0f#!%Z^3d=tiL z<;uA@Amq&JCYw6}7suC>H~g(zzB27!M3MD+Cu>ghsp7w zy&7XY{pW2=Fkw-0S9YT2h;u!%4N`Ipr2g;1|JvplNI=c;HVNJLE~dEdSOB8qYho#T z4=u7~v0&J1$)1WsM;!{cm}|G-;9pqOSnKMPDE0w zs10*Mkdh-oLBfILsYXAcYG#(c7UKkt4Q^KJ@(`zej5y6|Tg04!qwBcR+9^t;K26$K zu&|hcb;N+dDiwe^Vt~n0ft7<7>E^+L`nb~dj}WF=RRxGE979K(9zYvLU(~=m)fuq~ zd3mN3dLXqg8BXG$_-Hk5eIKoa>TL&rx^HF z%WcjKm>nAdK-2N0x9-7cGehrqQ21vMV09$M1psD8+&|+qKAz=^Bm>K7Po-L(kdI)Fdz;yYr5k(`)gtz8q~ zPVqWiFUguK8HG|9(0E*^W3FWQopfJHnAaWMkpR6TZ76iY?D*2KyKOQk_&dPbx!Win z337}YVC{&T=9~tY9WT>dbwGy|(s^`^pf<2@)E#lU0F49g;0Rs=MI)OVUA)&ADrXy^ zOpl$ZJHCcKt?ZUd1||=`0)_*Zd_<2B71-^qF3t?F9&x~P8X$Va9T?C!I!|a<;dq#f zrM_+1u>`;#Z=vBsACNY@`49wtPY|ttKw8mrj2nRXh+8I{W`XY6@u1XMQfjZxnw4Q( zCX`{%ZiKUBK4xZI99_Tb##hf4xKhQGi#v&>D;d}t>=}jx@ zBy#}<&oGKuEQMZX=pNCJnX!7rT`V&=Po(K0FYno39x|o~_5qe*H1lDjxTOuyod*OK zGcJ#>NnwdacD)rOGMm#BGggndnB<)YgdTi9VJ>X2?Ged1d8!$!N8A)NCs=TK{Alf? zQkZXH34ctAzRd}b2u(24I0lcma!1<~_;5_1;0SMtA1{^N{d&CtpX8}x(xYJ>#SX~57=5y0P)2P zqZ1}noU@oCz=0+{falm8+$nq(1RY0HPzJ0AJd1b&2b{R!A1zDe2s+~VJS42QW&tuz z=cP=uD7?seQaVWD7363+JPtJT`Ovzf*uu0rUIa4-&%yThPHZ)snO*3`r=>SPG}wOzF=(Yjmd%{ zcn*N<6v(te6tO|}<4TbL*>O|OEQiX>Jb@$axRPh9wCBJfHq3B4Zp!WVSlZDl9mShj zME}QW0NDW?a~sYdw4QiKw7*qa>u?re?no2yCNKkTCra_u0eEf$+gRiUEEwxqx0A0E zf(NUQfeP~op;=r!M7a^rcdV+$L3aG;{6;L(r}_Xp!)kGey!{B6J7UBLT9dVS0P2X- z4lfc2Izh_uHl7tIa632WVzSx0S+WQ-A4k=(DkF>lsMFJ=wfB4BWwn*o08SH5z}M+* zI{nRm7E2^x>EKp}A6{2mUDz`-bKo7(UGM}T?T9Nd&^W4&s4Gqbf{y5ZK;w`(o-NNw z(-!EBf`S0)5<~4@7Jc6Q zk=Buwm1{q-w@P71dC0*+WMDsU&1A~1o~C`hhlP_+T5tAav-Uo5RBj%WUlr%J3+cxkTc8rOslu2SLSH{up~1S?&`?;e7SMYd$dcn*?~U&eXTd` zUb;ETt{)3uwmGB+>$h#wJN6Xz<;Eg9{?z7=*^fIm?L2P9Oc!@<8cl7#Zt`H!%QjE- zp{q-0_HysKmps(fl@7kOF_eAr*2c|Zm6yM_@#*+3wzB+D6Gr6}MkGYUJs5|7%QX3S z<{wGB&XmzCnn_By_lk-}A99Zq9)_3t@yv^SyS}?42FuXh9fkB%Qim74w7Csv``0?0X?^_N&g{r5 z9XC7(tZE8>ufvf&w5KD=iQ&%<6i%#{Da!UHsYg2KOp;zsY~!Zk!>B5=)Hh- z1*FY;Kt&yei600Il5{iU@SD}Q(BldR;>YmT;)%GZ=+t)FHc72L}kYfOO`fg0_o?Cak<28jRl!kuRF}!=8 z$l#7hMPdQPTD5wDw9zD)aubW2)UVE8;fVdGwh#b=us4BdTWV zrp%3}cBhR2G~;B)20H4w5nr8v_F4G0ju>2#xzLWqwA(tol^)&hNGEdLdQ#%KV0ZSj z=f=Z0r~jiPMaZ*8wQ&@*s&wA6%k6;-z3{aw3%J^Gz6bmF2OXsz?D*M^Fi)j7oZ00~ z9d9_X=kH(tq8;Tgp6*IH^9ixV!gVS(|H6j)82a3|)sqg?xw)}~&Fj~>n0{+#db_ee z7OoqPkJ7epaALjpZ1_3O^yj7j!`pYjMR9zOf0lN%<7m>$0V*I$F_vg7U@ug$L}LNv zR21$G?%=3$1{Ko;Q+P3!JxuboWfx4)Ni>Qj)mSja9>v7ORK>&?V~qaa?j1090x{ow zfB)nIvOBYH-n@BjX5O1QztKgCS2VHF5c3slOGa*EJ;TU-SHpFi-DlY|b|8}(q6mM2 zoq}hN34bcA4W}d|T4p%Oko2Q$iZ$8x7rWmUDu-tUlIpKme-~o7#p3Z9SjCxr?tEXy zfn025580A4m)MuBh_9ESlo8q*NFH-C?6-!$s@){8-rJBNbi)neH%RTsbq|(HqYqn} zIxi)8TGFVoQ-FD41s(>dNV9>D6s${!xWOd_yQxDv%$_|JcDj4_fK3b8-c-1y@h!Qs zkoB{N$+hKDQvLnLIzqmSc=hc~wRM~D#GJt!QjuG~-{=5Of4oHoQ6V|FtTk|nquyMqz^4fLV@Zi+pU)hrTOE!C3VW9p7 z=PfOT8|(@G)oY0OSyOoQ5XPPX_3Djwn})2OXH^gjFB}QlQy`K8S6I8yWGwyc>C>-{2OEX49;-wQ9~MpjWL|U1d6uD=N~hC0S@>`WJ3+%3>h-c z5XX?HX$EHoS`T^Iz*1tk2m5wot(lF6voPu%!2Nc&DrbEtpLplWyiSsr5wAOH0AjH?8ti`{O0`A7j z&#f~|0r?@rK*&(ysYHdJdApJK>kOx@NrYCwxQ!{sk;Q)*`q+?yUk!hnx;*p~!?Va? z0y(z6Za`vgXf?>l$9h95a*6Qvd8RJU8l*bZ(lL34D;*qXM_y4H)|kG1Z=2zyHOTw< zN7tS=c#@xw8Tz3YDSUrou>rj$p=9@Y!vaULnKL|XMYcR+7>7g^2IS6F!!j$fDZ_x= zZ^5`uI>Q|sQuKpiCHe{`Mz1X(Vx1#HE>_f`*!do)yJQ2c&(}GVmMwL0D44r9O9}f}-3(ijy`-+*n#>N~T-8~- z4y0sK-5hIZb=)AQZ1ee_>v${TqpYj4CO$vby=?kawDqZcU8R*^%!A2>;<{0YE;>f! z{^hz1JEA*Pmu?L;X`%Ln&8vG82W8^`f597YBH!Pt`x;fu#5x(-Sy|`hOpaWr+hj$~ zHq`a9CNs5lJ#CGEE+y4{XiX62Cgd^!(1+D^{Y*VtKe}$0sha2VI^-X*Y2O`nIBsIy zW9#cyTkmeHyGQkiAl9E-LA;~Chsa;Y(&|n*2s8{Nk16URFuw&$MAc7F^{>QOErEDj zUaD)bBI#`1AR7p7DR3Ye(#;h}W1+9;t_-y!8JFtTS&W@V?_Qdqf=xn^_A=gH2_H~1}%+0GI zcBa9L%!@RH+JgRTe<@iosICXD5w&$aAkMI`;|UE~B*ZM;iMzh*oSa~#Pn{;zd2~b&E+~-?~qk0Kv)DYUHYgawYoO z@(7JOCtE9@Uo6)yRsdVGu?Kwf3~>X4XOh(Ui8*ovYpe|?ZOeOEVIw)`wmRKP0U`4ZW7rKBun}@0#NmSnz$0-NbSc0uM5^3a$Ef&o8 z0NBjnm4Rf+BP(M5oA&qjS&369zZEiz4#7;n6~5Fv93DTob3M<6yy~}N3_Tw*=L9k> zeuW!FdW(UwWH13Nsi0kQGfm2)jOsnge|YvBE^u4w4y z>*r6cSm;W9omQ=vQ;%_h8MqibDI3>%tMxSZHdN~=5x4C1Pt|%FC25VmEI_4NnypAz zEXY@A<-_ISO5x`VgS}Xbu;G0k|%uBQ< zk}djGHa_!JsvLRGY-P4KJ2NM{M1jc7#xp||@Z1jlpCGpiv$GM(pu#)Z3pQ;{b%Gb) zz{4xy>% z<$ArNEu<<|**Ub=f}Jb%J>h;>qLjGu`Y{ajUa&Ek7#j7TSUGjjK?^#f52RlZ1JS=s z^UjS``Y3Ar1Wil}{^hLIC|;LWlG@||dnij;<>s;=Gbb}YBC_9ztYWlnz(n=K`wD(p zqlBUM`*No(A=U(dBn&_SiD9bOd6iit7r{t-Xxj*oc<@Om?Z4c+cD&&IhD5< zXl|<5ChO2c;&}*g<8%cc_WPmUh3q(>f5yH8dvgEi@-?(hv@mv#Nz4C3uZ9c7F6Pjo z?)M11!6h)zmc*`kawyHR7QlRWKRMsOqiqYrYQf;-F1P#+Wmqk0ldO;RHMAI6wDt0< zPo}$DwACfzfQU=UH(xCGHQTWuBp?QEaVx^0jWbq;L3>NoHHc zX8i=DoDWHS^2v3y3u4j27n&#IXp3M`oM2r!g%Ubq`>uWgEdieot-M4%TQW=SK79|W zm^AL!ze_*AF{yF`E#mJEtE6~~d^41zeg%&VjVI*D6Gxk5c6zzgPam9z;l_x>Q*P)R!&mkyXc zvaVHLq}ouqlUneHhlENiw&zw=1;XPa0%$YeNmGDLIg{vvm9r@tJ#2d&RD~`q%97xUP5;j;k!DRf6-m%5Nz!_~=Kt)0Jk+g63mmAyh)AD5ex1y~H>JhyaJBn&^bTng&6mOW}&vdRmZmaL-b zhVP;&l8AopJ0DchEG145E_}4|ZTdU&mdLpot5RuxH81WIk>}RX-GzrmF1C7AFIrj- zTCec*dCajuqmVziiziHqdQ;uQuHcz}4{r8-TfOQK9WrE&KJm?1ZMKPRQS32z_4x>@ z6+=uFrPVAupYcnTH&iFDq7|LRCVVbXRI=>+ zpN|L7;iP{*=p=r8)lsTd=$5$TYE0ED6k$n9Le+h`$HLbScy0G$s=P__@Tx*e+{mRB zRX+5W7Gu79L)8#kIhq$+ber6`x~h)ucek}4MieagTAZ3?EM0Xxv}1gr`$isw-~nE% z2ji`oiUi#0*jQpm{8m@x(S6KtUPYTf3*-3rd`)E1Rih~r4BY}Gy{%Wp(T_S-1m-5u_gB6~jbisLfW_RdvmUft0a7_+Ro#C<4O&11IVSHUuewEB1&eMSxxDfY zz5HQbEHV}ivUQ8z*S9P6Hyb+B954T{GSq|O6Z00x>OQMJq+C?;c-*RN+G<)2JS!tJ$cU zBO3I3)t9tq+r4rS^)ec0XQG=~Wp;n|*!Nbpb__2W@%~EI%m$noys8Im%v(*jWzGZe zdERPDO_BR~tB>L~K;`NhYlzsiy(f&TT7Q2LkoRMb43sG=jjSxT0Mv_;XnmF{~-7>mligJ6h*X`D=yP|M|cUGwc3@fpYSMS z2kcpliTKK2zkph;2CUSVY&}-7iJsoz%V3yvtwP35Tj<4j63MBGQ2Ng!=H9~S}qaT zK$0%e_opBdL<+jW$6}bV!5H$htNuT9zbsl6>wNiZMSt3hey~m$K_U*Mn-)hi_c8s) z43y8pEot-lpm8)No~?+Nz&jIjBFK_g%3W+Abc6PDaPW)_6x)#@bQwby01d; zAcMofPH?VH=M2$q3C_?uG0g>!5y2@!(7G6VII$(d8QzYR4TRK#33jC6Ro&Chpn{%` z5Y=CYF-6)E7pQq(i?@pREy4?-uNLGsbc@ zXbmH6+|DsgZAm^Mb}h9fqQXL>Jo@`GiuP8j(WER~TXpJ;J^ z6cIr@nza4Eb#6%yke>|oC11X;Eyf+My}@`R!<4c}VUslq>ivfc*ESdUK+EzXJTZ2X z)X&&n#<7xqFzm^qKvwylH)hd)`B|g`xwN26<3{#wDZb$W`sGDqggi68bdWXK`+KPu`Z;c;G6~?{j^Mf)HVvcE3y8k`ZIXSyGsG?l4TWOvUFnU0Ki%=l4VfR&lWam zOD2P)(%HRtf)-aC=ND)dn%NTbAli?wXU*OehuCJCk;>iGI*TMDeQU|u@p8hz* zeHRrwlhn(lOTF00nny9sM;_u}3rZ;>gdqz~cmW9xmmxdQ7VedlhQs{@q4p5p?@0%e zGP(5I(025D!i8&$lxTfQliUOZHwhT^CiVA9wZqymatFPn%mJdZik+e6&k|1y+z8@^ zw?_$l13Na9go|U_>!HRL)P-f^L`o2BSAroF|F=V{o-@#nb-95v7qY=n;u0y~`@WGl zBV~p5WMgS*Rfv&`0~~x9M^aW(a!(xWo^bStgOp6$SUL{Rh^`8dz|v2&5zt(X`{Me( zxXFKfQ1KYg+CNG{YA=nq14Cn(4Gf=LTq3*y*YqM=^5x{>NUQcoz()xT{h}=HMHJ13 zjAALQN-lm(ERWw3;e=69#c8JMA7ZRlc3SaU79YR+Lm39hUMP`5)5$12fi|t!lWdz( z{DSeTj1PTL-Q6t0*dP1yy`Y@i(-U@;_{&J@^x^;;5mc;KnjN(KUSbb5vhrTwx}ew} zM$RfmW%LIEeI~Zd3Di#&FM;?>gk1JS@nqv?4FL{#SAI7y4~PY>nZ@}+HCDaW2QwjJKP~lc@A=(6WzO(>X0g1Zhr{O=FK@5z z3vI zu8S}R`HMxx`>bp4^$^vi8`KXjjxpLK|Gq`r!8Nmd47B^H%JLh~{87$Md7gH#uM&< zAC-d5_h=>z{fb>l#GRrTD~t{)F`2D+{&LKFrU+tr>fGFkjK2gC(Z{wVSy zXhKHX64#H5&e{mBf(!hdD0cwYeexa<|8Y@2xE@=CKKzIg5p0R;5JpD6krt1a)Rq+? z^{|uR_Xv6(t^;uySHF62T@Orsz zG9U77S^0T8g8sq{Om}VVh0Z~GnGK1_C|`uc6I7PSY!T8DpRpu5t?Up32a3v^2-#a4 zZ4I8uu|Y&#P}XDvmkLVajKk0zT{KGki%cvno4pn$I2{OtHnrghGovK;eDUO%F%0_QeFTJgGK~FYuFeE z@?3iPd}o3}GGdq!#r4k=4H({za-`t%h$1%%GJY%Zf#GE+y@IrnUUN&9;O$PdcQb-i z7ZzQ`B!L;BjxZvyNJ1`#7G1`xUjvKQ*^;KnqWKJbc|#W}R9KD|Y3T~uxoH)oz8-1= zt{Ek64xq(1`K3DXP9NJN)*%Oh(06iFa4sK|jR{fa)oFfQw&NQe(BN*4V`XkMZl33A(_ zIe^fok!OC;O_o6FB?l=OW`xSYV5wHQr% zceE~`H}M*w``(s}DAI9ukTF*02l6Gl{k5A)ZJ?zBr3^8B78)W@ejB6-4sde>df%$| zbr`&<)&WN1Pr;c2esSIghlWnsA<@pyaKxd;iZJkV+ss8 zyRR06F~V0;Xl~JZLhe$XBMDR%OvgCM!8%t#xddROkItJR_-9X(zC$7M1>P0CWq}s8 z8ww>PVvz15Q5U(w(MwJNWNv?5x>4`I33Z|b?vC$kPkw$(*9${QO@K``NsKO+fe#Lt9v<`#Zunyi*UGrOk6Zzd*cN?cjqY7hVAx2-A4i#!t zfU)BXapyfk=TGFn7kq>i>{ZxHoJR< z93_wgZJAYp6po+K4TE?U`WOD%!ZGNf_bQaYb!XjiX!ttV2AT`ezT-T=m&^;)T|sLx zsxTPj8@2t2-dp#L4T=7)AQvwVZSISaqF?w05!R(JP!6rmx?}C%V}!)A0CysH*GX-m z`mD}p_uYa8?htP%bcFjgg+oc%>cTg?$l_&%=NusACQ>?uq%xHpk<}8CNV1=P@;t$>l`mQg0njlDf zl#IxtSa8;rIFtRq6n?{y_}>ekVuY6P$~K|T1p6Fi1FLhK!(gzq#5gY#=$X?AJ@Jyc zws9ah4ny!R+2}%?dOGV4LB`j?v%#=8EDS~p#_HH)ojdWqTi7B2>E?bon{4eh05XO+ zJqk<8Fw>}cy`K-P8;#?KUNqWB)cNfrxutD3h*Jv3fFXFD9U5W;g{pIk&VdY%E5r;% zoL=`Kn_`s;n|>YP3R4uB3$(K*Xtiog$m(Ke=H#LrdMPe$pt5I&6ahZ=fDH9gyfyDk zAiWrKw^BndFD~Avp|`KteVTss>S*42&0vu3*T^hhdcpp8G=A_yXC=X>H2z@dtmMRg z4IPl!`dWT4Z2DU1MEW*qz8vxo`=92e4TIDI4Yj8OJ(BV)h+y&9IZc+wYI?w)q&ynb zr%8E{6g@*;%l8DI(FsS_V>Cc!b4Ykq+4SqpUpi(cz9HHz)3Hc>C?_RM5 zDSN=PFKX!3zRo(<@}h>0Tadq`=}RFu?Ip8Dj|b<{n*^PqxpteMH|*(SMm)qdoW$2^ zoC6-faAu{3-hHva=I1}mhSh?@uz4>?y>3Qav8jp`nroJP^#C!jDYWDX`4Y10P0a@m z4`60NJ9Es))Mc7)=>@p&dTN$X&yes<9v!*UCNxf9*p(|G{dD>Np%*tTYBTIIIV4}p zqgT`0AUq&;m&4qGq2x>;%`2S^%*oN3a7&Rzo(hFGPUX3ioBsJ1=!M#oM{+U$_-u|J zs`zR4#7mwZM0Jl0@0s6+TIaRwu7w6MryYnKuRo|k+cVmXPp}}igZT(z+?S3WvY?Vh zBl>UYkB#zSp`n~_=2OeEAitU)4b24_C!)HU?@F(QTC}u$h?d5qGcoFNc>49x4C?3; zbT%@bi42a6H)Q(-(WCmH1_&n^Q5prk*KC3LzoijD8hO)O8{NYfmD1l5Jses-$+IDk z_sbta@7i?_x-+6%@Ku*%@Q@4#524;VlOnV>w9f2|2m-5-n%DE!##6k|eTO>((yC$YG*9-1X?oII9v0tNu+Be1XYjXqQ|KKH3()$d%la4v@6qyn zv)~kqiWWHh3lRqtaTz&wDsL$rVrS8u1$+mi$y&C8};9gFWCf;UCE-+n63 zlbkQm?CnPPTXgv!k-h4Zvm& z+L?pUnF8*F$mGKHym~rRPB4h1-YS12Eiz~ZeTd8^Ur9S}7R+Hm^^5oNX%|A(ZaRRN;m1vtufq$EW(lU_&=*{HEj zbr&~+rMa|FU~>;U^hVynK{<{K&%fnX(-ciuwUj0o>Th2{9GA*z4Pjn~T>f;)8hRFO zUJMo{0R7aS6qVZC)`3Lz%F_3IA$H_oT#8-3gbEoV7ZxtPVm9A;0LMUKZOXJ5@cOEy zztOhqAEQHXedi2492O9;ztLoX`_jxIR6i{0JY1)pNPObb!*o}jGnV2)@U1CJBFGPV zEvC$8BrWlvXXj~CwH|P^OiTH)AYNkNR<2F6tVk-#wWF=!ne{n-mPLR?xRr|fi|Rxd zWAnhQyDQg%cqM5uxJDbRG~+4zJGpd7lHi1p#5=iP(_(5-r<2JD+3csh+k<>PF=vKN z#~~??;lWBvmeC?z@13)N>QiP|jyH)Mk&{7jIl-5EXtgF*dgbS(gK0pYyuH+)jEu~g zPq`Q%*0c-BnL_Jrp(bn|o#T%=`#DcD9j%kPcb3kGqMn&=mKIa2O#FRvtZ31~`aa-4 zI>()SJ}76PWeLHOO?H;%u;UvWSx%unJ<@BAF7<{T4l^8J;e|#Y_+(TLy^4ltzeTc^ zD2pi4z?p32vvAuxht@651C{guTChnM&ZoGBhx^rmxS1Ls7)0|Kx|2QNtAR?&g(cR5 zly5%r0PD2;lw+ZeXcxf(kv3ft3HorI4X7691d-pL%He6PYyq$f2$mdAjwa`vqOb*X zFeGGJ?rM5AZ(iK>s9{W zkxwt7MMGTA!$lT6_-A9zSel<^*5^=aja1g>c>Qw>od8W0rgcGXUn&{MLJr`<(@Xl2 z_s{3J{|`hi$0he`dbvU{Iz$u*(2f-`rtOP$*7~r$FY>!5Yn+<4Oi6KO?XEO0?SeN=y2ii1dMwRx z0--Ev(wT9z=uO^AwHGwZR#W69AI(;erd8B3D>dyC(~`kkCCta@>bAl82jP@yR7n( zDOUUc+CRYlg^))K>K*iYi-<6Gax9ri)X!P=lweO2XO$>+bSI1GRInKoAw91)M00c{JQoa@O`dD?CLXG^mLVcNbpFEXjqAe5V&vL3z!y5;FCP zWA)bHt7z!o^x?!X=4&4|rZAXsBDteKniT_)vp(qw>i)MSP49l;%j}JW+Z%}|tDob? z^kVfx1DKxGr|?2PZ( zGYHGODWWWp@%3)%lM%?g?++<8`<(VZ)Ia( z>uaz3K<>HiuIz>$){GAu9qY@C0)uReeUsD3Q0C9S$kdd}vsYIk&Lncy(bjl!bw$fC z2U7Iw(JvN>B&l+Ea}RNNbMKVV%p)-Sx4nI=9tj1;^<96seP)j{ssC;7H+^8qu@9Ze zu>QB}J;<9I&NhrE@87!o$cU!1y`z{rtEvW1`HBpl^7Z>sY%X@lo=iCWQGzQZ*X(yD z6Qka_q<}~dXS}obmkf$)$e*u#Em@wIZyT(DG;m5`sGSuECZN~KW;^dUB$j3B~(Tg*ci{OpkSLE*03q{u0LIoxgwbynu z73QckVr93E=LhO~7|SLo@PxMcicIae%dO9kFl&!l@@sgf4;$=Z}I0U z{(Of&-{a2@`12$F{DeP0leEZdbrKkK_NE&dGwp0^44l2S-?{q2DG#RU!YNN??egmQ z5O=02KE#9Bu&Zgn)kx-3IZ*_ke$A2O`rXjjG#vmpX6b;cDT)hZisH*V$3y^CH$2Xf z8y@HL`;q&x*S?xYPUt>-Wg79h`pZ^-*tFrT5J(L>P>l!rZnv*mce;_RJH5-!!&uPr z<@QJMeDc>_$ji&$`d}^lkM5L`SvC7l4`kOGdNT&{ z#NCtQeaS1;ClBOoLVe{-F0Z;)RzZ%0?f%V))Lqy=#;+-NLm1`JD~FIbOd zH~tjCxUdKKC}vDkFZ^BhJc~!w75G-)9zZ4!esh%zyWzYI>h;p^FHe%f?2B74mu~02Gs__7 z*Q3r&zs>Su>g}8C?E5hK6YL_?RxV`Fz_0EEz?ob7rA;|sI5BoT$*=3)En%8wyyeRb z4Q00>zHUv-SYKw65?pWbj!pFoyqM4@h_AzrIpfL4Uv5v0BA+*Ykl;yP*!`<>KL`#z zfCm-NJJ$CRa7`3J7_vU6e`3J#@XcOLYfd;Z7j2tzvU@O3-GG}j zKN&!ffApDbF81A#eFM8YTqJ)}zAl)Fy(e-6VSm^aG=%*wS;m}inv*7FKJ{qIOOY}^ zG3>l-DP!N1sE{%qHcjE{qzvD?NqDy|rpY5o%FMN54>U;`zos!KWsHw?)AdFfQ|Z~X z@u-a1Y|}LRa~U(qO5}t?Z2TT6BW2}J;4rdYM`VnQ-G;ULK;pu$9GiB1EMva2YKl&m zF)t*s!asKGPt`KUf&FoI%FSw`N;E#WtFT zy(MGbVw%3dFO}Bp*#;To+jOE{#uQsONk_<--EQni#MZX@9Ae&duE~Y*TSh}>S1cIM zxUz~U856?(iFFE_mZZvuN`G@b z(9hmw@02Onnljb=C5i=*)}s-#P_xpVq5fAc0iv()D?s@zhZZ=34}jL86EM~CjqNs) z(FOS$RsKY%E8B%}{NLu-z`SqxeN3pIJScm43vPrh*d>AYS`PSt{P+|p`#Kwf*NE--j-SfvD?=Czg8zcYGwN4!80-Bd zCxO_LJl^W{Bahcs|A07Uj6dQB_w8!&j+GyHwSYmVUl9DF0K?WtVgKZ}xj``dXMQ$h zoY>+}>zjsI9LEu8!xx+lgkR&gK>nMJp%B|E(-|5HFmL0|H9lW}j3Lv<`4EVGjt^k< z-#aqCY;%GeE#qje@4zs8nYB96v*S8!&I{9M<*q_I{ z*RH}XAXgni!;$E{<+D&8qx)-iy1@A{+<;B5g)p|nC!F7bq3~07;i0(CHo8KK9l`sV zBXBSdjpBS@eP15aS#LMk!J0_E)RP)Ot-R;L>>S}D16d#5k9~EAHG?U>efTKwz0Aen zeGa@ML`Lx*aQ{1A0`Z57Fs;1uyae+5@D*@>Z?io#f6omyj<))~y`40I1`Z?iw?uG~ z+P)Mn_0W*{CFW!F<4Z&7>TS66mD6wGct1WA_#@i`1fFyQ^#m@M{4tut%#Zq|d@mTJ z-Gz+l`yXG-GUHal$_KwjdwNxxgFaxw$ac@QEGpyEx1rIX=t*uK77QLviaCj}DO#24W!F^7$wv{c8!_ zWX9N``uBF)N>W4vtbw}eoCaFI3b$o=U5qwsh{BtTX;ZssKn z|9yDv8Q$GhBhOX}NB_#TMh^@QKHZ24Vi+F;ay2IjFug9$>hOZ1@w8!$;ORj_8j4oX zEzZu&NjmAr$H7Y{ue-7>B#iN34Zbdn15|v&`AIr&#G{i&Shv}I7!M;)>8JQRz=&Rl zaWg(P2{YBy_ien|K9MiZ)W|dC`HIY}%=tO2+xv0`Q}5c)4{NJNqmN&hsw;$U!16=a zJp{(|g6iL9+Pa8<@OV$bZI2iUBLn$hSg`k`JIDgJ%DTotm!GZu2N;;DTVUXexXmyE zYQrFMs9ZSL6LwDIA~6~CqL6!g(S{BD%o~Z?rpHLlK@Rh;T6bTR*dTw$!Q~}ffXH@I zniZyi!S|jQoH+KUgv@!5lUO;-FUVOcG^l`sHvA-5UftkL-u{5Q&9GnJ8Gu>tdp_c% zq3xC0G>G^Gp7^;yk*_RM7Ubl>jf!m^wnji}tG4-(){nRlOoe%J1D^YD&*SwY$L{qY zF-JJ1mBe@oryLGC^4`8ijf4p!S*iJog^GLy!t8)(BiJ{%tk~rR2+$vXJ<45%7B&&n zP?x4*w$2x*w~h=-7wv%`LA!C70jFlp*{lsVY}_M^H`+f7V0q2ljjn;6I>|+vzLYg;|LxAAsF1&OWaPA z{Sh?!HzWi-B2k{9c>-F&zgoB*#&Xs97+V`H4jg0zH3qRY^P|udFN$)-%dFkMYOCb> zp+BAw{}pG;syBt>IsJ=+8qwpp`MP}%qo7e!C;390mNPBb-Iuq=;*q^qIWN~XjgxPZ zni8S z9`5PG^aO{i$c}@)<8~QKE{-p;v&t@HZ}j(J!i|N~zHcjRd8@=0M*e^v2yx#gW1EkA zGd+xTv_Ej~7y-=rk&}Y;Dt zCS*J+vx_dvR-y}{L$hf7Lz|teP!$NL6${deuZ>3qFHsfbD>HN8px-w1`mQ6xi9RP9 zZddrv3~sSW{l=WNwG%5wK;F26p^$1n%TBQFIbyjj4$h1Skf$B=g66jlctFi~H2Ldi za88golUoA(yVs3&-+qP(4af{?31z3nh)MJ8Na8|0kWRp%0cDJ_pW`K4~MP$ci~0Bb5PeTdV zBeT&#!$M3K9F3Yo^eJl=ar-vSaA2Ilv0^{o8a|QpVw+LTIk4&oAAI|OYiOdi?L2Ot zrE>L5PfkcppO7+DFyIOi?kR}hzQvARlOD!k8eq&U2NFD=>(8*7JKjtn zs9l!3gU>8380s6F(T7uU9<>WOboUl;exTZ8q=O^$*@5aiI*XH8c3kAXIa%DYmx2yq zLh|cKsiM#M$G~u%$4*A^xKeneKVvU;2+1LkNxqr4g{=y%urpfyN5Rbp+eLpvD<}BV zYb)ibk@_FGN3G$~ktVbdf?c}%1V0Uw*SY-8+ECzeGu;kF2YAs9l|()0sV&S#K9w8& zHFME^7;g=aO+U;zIfn~(yk%wPsFZkTso-C^C8Z>fPe~VsFiBXd!Q>_3HE0iW9&X{O zD&xT^X08<&4s%kc@G0r$Z$CK9$)xxePX$+D6KxJ0Tr<^9$VUaDz))%dzUP$mc_~vT zjGZDnf9Wacewj+#v1I&&lys4+rlgNwtkSS+2M zQRB%+5VHNZATT#1y*fa;KL`>o7hm@hJ%2V9O^pj}YOXA^^$|TSL>QfMt-L^;g=db- z1x*2SHz8jh?R6O42f?8eF!p^AyjJ+GKn->4aXuwZQ_vzw9HxnYre^2D&TTly5fmG{ z5Ur9-uuA?VAJ80V`Blv#2-<3|lQCLiv> zHusH0r|ej-!_p4;@=oB3-wB_I-HgxW!)veiw2=zXrs7*f8gJ)3*mA%h^k-9DVc9nv z>er7^^|#YOW&yP`cUhE8JjAFApApb!e21+0lbde?4WVCP*86=f4pR9`vX^4`e&Wk_D@NR7D-dMEbm*ThKg>qxKq2vO?w^+eG8$Q|A=)gJI z^6~9n%t*K<;|D_hDIC!gK{&m<xB&`~99UcrH*~-Qdt=kMkLjHFNfV=a6zyn}S8T=3jY(<#V| z{*NCRjy`P*H+}ePX#b6FJ-gn;2OSEbfG~c7Shmlw@fb4UZHPZ_#kdTW(=r2YZ#a08 z!2!G%W8_Pc6v$5&ZjlhDwIrCI-%e>fTHT6wC8Om0%Xrd3%}!rXpT2{hNnC~vyt$kU zv(MJZlQNZ=i(u`We+EGF3%FF*PAR9%tSpUb`wKE6F7yxy6e4(c>c#tPYD00o?z4jGqaC?5egytbl0)wXoS{(NZ^ZV$Y)kNete0n4;R zRb{jc)aumz{pfMw!qjNkHw~T6j3&+j{10;Oovl-`3f$9`5!pMOlMOQn{P%Gwpq|UQ z$plTU(Prl2K?lM)2QcXvI-KLy@WEu>2fVY5=%hXO86Uy&t-W!MHQcb>UtC>sWIf4XUt|N^mLF!x}~yw&S@_N9ytF zsn#X-#Pd_+C2A434M|6+{tQ=vUzph_NB_N20vCU~X9wSX#_QTq%YmOi=cT44zI?omb}qW{XwjqaTC6pv_y+3h)N0PbU9^BGLL=Kd$Hr}o zU_wB8hTm<(tK|Zp4eiU@609rug~Iwa-hCUJWDhIP@^7_wVKknqjFXz!9k~3ct_sJa z2e0h2gXVL*17!9)B)SKl(D3d)Jm2R$pVN*`r=QuN8;Q5HL^h%))wUiLs1Z)tQz^ye zsQC(oQjV*5xPdIk)v2s(SpMiiT=q0MF)~TECM!E%TimWla2DI!Hd`|$8z;UKT5>a_wT9waAt zGq~XB0poAs@{veXXg|naX0)z2CzF}yWXgu%Ru@q{tw_CX5g*S_xOe6Y%4#B0lSL* zp2kUeh9QP=5@z(G3+pA$gwe9m3bGAz|9%fMS!@rIfG0NKDn|={%R}5Qb6DIKJpm1G z;4*=76I%X`83&p-cbP_|oXbhZrsdI|i zv@&VigsW3vPrruC9HKPgC|L_%%tp;9w_HUt%~u2vAr|;(3h;zaMHc=qgpvqr^Igwg zj0!ild5;a-f{TDQFgt3SJ$NN<#g%nIISKIPe+R$o=^WcU#*K0IZzq);Z6azwIj;CB zGIMd81Q%+*d)Kr)FSOOW`?j(*#xLPuWTPhpdG7SFNzi3xL!Ivdkx{yw+jv@I%doZ& z?**BMP~F7i76rJi;+_Td8=Ny)xQ%ON*bm=Pd3{4 ziDTfv6I1aJK@O!iHKq~ogftCdgo8jDqv)au-B|L z?H(7VNROsDR!q)(|`pQ(L$W*)Fnh z^Hho}L7x)Od;IM+ZUnF^ak;Cm61SE={bZ**`LvRAvqCZys(Uwz79r6Vjkp(-)<9xJ@ zZtngx1Vw(dsk1`pmI5x{1;$p;5ZW4FMgo6|H?vj-6MovJchoBqioVj?Mid^-Q6553s&R8|!zzyDaGcfUeqZ7lX+5rj3Ho-f}mh;L#=uT{mng>20la zh=qDny=(ur*KMNF)_Nzxf%;TbS80w*@wnqZc$uiP?2HHCbz+L5$f5Pz5-Uq91ZahR zg<%`fC4HRbE_9e93)ACmWvsMeGk1(KLIjP_SB$0YA!vK*8QSC!G&#Y{zqT~KA`%V) z%l==O8zcDtiOsR_2qv_RB(-aZLlx7f55|SaDH~%76rr~t+CCM90jjrgj~V^RhD6TR zN}*%bu2QB)Cy@>U!-uwUlu^1md^V**XEIKBe)}FgfUtmg$`v{aJ;7qPHEnur+SU~J z?8=_n>cHk<)1F;49o|*b>U>3EwyHoww_kgj^nm@ptg#DvXbkMz;KTB3+f9?*ZoAx8 zA8ov_0xq1QZPUY~Sd31C$v?^JHumA4P5_?S#*O@U69DwoB08S{h$De+V=u{KqcyWI ziVw^s{@`#Yuw$kwOfzkTf$nfQAKbJMh#F+H5~fx%wP;S!W-9(SGXPx65Dan`!2gHt ze^@sS{nx&~Kbc6lCI*hS;`&FYig>_3mUJ{Wl%TtA9q4M3x^ryISrs)l7c$zDDV5-wTfk7*xU&DRbVL&?ODyO0TDRiv$ zH4n~Jij76BYySsx6<=ss%X!-V-&hX>?Pd2b=PIP>dG5S@`+RcX!}3nLC_^Sk0aN$5 zAx5RsoOaocU5xvXQfePk5NR)?FbEz9y7B)bQSQ+x(5^)o1m1Qu@wPC<3{f2O0!a%_ z&)R26CO6v>(f>J%_y1?49&Ik9UDDY^5(@$ScWWk|Mlzej{C89i?hK^%e@^7V4@=~! zCZ>3hqq|Xu?e5P1IkR-E^NgT8mWSW)F+zOp6tk&2{TpK1{%#;7>WV@qG8{$g=IW zul}XQ{iojLiB(+u-za*MWVgFl#+8Tm5&xIVx0arv1@x}@=^roN_B3j!&inCSyKiDj zhRkVHdP?%_Q5f`{cj$(>Rt$mt*QtSoL9gAdBn77 z6URi#v$JqRA$wu5u&O95rC?P^v*+=`FbAbmL_&@>S!fggwL~EcW1>{_Cmw9ey`GGu z_Uo-qR`My3_te%Nk1F!T{ZiG!wu7@s$H-cPTDqm zLi{UJunR)AQ0(iRyH(skVV|y740ds{qS%C5gpq$tee5eY1)d9CHq~G+W1*!w5^8GG9<2h80j2cu6QuLQyW z*MnuEJfx1lhj~UC&Yo=aCi&F z_TzZlP^Ywp8i(iX+>qMlWM=2!{#79CZ)lN_Ys)x4ilk(yo{JJgOUy_m)*UV+aU==j zD<4~gcEh-tj(m`?Xi>gmk-*{9d*m)L&qql75LYQxU~m`OQHTt zF{NZ~FvbvRF@Rh1zZ12HPDb7+OhUH;uv=|J)5_-;%QKbo%r-s2s*9zJ$yaIbuOseT z;z#pM>Pg-UA521OsbMfZpsgQ*I{H8EXYgc2@u)Ub+PB?1ursNUn%6hlcp(qx*n5Lv9JifVHa)Ys@9Y%dpORccLTQ2KANe7H6Y+(q-cq zFU~Af2u!UKvl3Bxwx>uLBOm1Ie4O%Nh!0E}@~U5jnVxO0ieHL_5lb|LA3J)M;oBJn7`sNhzpK{xmJUvLS}`a(J)HUJf5T@v33x&e#}XT z+X$|LVPofD(wegvYulF3`P00uer(2sn-aJ|P}QNs4~qX4pgQyZkz0y@_{c=yVLsjj@MM-uTGPc41EDA`N6#?lh%Yzs>T? zA*^;=Ph%GKOanj9xWtQ>!P&z7ltVIzs@)dA)||z|23Yo%5N|x74r6#vL^j&N@q-w{ zCuT#$du)>knKa4Z^(y~3ly1flgicaauuv_$?=m~ZA8J9T4sgqk`b z)tm==7G~xYC@f%OUX7#yulZY>gznDB2n>x9QhkK9d5m;_?_z-XxV~mDx&(n!me@O@ zkRgP&EX!cr?iAW-<2G%vS|LOX8*`_yqInq7L|nmFYcXjgw00XFb|^GdQHZ17_UHr6 zX-E8p0_pk#dJF(_{Zkg?Xikh^)-vKrJ)zOLeN4qvB_FosRt%oRQ?HORrgQ@q=U&Qz*Asy-5TYPb6B5|e>n|}zAh~9;{^Zf{aot)0&9bHJ{SU%aRGk{eS z@U(!x2S|=i;)@>;6;XeLXYx51wf10!na_fU0u6H%{4IE9G5;(aui)Lu?Z0m`P_mKjPBm zU5LJAWrA?Dox~s$9y^WT64`eRxiGQ|>K{vZIO@ws zAvJu*pz>^|3mbS~6rTL@{6hX713}UJW~d*_+mg!_d}b#+B!wf(F+e_|5BN0^A z7-HLnx|NU@hwz~cJmMMWPZHPgyUc|0X#7WxlCp(4s!VMeT>56K7lxNEuHkPQ&Ckdc zhaF8jf_+z93=jo%&vr2!9@oKt&(%6_^Pc>COQZIAozZ#+Svx#_l@ZA#*_q-0oL zegLm4#zR41<9>dXrB}(yFAP8zcFpG=jKp8?7|>lXF8mDre}$cSKoiIQz~3Yx$wET7 zB!D83UD5`tpZA0ZN2cM9@O{U4YjntzW4iMVKXy3Gdr{Uo$q&czMmN;ObU)2lQ3q=_)&2B z%d$SOmn)yuZ3Tggwa}rP@`u_U0>1 zA9aS-^ztC;2jv6A6m^Ws zKS?rPyAIH&zLsj|rTy;1XSWOlpFmB((s^j~{MFw)ECU%i6_4HVp~5bWgyIbRGdk#i z-D?vtS_x!PxtcB5tR(1hm5GvT@uKpfT}~!{zI-4I$t)kN|7=dXOcttn{xy6H1dyXF z_tpxYF)_{H<*)-@VI#+ zzi(@Xj1xzlXkKo~)&MSTmlKf$v$33rD5&?2+FcX!VlMuQ$3r|G(U^;mi)OOX{y~Tz zc=F;kIrpSb5E-eVv72lKp>)I9V;v*mR;P6f)sMF!^K0s5>pq5-PqP&{Q}H_667g11 zi5GjziV_?A8gOaK2O4V#-4JiPB%*75ZLjMf+}Ac4T6*e5^*X{r6~Z>p8l)hjo|; z7JFIGKo5+fqtb0(sp;cUHr&X2rNnm30ZwYHQV5pVX46rQwmKE8?2T1$_p$kksZWB< zQ%vW-YrBs|Yj3Lyy|dbe%$tqascJUowiqhgb45Vr~%$vHXOgq}G2 zyIsy^TB5M@45ank;Q0Ex5VjU8KeH#Z>E zo3xOk;a;QxTHEeA3#K`j@8eBAMvzGtit+dItCB9uIR)cIiiFzA*-$KW5GQX}lL{|3 z7n|oHS2W*?tewqY%0QjADw0dYs!tOOc-Nm`$M(Jq7h&=uM|5ml3`2t10>r*9=lB+U zS;`j6vH82-F_tLh+<*2WbETD7$D$y14fc&I=P}TmysZ>&YB=Po41wIqqiTZ2H#Q<# z$1$kCw1lm6?~-vRlMvV8Y?{>TvJ5dXeQpYyp=30(_e>lHoGGQWJxd zP`CMf{Z#^^lKZruH<>7bU2Ws~aE9~!NldUnS9GFFEax+icYzPv&+D)wxKPXOEofG5e4)nM9rhWG5{Uf~)q?9` zP3{6kLCSIubtJAUsk6c82tyY1Q*t-4mfsVu8FSb{IO_u)5fg4-vySu-aj!qYI}o!) zc&9zNEm(SnBRdJxuVD9K5W_9Tc^otn`+?DwwP8pDBpr;BuLZVBOA2bk4LcqWwf)tQ-^N;XR(74ePu+NH=U`#V;`N)d_J%`&oS#aJf6Pq zm__pOAe>{ChC!`SM;IQ>(4_eT}lq!Y-KT}U|Ib$A7 zqrFW(srW1vu(8G52RPFK2bvIMau=}$4|}0hUVq6PM?V>0y6OONe$`U;^(#)imiv=A zl2yec(+G0z?Z;8|T$L-dtX=IuJ`@=<`^TBWq4;<;8pk0f30*YQv<5MEf2tK=ts>~S;ih;G929DN z=*~pbUN@Ms*fJWNN1FN-I<D1;pl> zW3si97ThW`D&78N-EazIKO_n6Y-Avdc;MaNz@ z4VUw$GALNn=>(+}HCi^lPK~mo_(pXgZNF!FA89&ix0EnIZk_?BcGWo0)(+DM@t*_z zY4KyzI@~Ykc&!{NiY?JFXN}2`X1JTf=Gar__IX1N`^4rb+L~iNA?lWrxBKX=rRGND z3UytsgnhTGLa2DP`M4`vt|tiUNO-r}jXnLX6g7q7ZDuF7mu>=1K*!{pE8O7DC*~k{ zoNiXI8k-Xmg6i;TK*3-z%jkri=F@wis;E*!qsGXN=O)1vsZv+d{6P9&SS#I4`Em6-yeoyPuq_ z=dR)~IDNM;*bn2W$hjd5kS{1~ESIJ!4E+#Spv!fMTw02im1veSd*s5Z!S za?-w;)!}g71B!DGJ8?z71QJB_#a?EJl5X_jj-6w7#CW5$`sFScAQ6Ck)#r|&zy0IO z5_+he(~AEt-VeWKco0{%)D%p{!i{z=kbZFww;*tc7ZB#3w;;KG`Ck3 z>mZ=x0gLpezdfjYTMLKk4Q`b4Em27MQ~V&%Zjiyp?S|!$(28f?7YzgXupMx?)er$2 z&l#j}+=}qz`Lzc0!arMYc&A%JjE;dB=M2N?TC1T6U0m)M6;qg;LJ-D=U5KAJxn20yeI7Q?BFhVS5|R>Mw+YsKQ(_jyc|WXkpPGj1Nqwh0dg3=N}B5K_k~Utx?m>nr~B9!i|~ObNqWH4CH8;tT^gN zOTX#tuTV}wOip&@Z2Lb5vUSd7UkDvU+}O;I#E2uv$vfjfla6&Zkw2%Tn9}BGS9AGS z(~EnnN<{ATgTNx=5W2q17%8PGMaEJIOxIYE(9m7~k^)m<96{gQWYjtozHdaBc&SlF zQ90^I{`iRs5F=uFt>*=Lz-TlOmREhoKyFb_DO=!+_Hbcmn4C@85Q@y>_E23 z!V^c8bdL1aEB?^&4ug*BiC-WYCFzUdG&cT=!B6Rv)os>ZQ2F4NlKSo`Df1R^;IuaE z;LT)i7;gQ50v{z@Uz!|qzcbJ-W$c27qFnmChy4wQ?2A}AY^lC59wqx3> zdEZApq2EV!zPZkBPUWHCq*c2=-K4i8+M%e?=teKtjA#|zvKeI%W-@wFTfH$r3>fMo z{PxM|;B5fOu&VD<5Yt z1-#r~j7zXjcnKts2zzCg+P}wl)nQ4RCVF1>{In55=FwroIbXHkgM~7>!h_j3-=3&C zwKfjW$!`XZTUB5pgud%j58^ zJA%}5egLDZzB9HF8r^8@AaK)Wl*9V(jN730f)Rilg-+OfkMMc8(}r5(JsBNqGFHg> zesHE=aK^DBwhlKZP|%vShG8!DXJKakuNNl4fauFg_%-r!6u>_#pQFVSDj78m9auS% z0RENIr{gO>A@rk&%2(7-n^xHuz7MaQ3fU2rT3YaGWu*^facJU{hgXKs+i8`oiq`(K z@}`Jt0}knAoHRyD-c@uNdIe~n53`Fe{xpc)`)ClFX)Or8ceI1=Pgi=9X%E;OjP|}D5i}6Yj#3u6id6w(4!jWQ50<7$jpY{-eIKw-huj{ToW)qEoa#R zN4WidihCb^T>~ynei;`7k4}E+#rPq~P8l--f$aS96Gv#R@$MNLla-wnl9rjX zY-Pyri%a=M5GYQ<9MfOT5+Dj1J|r2}IxOVrh|ktl@S*I55?9(7pSRWg5j2hDTS1YFG--o%&6$H!%ROp+&jUz(YLLP2cgH6P>gtm&^X#*b}ImEtVTs?0&yWI-y-h3{5cK9lL_!_U>)4HeKkGEUGM&)_1yEer$E zzsX%7Wio@_+3(<=m6I7)2!HPYL)l02(IW78B6nrKu{sh3AZyzVxF>QoYEv5-{Kor9 zWuqEYNeDIx8Nx8su~Xh8W_NClAVKuXyNrxb)q3U@fkc80khG0a&=p&lr}mqMr?QoD z==CnMQ@AC-TVg1txuxxu=DX>G{Wn`@w~5++P@c^ASHv*46wyEa@sF|3PkR184{9qp delta 378798 zcmZsE1zgq17cbZ4a%l!6@1?ujRzyrJz%B$8yRcgjyMYl0Lxf58JwT-<*YtFFDdMF^g=K7KKb5;Nwo8KU zr5_)!X7l>1JpX_aw!6P7kUUh14v1f$k0@kQl2pOGLp+e^I8o<(C8j`Xd*bS*?C}6q053TLopSVod$VQ(RJC|XO=z?D`ijHMDoN$b zOaAynN5^O5KbP3UBvl|UISReHY+tz-OYGUPM3tc>vSI{XQJjdQvKIVgec!y5V zVL&H+J66_DmW%+IZe2X&E;~Fx<;2@)fZgNtyce>wB>P(nYhG-D0}Rc^eEp1Y3D z&NEH=GM7FoKQ4=yKB@>_^%;ivC#P8>b|+EQP&5WMK7TA|z_JtN+@3&*`J+az%%-oZ zF>mt{dNrssNss09kqR(`Hp}<4)38;2RgJ80It!uX)#p?1)&t@{9?ZF~%H07C?KKo( z6T}}Uhqu%=al$6nta6yWF*yreunppmfy-X8p@~xa>tTLLuRfd5N`(WB{KJrQ)C`)9 zdDOZe7G~Tt_5Da#r zS!*v&F@#gxC*_Oyt8tk-JyFAzT-6l>5Ra~`+)I}^grY6b^A5E*Dje%^!L(I@qhGJ{ zg2p=tGpq!on_S#^5WUkgjJG%mLvEOKcrBfs;Ae}huK>rs{d}^sR?=W^IxM(@+MS$& zrq}{;d?bsfIlTl88z4HtI_Vni*;|aV9{uIn;U?6&r|{_5padP3+(E4&RbWpz7sSp#R}G^d69T!R zO#`BVgHGJicCn%^y)0R(UA8VcAXR}lC!y{^Iy6!6{uV?ww@t)8YSp_wXXG64Zu7m^ z4_LKf7p=3c$Y@{<$3s+y+`CBC@sT6|f;JW+j{TT9i>CK%#QVE~Ko$G{T0^__s>LTV z0tgxyd*0V_<$@D=+g|NLQ+w+276(AWs@G#TYg<@i3zuQklFYLaqafaJ*iUG9Ofx>p z17O=@pTc#A0@&^p(*X4C$5!bVrv37cpNYr(GtW8G*UwH+%p zRvVJeQXYs6OQ-Fjtu;c^9f3x%#laYQ%T9#4Yhc$;;(r~Z5A3bjX`)t>SHL^U5;6B> z>NombBP^{Guw3`s)Kzqdy_lsn$a1UtMFEaW^E9TM%PL?y(!$M_uD2Ic-vo5_{`4D0 zUDU!JqfK>mx@XVc2tx|1e+Dglj0f!Gbato(o#DXPgjQ!>L!leFBbAQ$@yZIYOO04z z>_J(}oZoDqLkxtFDxt-XfPQc3A$?KM5?X}q7_g9f8wk1P!0(#g@UK90s|px&i@w$u(-`HZqcgww*&>=}AZFiHt)nyZ27f?0 zh-;gAc+i4tHca26si`G~_5vwV#KEJQ_hvVnDC%-)?Fa5OdZ9_ou&FG04HLL&|6&MR z4(#wYeik}9`TLgIu&gEuG3%SqCULIM2X;0}A*?3|R57PcOl_u)Quy=5EILZjgm=$| z#t%XYB#&$hIpt2epnDJFo}W=%m)`XjCtZ*>uPPOk60 ziN<$r&LiT6uF`Tq(HA?tO`|SdZRpMpcDywj{@TAi9@F_f+VX-^Fv0E#dwcQq#w6#^{H-LwM=ZCQhuOe<0fvqfnm z{_Rlu7tQa4#B1{Acl~vAjy-F-oksSsp%L8(%Ws=$LGDNuAh!SPKZeG25JNh`kQ*x3 zcA`}=;hdMi*oLG9xCst`IN*8N7n;&txZJ+(LZ}3$rRzMyhkAAMBe(KIYs7a=JNePc zv5}mWzhSU(UyS~xM>}d*Y74b7=>bAR!iYt#wn`e(MZ>yBXPS}LKoM&Yn~rYY7qntS zQ#x63LWiKR#K>W%`?PebCMu=N2IR? zG)6)!x20OGYAAT8zMVuEw}qkBra#RF?(A7nE43+cfD#-Au}$Fc(R_BtyO_|C9rZc? zlRLW8{Lbc_)1E-i^<|@apjMGJc83vPq&E!(3lI^{63Ey`-FpwriMWO>&P}^vg>;#J zOSL)aDY-@bd)%?smh*^uYD%<=rAKS|Nr?$^;l(ThMAc(WiP;CuS_jzj$trc{L9XimKf>s zG2X)px952DzqG`-IWMS!Rb%`r+cbLIq%|*iX{@8;-J#PQ`qVI*7sSAdQ#NB_6tES{ zOlyF+@5&Vi@#XD{52%ZYaP1_MdMu%anvmnL&BCc7=B-RWLwDR%v%Htg#@=SKs6iZF z)wxou1UFCuYx0q~k+V{ni1D>+S-vnXn8M zbXl!brBZu6VLRppHrifP0LN!$XiU%%fgE#wG%;)D#TF9;znJ6?QM z_7igY3C+7KS{_0_ocASN&eY&TA~yLtqB*b{%$1*f1(aVxIA0UJ1v$j8HGYLq@5`>F zD`fD`X*xRl>PP;duddtCl&d!EUSx(T4{U#dg+Uh@f3+2lW6eRl zhpA1JRwcFQj1n(a*d)W8%#^l_Xcn~i6y1GQtVfq1@pTM)bRVd<;A&rqqP(%NGt6Er zWwpQ#Htm==g6=*qa+zJw<-og*O}TvDL}d_rPpLJ;1B$d|S_b?uKx7PHegv~ToE>7m zh3Q3l;ELF{?KOk2_pa&&4ZI-MwcQ}j?vHgIu%d8t z!itTqtq=)MJ6Laqo!XJgb~T3LZ;cfq1Q2i_JIm7AETgte8;?WDrkZQj*idXycS6^t z+poE5d2j$8vPNY)klE4;5l0Q&Q_h;y1=_tL6ymI@8}u6zTa?C5)K|FJMvv`392Y{| zHKH65dwotJ?0GGPAIX=b5D)e4_LlwKNFm&{BT)HnP!!1~g)79))EnCLn%9pp^9Y5A z#d=Uuaculv*0`2JgzF_hy{a@t7u#5|dY{4i@Kgy0M!a-(TLg26l-aa7l)QV_wJQq2 ziX}Hxh*hEmj6A*9{n5;<9uyxA*SL`)NdvL3rTZ+jk6NT9Xb&kPhU=Z^&x)~w-Y=#m z89)Q85bG^%JDxpg09EQRjScB5s}MI$zx;t|8Y+TG0&JSG1LBKEx9_rTwG<*>GKERj z?lr3=`%y>Xz=D<8Hl)2|2XUOoeUc<8BL4lSf0+>D)<}h#^p{nL zX0>zI3Nh|zq_81MSgBE9h*!Q$y}~q&6k!B&4=hDA9RIT;n;#+V=`GCY^oC2GY-K}* z*tBVYr!jd=HnOVv3K4Dagk_$NeJs1xP@2dYpc6*dItdBi3e=dZ!iCUSd;^8p>lgxa zqf_cxu^vq%<(*KnYTk^uLI~{}E5!aM4T_s5Z5x5bVw+e21D1ao-iDdhmt7A*$<{Wt zmb1zAB@1c5c>L=2J}kPv-19{N9sfaFuM25R@&%*9qYRukVvljpHlhqg64Vm9f0?q_ z3iTxNlP1u82pez`y~c_iYoMq}zQLM=-4PpDEssIUB13|uL}%6b=;7$hLP*KbeV0dk zhL{}a!kDErQW)5IK`=!ch_7F!_tvU9ke_guB3hLwBf755a40rktSS>WbLCn|I6X!OKNMfOhnftL}i1FGf=dMoG4&%)Q z@urj!yFX>Bg_vx#w2iij4{!3aoS74h&^S-T!X9%OjN{G;Gvd#{tZ*C@VPVlJt(CBnK?J%AAFyuKiU?tC4m|Z;?2M}jIxVJ;w zt_^Qj@RS*|*Qr!P^Sc=nT`3{N2BY8T)A)OdeDtDwgZN;$SuE`Ewwabll$MAuSq3u0 zIUznyUV4LmyW53xJQ@bRo=Lo5Qy~nZ;-cD>Fc2U%M~n{pUIv>2kwTS&GEzqkuSK^c zx{~>@L%~*v&tLA0q4yGnp?U(*20hlbpq72a+0u2eZns%A2UB7#=nRH6)3TArC_3Fn zq&xEz8AXyxHbGi)tcdjr@Pl{*R65%b5q=ufX$i_p{&a+%e` z>fNHjmSXMu2twWFF{%f!Zc8s)+L3UXULw|?H}Dtm;>g|pl9x_B>)r3a683YsL~!Wf+nk($)}%Z;0}zt!#zFUV?poUFN+IX!wv>u7X>{*lQ17 z(@&Oue1;U{aXVt5-hVS}Qqz(p=)(*RqzVz;hj>|21Djypr>qrZ@V%_7Ex!(JQqz$w zxz6m#DH)6q7YrWwnySqkaSQ8V9?UA0Y8$%%0U~c0wyKkgzEd=#s2uKxka+lM(HN|P!4$#Ow zANxmKSJMpP#K)(Dma5$>MLol2=VvW~& zt?BMiVIhBlKaStr;{u)L0@2o8ZNko`WLlFAFad0jXxR7ZH@Z7maF+mcuiLxte%dv- zJ?FnGu$ykusS7>nC<&y_&bB0@;UEwRAWl-%n@JzKiFm66vU)dYiy3tZ)v$!*Ono-8 zHXP=JO9m06OfTnR_41j(Nwlm$tlc@^f#lnYf1;ZiUY&NUT}|4`fmeT?jicJxt4HcGSgo0h}di0_ZC3Fo6X73wkC^VmdHKg zKZSz~fqUN3gG`3Oum*8s$-&(;zLjSAnrt6(46aJC0&#P*h|Tn*t5}9|q2>F6_d4`S zEu4`Biyh~o&-YaChKMeR%c{!aXmQi}q_mmX1taz}deRLvrD69Y)%K(l_zRAJ*w%80 z16}PVqKyOSu(EZU4gD4+{BH%sjyFflYM~HmqO&;i%!h8@hMN8hQh~V)$~I?ZiP`of zzlETRn9}gzDQf4@k4y0r2z+Gz%VTt;&tP6)2g3~hm~KT^wc!MuShBs^Ox09KgnsZI z$(xOVW@pz0CDI=)|7&JMode8xwFkIoYIw|HN&*vjK{%MV@1re^>7v%M{bEP8K8w*n z9N17>Fo*c;+^aqGM6_&E;GlLQ?|~Ld1o2DouCsJWq^wTdz;s!1LM9;*vJK+$)QcVI zFVAE??s?eh>3-Ti4~)W}l_X_5lkGA%BCb2@)0Lj|P2^4OfyMf{+v?Cefx~zhx&*SU ze}2vxZ3O8+Gd$dAy1xzE>8iG&vHtqJUmFh{oy44t&1rq_-n`#tu&00vtt+(sddhxc z8MzHqkEOGIG%hHSH~$Pg>$UQY)i&qDutXPiXl9^Di9CT|lEc4tba$)YXZ~Z7o*nUV z6w*PwJ8CNB6Ac~-6W!q|Y7p7j@T;_)?;y_beTd{`uAWzDfL|XTJ2U)hvDJ2JXVrF* zrqM9ZUc4gHvk&hv*%_|m->f|hwx?l@=EG&0jr1MFmgo0`aHp&6qi4t>{nQ3*S8lci zi(H;*ta=Vs3fiOJ>LzfK@%6g!S*JnA4ZR8`XlLDm?yl>>yq9OXlipyHsBpv|$G%Oa zfpubd-_$xiIF{Cl=WI=Y21%3V9-$3AHMFw1*lCXk!e73o>d^8Qy?Cn;Fsb)_^x(wX z9a~wm_Vv}4w4{ZQ?Jfu-mv3Cw2TvBYTjH}VXk{a2dTP{Z;%X8Mt}vLj;WVSSH*$BP^#9twV(O4~vE zyNR^M5F+^v)B9;OJ&X^k&sLAmG$I$Idmx5*4Xn+zWfleN#)&3sPn8QqcNm#=Z!a>g zzu?cUc0_f7P^DoH(z2aMl#~Txepj`Ivu@Ba(~Ufr%0e_U?AlNp@s(`rgluziMvzWI ze8!3|(fLiqj&mz$#jUiW9|lZTl$+^DQ^SNtLSX(jbKxRxcQCGPN>+I}L&HPqVaWwz z?_KraUKpaL*68%9NvLqhj$q&Z^S(Ak0{>OB*o7@j=_=V~53p-}$EhnAg)3VU2{(lk zq}mY29Cg3Rr&yknt;g!wg7WH19U!(G*nTD-dl$>LR&^B;py{>U8EDf%^;(+z?kIP* zYGS6fDn$m*@@DRoG}5O*4aJ%^5KcFD$EKOUYG=>Nm%>o(L)03(K5{6;ibw6fYh5IW zzKyVE_tG=%$x7*dh&6BPzM>VaH9%UI?V6JrO7cJeXi12Lkz2dr^2O2@XZjFFd6bTL zdv4pCXq(B4GR+uSoM}p(8w(9A^?>cuu6Z+1H$auJ(xsWEWCNs3NEOlI$b^PMbBnVb z$$DvCh+8~5yaUH@VrAhVwf$24hzEB}_eY^}J{yHWWLHayh%KrPMuWw-<_`X1ysFEWJF-06mJyn1M~mEb36nV= z;^VZk8|XBg*H(e>$YG2$S;R>fV$HZs0s(isB&kBgqlXU_X|-INYdIw=+lmEj_A+GY zv$J(oodp>>J)$=k%pE&+gc0sC!RX&12dtGlRtwmh{Se0xIlLA+W`KJTksz)ubap>3$l$S=Myy~`wjJ3drHR=7yyrX~x_EWq zsS*VSulgyy@KpL>7_KY|f(UT?AgnfTKDLBNtY2Fuj zo|s=#ZO;5BLK5sC4FGZe#%CjV?wYtc)08#Zlxb=AL%JMdR!O^$T0OU*F41<>sg*fP z42jh&Uk@wC-_lzU6RoWOgk-5J7nlZemBVe$ctZlvlNWr17H(D-hJxRB<^}%XLXX-U z84J0SSQ{&##V_lFHzAK}$6Mf&nWvjrX9xyj$8ioGqpVZBxrnPL%ioY~z<$t#E zISmlGMG~T0z^$dQobqAolX@}?AZB|6Z{w-51f@B}WnD{5S+hGur9scKPDX4v= z4b5&Vj$-gJ%)P{EA)o}YuZx0$_pN>$0MlyD6OWGI7y*rD_0;OYhwg4>$)?wVO;Nh7 z+Q=?b?r9JQomA}7w)3WnFdMdgENDDQ$^fx@*o`}xA>zjFA0S;>zRrke^W06!S7k%0 z5hB9sU6{obpNa+GR?aNd3qsY_GeVe%y0f1j$y%Zi8!)`KUsB%mDoYGgSW)uHlB;kW zxXII{kB`#Ar{XA}IV_cF>`Yze5~>jM#~sVek?=~?Tmc>PetGkb4`4+)ckuE*wETq? zHT$k&2XEzQ$R_BGszmflOZ8?hHK5OtA7+`~#7oV|;7pUhHVt79eW0TFr;3(*6W8Fj zF!LF+_83&xu;RNpN*42tT9GK=63HSujGl9sHu)}gFgKvnr-HH>)a8*C?fJ`)72M0Q zB3Gm^5pQh#+LI**z+gsSO=!VaXU_c(Af!L3>Zf)v53WbtsD$Sa4bkeygU0-_X0bo0 z1tHR55o1n}hxFAC5oe;|q+#UESIubsufhjz0TG?c&&{=@Rbn2gm1-*zEmu**`PMZ| zCEISCCtHy7+CZbJD0wlNBfn@(G7g*o=Z(sCAk1J6KW-K(*Ke z@lM8|x16leS3%YgRN-(ibc$4zEAgl!S|i45a{rVB#f_9BkodW9M2c3~Dw_XY9BZb+ zyavpyQwp-T7gI93lVd>~rC<=_qMNL)o;D5oAry-bPs0BhT$imefO$21EFMKFV73E$ zU5aH*yr8t?Uva|{4H4~L#`(@*j#g}>LZQzp`sJ9C$0GenLiFiwSIJ4SHwyW{(ipV) zYDw-cn*7O%EeKKAaCy#wsH?lA>NGHHMK6C8_O}oy^qjV53-um|S(I0iX8$FooE7p8;OWbVAZ;+cG;g z{XJ}J!$AkAXvC7-1&`^-$9Bx*89ZnxUn^=5{~lX&7QI?!Mg2dDw;88_d^c74U&6AE zKQ>^iufcxB`GE)`1u)Lnl`bQ&5A%Hu4{;`}64Ve!Tg|J2aje+cRq*Waygc7Qe4Mv` z9@TpyH0KVEtr&Q<1I$=#nx4R||C&~h{{*FoyE0G6hNea8#n59<+{s0`gduKw)v*oC zQJih!V?y-2l1F<80g9G^ZbQqIW*@aeHNH9o}gPhyA?aN(~@)@~M|`}ikgzI8bt zA*dqGT;8oaxBj16>pu&}({p!0YMk>(PRC1O|{_#G5q? z27#u1HL;?sFJS43!`1J@;ebkqjk=|-OMJnguovRQ@)IAppIj=lARaqJ1>!#IR!y{i zEarjN&&REchtt;ox)JlPqAB7m@1;}e)Q{o{ChnjVmL53gOvBFc0JIf8WAj z!$w$0@^~s0dgZ`Btg(|Kjx%!%#8YQorw?q68IX@Zn`6#WpHh38{6v>DlmQ-5kydp} zu&}eHyxlti=KtyRyv?}M+cDq$)Q4>J7NS5bzV^Kn21|Hcav{f+43bGR;`v_v<_TiE zOcf@q+zIX#k4gm~K3mo#gN67&*Y*c<3|K>j#)G_@R@!nPdhgJ86__xr4o=Vo?7%3GfWF3NEv4Wt+m2j1&Q1xKF7AmKYQWFuZ5Rp$aq zIFcx2DdMa%R`*bfc5Jn`!jQ#0qQ1mQ$_ue417xDGb%B!MliJPJ(D|*pcO_O7E$q*@F zMEC2BD!3i4G64a{TETt&Y%nA=Q^cMIXMF{CKab>ik(;t7$1f&(1$AzjzI&)YX(=Uz zSi1OAPgddw6WhE$Cx}%NX>c#Wv`$36tjU7Bq3)22CV=bH{7rDcft5Ab0~4(hOH3i)=s>cCVnU2`v_64WA(H;0O&a7wD6Fq@Z69P|89uYwZ@yf_a7myio(d-3M(|@vRwD7f;_h=}wlMEs5 zHXI*^Hp*>Wm+dH|p5(i%M~wGu`Bc<9>M4B5L8&yvnO-47g+B%;VQ{eEOT#A44&Tr$K}&KZ#DN5%AyLZ;v%dhF;f>P9dX zLW+pR#RXQ(*$<*-se#6WC0k1)o&rX(vGmDdG1~AWIbq~)8Ql@rS0%^dl2M( zGh`KF_Tl5HXk6krr4MLve&<2Q*iL<*Q|=GJ1Ae&U{y)F$^V@spFBT;2THNnA!^}$0 zrM(f#zZ|IWB0c2H5Esn8azaq#UhnUy@nl85QY!nvFyb36a}{Ahsnmp!WO$;5!bBWx zcOmLG<8M_&y$Qai!+OLRTG~MP?h>_pX>=8)73vXNEVy~4);KO#D@?dlpMX?dV`evG ztDP0%G^#Zy)X8Q4U?HC9H(-VM?f}UnK3S{?5h_^XFCUI91sY$=3+f9MG}M5s^CUxv zYxj8`L1G%VXdex>bCt42w5exbu3h?@vL)UMCzkh+y3xwdy5uxa{?QbyE_pdW=496vz>%az0s188X*?B&QBY=xDq3#bamL9|)h zT_t*fA&cX)PSC^m`<^NhDS6EJu{Ott_)Ch2_ZCH76Ye#^RO3m;N)Jbz{k(S#p{><( za{S2xDHp`2m%+S69$*GKZYQ}%%*}nf2`$&2^&%R0#VO^FIHc}Uxe{{InYth+$n2i4 zm;$0_+#nWWsc>ecYhiLnWz<5nzL`7*z1@zPx@x@1bg*okH^&Fvri;)KZwR5InG^}) z*tSJ;QS@TZ?FLd$ql*U#X$-hV0~q;3+HDOW*s6P0kr>0aO6^T%%jqI^ni;eS9bFu8 z-UHH}(e@WbWAH0IX1X01o+PJ==v}MtdZCSoe`z4;EmIOiuTq@`BHMxWO^@|HOYO;} zCSpQ}is05Oc`mlYQ|4mNA&VH5I?ob~RHS-;VT2m{Y-siJtIv)t0?m#F2SC9fdOhmu z%3c^N>Tzc|3QTQ1<=;x^TDyMevT`epBdI0zhxjs}Wtq_Wn_p^wf_n|5h!}qQ(|*za zgDcnyk%J*V40!fh$b+jk)>7`eEkIVs^+Q#n?sH90-V&)i#L@-sRiX+O8LAo-C!>i7wp};R0w^m z9$4i#IV(i#31!RL^!2F*K8*j{UAl8yU z#5r{bS&6<}8bNa*>TZ$djQHl-785kX7NoZkzUoZuUzc*537S{70B;fuUTQ zuY%ON|3N-r&=v=*dqBjqmrTvX0X2+#QG1cYP=rcDJhi$*p@{IDm(>e%;PJ8K6>)p` zyuQL;3toc}zmi=Mn>{{1M~E4cZ=szxQ2b+B-(kN|%-cf!h?_jUMXXn0?1hFYo^ULL z%pfn_?5fCxw!WwCWUm|p@n<)K_ClUJ?@|w<2Wua4j%elorDOHlB_d}jFl=ixGguVQ zGSK*uLaBVj20L4w=dRP-LgQ^FjoJ$^ZAX;>KdoZkZ-IeIIe)}4Yqq@+x*AEOo?n8V zf2NuA{w;1oo~Fwp{sIooh4km@;Bza^pB@I2aq=oP}&;lav->=!oMF(Tv5Fz5+yB$JHqpch+oy zr^bTJg+nf+g}ALpb3e8_RN+cm4;Q6~8)|QV5ADSs@)?{pFV-I$BhGwcUJ;h~FP!XL zliq=Np?1Ti)z!4=8*y0l0w&+L&v0vTkQe{nlJ(A{CInw~;P8lXvyM87{q^Ds!jhN3 zDP>#lnef?(xb-}vCeNY{suCGo@;wPqyEA*Lja*m2tz8A-e zC*jf0=Y1Ea3YJ~@!SOBNG_u8CX4<47jLxWVWhGD5mSl&V45G=WV<)vNbE;M(D?o@9 z@$HfQYTEX-c#j?k?f*DrvrpSz9KzZ{sm1ArZMCI@-I)W*`5^~EG`t;t7VQXTTxpy6 z#)2;qYM9c`_#X4n9Z?jPY;guP=f_BsWnaXvO*;htN4jDmkp3w}jyRy+gxYuvhy4>D z;N+y%5pSKaivUg4CwFBJMAeA3`uxCY)q8OoeIG`#96PfPJz7zV6v%rK#9xnlK7~Rb z8vL4YmK(xBU}ycw_dzXO`*0LIkD95R1a-QwQtZc&VCz2crcziCS{Ex%r-r1ZGy=rA z4?phE8mu)d9G7Fjr|vB|MNGKx?u9y5n}hz5wx(Z_XY^hY;R zPliXtpNAg~6&~dGk2`7QE1DyIncE{=XehGWfrQK4196*Y%SYVM{r;)R8uiN2C$r$x z3SAb_ron}Lp?s`%96_zg7H3h7n6UoCL)qDokx|sZR?BOwoHF8rdUKdN`4ByHB2F*VK}VGrwb0YrgtAZkexoFDPsTOZcBnnU@gt%-t{#ZyXPZwgrTmM^l91T)8V!MJB`eZ|M!4KlgmD>!ML$FNY zHbW9Vu|vC&c*j6 ztmkaCx!o?{4QV2tZ+R_R8{ccwCYg?`$c1W1s@zo}&L4lYn3nWM0%8$<1hP1rG{cB4 zNw&_+6lvCJP{63+kGhI7xX+ja$I4x0utFRVdi@D?O17pXLp-A14t8~SQQ#z6yuq5j znFN9GO(y(?0xT1GL$t5R_ogGKThqnsRm>!bTB#EDuEfJq{Ahy&VfY(+;Mx2A!Ejc7@q0J2_66>)Fb+}ZTxCSJ+% z0;wKL@2Q60W?^kzuYaymVA)vL^K>b>p0zYMzlx`1Ff``<0DqN zE!;%g_iI7i<+zBJTi89ibn^cY)n_BRsP)NiX-J5BvbxmQ^3Lo$asp`V5Ro-3g8cHD z(kqWH-D5+81{*Rz-yAhDa~6Cf-UwY*p9YT-Llkv}JHU02)ZwfUJ2V+ySUvHQz#PIV zhpJRGxxb3|O6C!7E%hm><`bGh4CpTy(8EBs@WUorF;@)nqANT(`~7(BnqGQ2jRczs z99)wnbcM`ns&pR24j00wpbes0SVUv6hIi5k5r^8)FV#Yaadnx0FSWhhEGc!w%^5{j zT8D_BE`x0uw9{ur{y8>`j8^IKCAOQSiKsKLMI$LLZ=N=3fJ&D4kLq6?Hs(~o3VaF9 z4n>7H;c7t!ojSmUZG&M*r4%A!yLJ;Tp+=lj;tk}C*xQt*4-=EJ4~J80{P6@5LX6Am z7gRlE(ghxqrGbNDE#l7Z?dsFSA!3V$H(NK@okrAQKt~>t`htsCb!zs#THH&!sokiv zRK^4dALYu^uYVUA7X_r<^{Fn+A1v-Gqk)TmSmFy>Ec^jQ#zkvO69*WRKnQ!t4r0RE z6*C~1h%6@;qRWG}0Xo!iyqFvB*Pti-JV#$zHKO0=#)EhO3OXzT&`5~TIm)Up^x;Tr z_I0M(mZqi)^VtvggJZ0hl~L<-u`#XzlJ0#w5)2x=qH>S$a%uvn#a=NgF17Rm@e|O( z0ufVgL)y0da6fBqW2SpV($pAc*yfk#H|~#R1uE9wo5J@A%Ib)(k8GB!Eu#6(!+AWW zVY6;-u;?Yia5#U&0Ub=TtBFK@=pa1>!A&8syj|f6pY@6+Zc}OC;74f$d_Q345w(<~zc{#P6?U&#o`%2eP%H4+`K> zr8ia4;@uA1H1G>$!}etDrn?~mixI_^wj6fM*W2EoNW1SACb|Yj*^-trvwGGriXJOk z3$BST25{<#aV=->;ei?_2SYiKdUBaU+;Yom3b>KjC*n)-mZ3%EG? zODGIgiv5F>s5fAbH*L~EE7iO^lC5$C#LS4JZM8E48X^-I1l=|+(RnUKCho8CN6z!R zw2iBlW8+yu{FlK$Pv0Igm8L8bgPb@3S-=Omf+L!o+GSNOT+Kwa9dVOU6!C0&W)SyO zoaDv*nQGEdvX3~}JaIk@8Nm(O6Et1Wb;dN5He0X*;$$012+@0B-+byjxjPTxt3dSr zvwq&yE(Fb~VyXw*xlZ4S<)^B3RYasmv|_6G#nUR7-UUUS<)9H~Ry+cDw1L6U@DcCd zI;+Qp_-2wJ`!xn0yGBBLtVNvfK5s4b6Bqxxpn$%NZ6>6eDjs7cfT%sc?ElJxwCOY> zwzDGJO|?sy3B58+99zAIKeMDO9r^N`H_3)YzRb2DPNG#3qW$$t@jMfpp5n^84xRD+`Yo5a!x)p)3HqnYrHM927Xyk`!Uor9gG}`19kc)tE36)R+k& z64i*LOa7T@ zLxu{YNAxtMZ9~z{|8DoTGQauj%1fKV#LA>>qPVwHq<4@ zh^bs)x0)fV5v_)H*)97S(UjBTW_8&1urW8cA4A2a?-ArB z{!5O$p#j5%SkFSYhUt%b(1t_B!`cuim=Tydo9pVwP(zmd0KBn}JZ44Aukx}3!?vZr zhU(LTVJ>v)Fp)nLf}5AEQI6(80K4WT!sD;4G6*0JDGD6Vw*s#YnXrVNnP#+PzgY1n zK`c|XuKS8>ChwrQkgNnlT9R21L&<)zX5ky13wzfc#O0H{->eQG7iBC&oHF`ZZN7K~ z9dhC#*baq5-Ougdj`8z=a11jr#>!U+;+&~xA4%~5P@{ARU%rj%F> zaLn?*BD{fH5nqNw7?|o1`jeLL7mwWHp=;apxt3r`;yO4Nbo*(F!%Dt^`?^kP_SktsE^8zv-@ zgg7|8LG`w_1Gh7Quc?;H1qVQf5CahaS%R+epzs8Hji#d{qFFV;}BWTccai`*x^5N-0faSV?s3PyZ4RO>>cUuRo3io6KZ51FGD(_$HP%4wN2n< z0epyND5M~lC3(alUAxbv>FFY4TH*_Pqhn7Sac+7S0`vRTDt2i<1ea~F$w9>MCh9h&9#^ zGZR~%lb&|Pk{)9FjfvB=lJTK&h1M_;C7W6U!h?|%AY$GG&BVJw;JW=FA8cWq8Cj5CPjYp2&g^uKr6dB_7 zf%G3)VZhEAz~S%(c~FDc%OEuzR|z(B5B!d{@`PCO4uSQw>l9`RtD7|)vd@lN?_DT- z^6ADPYJSR^4okM?g%L2z8+PB{TWNe%>~zKb9$y3|Q?UqafnjI&^r!<1oJiT)!a`r!+Fp%fU`^+O z$Q`8(AV%+>GMWxJEK)T!oNu2i&uu{u>=kFmZ@|w3%u24q%4AI&P_YkP1S8abKj{*E zJVIoxLm)qyeCt&q%v3~yS-|PYp}TJI8293oh;f%d9b@`jp2V|;gi~VYGzcU<=i!N8 zpfnAwIAz4$u8p1i=E*Y&~UVfwe6q4 zFPzJzw;|?cTK0#-zxH;MWFcaA;|~qAF4&BZ9sEyr5Q&pb5W7UUU!{)6#dD5Gu<4h7 z+E`W(v!Wb^Nf#+d5@Lrs_kDTbEjuRS4}Qn}N5z-|o~=vHRP4bH*r30V{SecJ!Vh7J zkGJDXveOAM+&^Fg7R?M7)4|7L$QmgK#0RSi_Crh%k6}lGGA`TbJOO3EdB!nAoV$wt zIx2i22Uxay{W%6QP#d~>i;Bi>5r&SxxNY5{Di0WI%12dg7B{BeuJAOV(dR~x^YR|7 z;$)_cs+*7rE!ig4Km1Cv*NnpM+-O&AfuBuWhA(+i=~jr*qxN*-rzlvPa5B@EtOtul zT_WzyN&5w26dTD5Fu~AgcFlMsTLo_}KK%(vbbz!r#FO{N$8u{c+^o;c&cjb!@d+Ce zLoEMr{t36#if#I=@*MnBZAEw;@yWUkG8`eceE6U-w?C5|R^-0CZbK~2ocWNu5wZ&X ziEW2*!}yO#&cZZt6vT?VN3(dYj;$Q?A9=Z}{^R`JsjWUzNWBujo$gorJ-{Iw8AVXH1=x{y!O_z*XaaK8j6 z{nk{=da9AXC97Pa)+L5AiXrx0vUUy+^Ql_}n| z(Vp=6Ke(wV-0V&grPdIcQ)q8#WI`7BO||s_<5qK3zCP>2&C>2%J08?a!No@$N_R#D zvJHjVR(5Ks8^i#QzaMEmIf90a@Syp_?f>To#3%O^=F|BjVmPrv5U?U^<}d0!LTuyk zQ=MUFZ+X*8!`qTv>1v3vjTI|kEfV+mwqUq%t9+Wk(p8r;*Jh&+D;Wqk>qDgBBQ{u> zt;1LBRU1U;UJi6Fu24sS@Wj2H3anv3g~KKw?96s{%rPOQ!o89Zlc#;QhJ2zH=d>;q z#CRnbKwoFJEgROu;0}voCW*M<|&&+&yl7^Lr zQeueC%ja0gO5Oy@zhUezll}6`5!dU)7s2nR8 zr<&|=mfwXcRjmcD^x>Ltnw}$CugnRv4ylJTxi4yy5YG+CIxmM78}A?(C@25V=GFYv z!7h0E0+XkCtHPM`JQxzcJ%$Cj%fe{vN}-VWm7s){Am%S}0K`a>O+i8!YhcpZV$ygo zcrEt3lyIJvRTvI(S`3ne_%qBYt(pbS^&`nb*~&1JTD$~5bB{dqSrbNyL)4`WMuQau%Z7Y%8x$q%Du(x~jgsPbX5WTj*bu}d@i z7|vMHYAcfvZml|6KJvp%!npcm;z@h23TKI+KKK~}C!d7a%q*d=);vt=@R_%f>^QCp zv#!Nyj*%S@+1axD_TC`|I>o6(<7rT+t>+sk$mgpsTyj zWP`B#Qgn3b3c*tDiZEIt+h7LZuW=Sm12(`C(F6BM>D*&sEU^>Bp&}u_B*eqltFpCY zvGNvBt0$T#A%5@vvz8DSL@6gE_Dk?iSFmt)r5@Pwe%Tzczv0DBqB#hHi|O~vB#Ut~ z$MB(ko)+#L5)JWQHFh;D&>Gfu2kfxc!Fq#|L5$J#I1jsTxcVDy#PY9ahmw7=7IA)d zS{Q6oB8Y92=z^%J^Sqd^DAR z8;^(IBMnsBt0KhDNGKWW%POzJ&-HcWdW^X8#9;@Xumz4brUl6stfB;d%zjob<%omo zO&A2sxv!@YixD+kMhf1#i(c3_pb zE`^E2-p=$U|H`=|HnLZ&g*-Ky_YZ(Yv*u45XPz+yjuuZD`a!F1JtjYnuJ%nqXc(&ZByRbv^gAvx-iY%OjoJcy-AJ*+^W=(!)G*`+7@%zH)WbW`%hNGtG zGF?PmwQZI_#{U;UKETme2{_)fIfR;K8y^kU^#(+PPm9Skw`8kx#Y^nt40 zbC(&L^_5kKt^ZiT9$wV7WI=O*&(tKP8C%_nxez>J$GITZ?YR6Et4LCcECEF+d4l6TgBmvDt5f5QlASc^Aemr+&4W_ zZRUIeDprt@1wZV`%CaQyrTrn6`5oKB6r+SV;qVz774}w&1CyzcS|9B)Z`J>&0sPc@ zS(X*~TbeuKqQ6#GvfVR&Bjrr~mO~*rW*)f3nsoZD9&U+xE5-i&F*I2F{a)$+J(PXC z(wRGc4G2&NW~8z;*K0r)ABT?L3;v^JSj8ec=hkH9@k$Zt@M{!@pVd&Xt38$C0>>YG zYu1*dotZfU^WzjMIw|c~VHat6mmwTQy|ApwW^`7H?a@65vtNepieedKfNS3RdH-BO z3}gU9Y_V1~6lW!Vr1=HpFl6-0u3{R{L&TT|F!s+k=kkPuK(Pfg=pvm5zm#>a-I={Y zbiB?dDc72;laU#5)%=>Rg+uWAz2zMQpK1E4bkCZHHQdUp67GfvM?mf|M z;6r5N!1eq`D#hhh3|RfNW+NEuGa883n+|r-R_^x^4?H&g{u|km&0%sEr8gp0B)fhQ zb`d!kGz#@9mYfPiGJ!6-HR8h?{-;=zNkE_1lL<-{^Bu1gFDu)^q+dmkYABfdj|#LB z=aj9%Z~9)I+!^H`%LQ@>G}2}NxaBBSaqU$A%HFwfc0Cp{TgJU1(8hOW?ai#u3J8#q zD3jQ3Stcyf9&F$qR3dYTeTV7R`E7>K$eQ2*D%K;mdzY0jX6QT<1b1SV(wIGW$TcH( zKrPq^(QRDQI=F1P;UK2$;w%|9U0`yb{Z1MQ0w8%qHYqY!P3p*n0def)c@e*fFm{U4 zh*fmXGA99EVgN+Tvoj#7%BhHrylE&r0XX5*8zn2!jX1D2*Z6^qg#_u2dlkJ0CWTanO_qUjD14&5 z?GX#f1&v(dQDB(T&}P`k z(YT5G{db?q;a1V6jGzGHI4&Ml1`&+z``r4cf7jhd}_}27v&|QnHLmYk94N zXgkEbo^a;jQ^60X%J1qUn$+xGODGho3|Q%uEL-9OGDWc=>MuKS6RkLk3+n|;tE+zB zgKYP5Fcv;oa$Hsb*)H85G2q6pfeaROao1cF3<0zqg;-MUbIC)%T?W_6H79LlNJK0g zm9X)*IYJ{NF42b4f)HKb90o6=~1Kp)8CYnJUYvcbP5y#LhPa(mnvin zLmDu{p)xx?2|=!B&r=UY9Um@lOqL<>fdfr0TtJWDYyCxt$e#l7?~Q-1C2^4<1aXMX z?y~B!ZP@gw(kA+}gAah_cj#MPCvIRoK#ZD`>+OVyQm2DqR!&hWSw*T$eY-$|Ri#m( z!VmbEOQ%ae=mOz#gJ%tu;I}9w*O-~6DowcBi$RI!rZ4FD8{x>1T=9tCN`@`Och(Er zVyXmxcb6Po^dCGLj=6pv{w2JD*X0bzs!3A8_)!*!XG6VReycC_%dJV`r7RFX^_r;n zo2;hxhs38s_D9@K9uCJP*NyRcRZdfi6N#3f!@fzaE34zVh#TrwaB|$>!73pN=Ying zXxzvR;&WfX zhE@A2!TiUDILZ_S@$se^H-8%e>LE>U1G06K){6Kp%{AzMiRiNn!<01zpFrhTLI<^o zjhw)==qx+tJVGW|4?sJoGrlbRzbT9)kOwrCK?|{a%brB&f>S9p1;bXk2zer&dp2|= z#!H^Y>9cmNvf$f}+EI?hg5?h_|5TmlK|a+s%aPzY8`=os#riQ>g3Xd-snwB?r1aTk z81P%vE%(T^;{lb)-yucqyt!id#*h>AafwZ#f|sEm*?(j!#s9pMQtXUvhu!J zx@4eiiI_L%?FtcewT+Z4-!oU2WXLlN#KevPCcjw?kHNsMAzSL5>p^}$VGAwWzl=56 zgUQH9rMOqX7g^mtxfLU;?YMfH!35V7M2x78=Fqb`} z8vG`c;j^T%>bS!r|HT`||7J5#2fvq?CC%YHaG;+**_$cWp+q2;W6AMZu0%)b0dZj& z{5ntM<4(Dr^Sat+z7 zG^N<7zJhw&NY6bO;lxqQQ7Bp9Td}@654B+P(&YMZ4C+!2)w}eY5Ah*?IzygmBUwfq zvF!5yVe7iXsyd#w?Vd~L(91={f{Gx;0ydfr6{OfZsGy=EU;`Uq?6H9&tJtu2L1T#> zqlp@O!>(xT6{9gmqkiw~E;rZT^ZlVO&)qgVJ2N{wTMl0g!ku$lTAM{rmco4j6`0p~ z8%wJ#KG_Eih6u`CbCZ`#~sdLv3Vi#A!l`?IQ`BNRR)Iv>{ z2AQz#`_}zv&XAS#Z4ZBJTbP_fYeXS9(Bg=hK?Tpkq+Pq+0%yu5$IN4XE6OW3=?7D= zO{yc|4ZG7{g+y~+pmH&X^-F}&{A$roKZi*^s1cCS$V=JgDt&;4I7YZE>Ek%PH;*nv zNLTrVHMqI)^N-)BxjK$d7@17-(qd_}2%EWn%J`n^9(?eBfMCpR5r|h(h>x-18sR7n zBw=jT<)pr9ajJ9ye)es)Y6=V8RNm*14sxkWVsv$V?0LOf*fZa~I!E=Ylnug~DO=1$ zONjhgP`W8I@0D+%#=DE|5{}ulc!T77|5RDCwnhhJGN#$Kn)>N!8@DHy;EN0ht*>4Y)6L0Ir z;7!&SQ(Su2{!e|v`=78FtFxgA`)P=Sd7Xx_$hxc`R$7~XVckAf_C8KgKoNHO2R_HZ zb_ai^i9*NR`a?9cXXcuzvoIObxD(p;9rV^vvFz&1{5y5)7=F8jew1*(n`erX zGCBtw8Qr(fO_n+YRt_9-U|DfkPz3ka=r}X__ScAg!Hv=+uYBC5Ixc}4ha$j>@ewUI(g=+^q#CJ}b^>YZ<<(nG)0FT&7nx3egu zTGy$OPel7xZ6Z6jp~@(kFvsDS5ON&FIoSsIW#qr3wvrpGV_rXM?AiPu4Mff?{B^Og zYHBCR?GA`Cj@fzelYS8@lx}AasDX9Xbap;McEJlwPPp4^kXUL>=p>_R?r;_Cy))+s z&AreOwlHG~RtcZw^hfCIshcA#b$L3ynvXE$91Jz}gm8JQDxggUvyIq)IS);R(X1v} zLTD5->a4yx+{&Ae^r3Q@PH1e)TIxkXghS|2^t1O(KGO`Pqq;>T>myb^!@WHH^lln& zS7o=N<&t$enqv!f8<*ghI(3EY6XC(SX*=|c zQQ6u^EX#LDy(Ce9hbJ56ASqb6Hi$C`kDxMXo5vRl&!f!QwzIB(rmuR~a zT$q)T3xr)>yx{>d-d&Zoh+68Z9+h4qVa3;@#vAAYc!Fs+aw)#8F&myOJIf-6 z@XPJ-XI=_Z30_({NLeRCNfM%;ceybw-mkG&GZu*?!k`a5-;!YZsMeRN@B)N~qMkfv zF-^$&9@H3DYc;(8s8JEg{o@mOd?hw1kQHj$HM9@bbmcS;yFW;kB}RFbMn zm^N_0UFKb^ac8>hTr2f2Ihurf8{BrIB(e54!WeC9c;auCbHB=e)z;yb?=>o_TsiY! zG06~dyh(OAF5mvU^LWqRU1-Am8X3~Xw$9EqR~Jc=2#-!I+s*D5!)TS)WX!f4(FmuI z9G#=PJsYw1hosO~#tJR0Phec$emD#0sWEdIkZ+_eX)V}6*s0ATKbC3_OMmx}MjWi) zNCVNp!h_}H;pf*!G-6kh_Q|4I|;@ zv(|&fTn=(w*uD6C6ZN!=*AQCIiTP8wqP-7lshcw?%zn%%)cS7Dls!4eK4NwPV-%X~kw# zYd@T|%xQj|S@qM3eX?gI^M_U%rODm*w2YAuC`k~Y1l?!uO1DX5gs7Wkl5afGs-iHZSR;6|R&Eh?o=AWGD0Ptrh-73AEg%O4BxEY;0M6AFU;;R9?v_ zbTcP;-E(H%SC%K{rR>EEH+tB;ptpskCB3 zk+5bNxr)LLFF;Iv*f$K@p#afmLihWPce5QcQ5NZ@Ecpx4XlBcA0Q#qGk(PO&5irmgohtf>*F4?Kj-!fg;(=wj9NXl?K2sNtchN5LT&uxwqgy zr{&hSd@FT;ToVzF+qf8keF{=#u97XW=zv8K2Y=M`lMHwgj#|T(vBUWa-ilp-oSr#~ z*t-6Yw-m*Hu~@-Zl@8#7jzr--8s$KXJ?>>M^$ct);FX}|-1bVAl|@I1DvAt>Rb#?}QThQjrG z-#b+dx&lh<)GVpXg#Phc=7@QXm!Gvn5#hR2^m5Dajje<^Kk}nsuo?RTHgdJSL6iB_ zhOdOFKw%4ZZ;>269tCo4`@o=Z^ioB{9fvq!qBm{$539di5gi|jfmr6$0!Si;$re@Bfl&}{xZFoRQwwjI1gv^fxOM3qDYnF;He&yieOo3u`;0ynN}Wd|TC5Y7XJBFJngtQ^CtO_d`&8 zrmUZE&Bl(4zh^2Iz{?deVPzo0&5!jui{W-zsfa0`Rw-G#65k0m;PsweCgtieW~EIH z2O*3^=831RT&g&jP=EHqo{SD)N1rNotm-oPx$e(i*wCqySM`61Ncohns(ZjjDoI$R zb7(3xWTm3A^B?l<)D}|i2z#`c+nGe576TKtEV}+8MJ<$fCAAv42*{zi7}ztnFhP6D3J4z! zj)MzF7E!Qu9?X|>wjxgWd;zDHKJT#d`wTcjpDlZJ5<#mWiDm7D>Ltxr9C7*$&g^Wd znuG(#G!JDlWRf{`C*~{S2m`Gmbq8uh>!}ms`vumr@2?5p3?`K5Y(;o=jy|}Oy6Gx5 zvnhs#=7ckFxF&*L>lda9i7%apiKsAJ5vOOGLUgwGD*A=|C|edjPf;!8x{Br;NH1%e zgMoKjjft0XJLajE&!t6&1>pUubHq8lW?PQhk< zt<}z0Z?kv?D>WPuHBuBpC8lX#+2!@9AozT~lNtj)Q##@7nq9{WMR>DX5j!3hP{O{i zD;?Cg>%d-@PeBV~z0U_zvK-bAh7bc0Riu3CHIT(QF(f|-XoAha?0Rb1*KxVV9nX?|XqE zTq7km-VNUJ;+ISG!zU!RD;5>b8+yGr&=U0Cg1H!D5(-BmA9~=#Z}s9x6Iyd=8jI#u zEjj+4-CwJSumOF=aLCve!d%j1MAHs$JVD=lU0g%qNv<^DnCV5 zomHF#bu+hHWU98pgKyM6q2u=Sbh1q%q_`aZM|gB39;@d8=~+~@Sk%| z$--UW?cR1mfR8S&Q#xV5;G3KDbPLb2bt^Dn)AdbyldrIl>7eOyRrqZ75JW0V*niYA zOMO{u7UzsUx07`f&fed)&i4dbvoc2rS3`GE3E^X_EmEqvzk*)yOt>;OQ?j5wEbG8u zf|d(2$-9{`O&W5#8sOdi{y$>%b#A&MR$rr_*mH`ny)bAUT@c2&NdpY~Ty2<`y6()9 zQ`ZvcYwO1qPw1B(V$ItY(w6>V=ot34ExcrPni9yBpdW_C^$)u{`k&od##E_~4KbX# zhdLl`O6N;w&xTv!HVt1|?eQYtUA-r5AK|0<+wl>Nl zn*QI+R>a|l(a@zwuSZxJn3eKMs`EpjpTYawzA3tL^~L#(S(vJ$r~L2YsC?mK&VoG` zndY6#HfFDL75NBl!)gLg7l}-E>QAsVBx{6~Ggc+(De>iFK&NDuSq+{} zY9o(OgQ6!Jf1fDgm!3asyxF(C@+`=0M9a5s?$%L++a~UnVWp7}u9qGSMvEH~x5<#XQ46e~T9xgjJt_9vt29t^?cg8`37Wk#7DV=uYUE2nE8Wbm3j4edgn~ zUq_2QoYP@S-MlS1cvKEjNDSgQBle4sI7()*?WDlmL!Ns-7q((CVM=el8B!RgB=TCj zq3=Omci&+-L*y^?klXG1CwOH=$<*PBYIu54sh>Lj_cB>cn5_zt_@N%0ry!-hx~B?>(`JZ1G7wso*Fm{ZXRRZbXLWvHHm zVw#~Ydt}Y%D0aDCj07ne+n6OAnxt5A@tX-+PySZxYPt9gV)sWX&Dn^Y91C_~evUcY zot{PY;Z5Ga-z*W+?61!MvP?>ICWI5NgL4>}8W9!Fn|n47sp0M`80>j)QiR zPI7vZ@2Uk1-1)!e&1aKGpe0_Sbb?%bZ-Q3cu+_X|=98383_n}2VH2f7 zjlwA8yxX;moy$_@@S2j{U=vr~dPBJ<@jjK;V_)-g zbm}8PUp(RF>Wzjo&rBtg*II^O&UT6YogE~JDa}xXW!MJNPW3A7Lu1Ryc4OamF}v^H zTC4L*i!2(!EMC!PRJ3whjby>@?1edAY9P2p5=D5c-r^hsZg*Ihu|3Pl zj}+u%I2BejSvozQuuQG)ehU;5%ZEB;oYYrm$WwN^!aT9Jo1CV^aFYCB6j}tWy&;NZ zZOEyn-jxm?;Z(2e$%0yRTgM_7=UAy1Q4^6&*v@#Wj`@yOhVjbCgwFk~+GW;rq%w;C zG6lbM^x3$Of2ke9CF8FZ z>czb|GaoIN&GbRq*HC-y#Dm`H`I@Fl=OjKF4l6h&rA}5KTI!5WpvZm%>dYYDF zrf!jq5H8xfESG&sR>tu<8lu1n{}bBK)s z^(r{q9j45mp_Dn>9+6XBog%FlVYmAWpNXj%rE0R;gPE;bL#7iJ{&xLeF@=2&SL(4Q z<8tgQ?+g1JPk6|=GE3FbnL$dPn;;Fs7bNvR)C7+bYcU1$w5UM_X+_&=wbA#e4JVd9 z9{uU%mnCBNm>20WF$X*Ql2L>Ma>vcnt4&Q7lE+L~24ik&gq#it@2;)mte?1Qvf{za zl(}}uu~wJJshM!fgW-2sMGc6X9j|y(x(N>eKb5T!rVgmSin9(?c&iDL*Mt@`dv#z| zaY{HVoXyPCj~&EV5&9inw@M!Ch*O%dB2%r24fdeoA!j5mgg;eZI+eZcsf3Czt8bqP zo@=G56DHN)wL~y(HdWz0JjX_gv z`;1P>F{w)1U-Ug^YMSuA-`LaThN~~T*asRIH;-x9g_OOb{{w4^%!G;Fvx{hM?#AAX z%CT4DC65VLrwv^rl6-qhFCqdx`}pVBO!_&6Q`unRyN>TN)ovC zM26l7clBJ+NO0Y4XpS{Y`DTpwj|a#pHV7_!>DYc51|#QYTEa)}ql~cHO^6ahY{?3eAtg_03f2kRk)$nAIy37L}=GQuue({v%C z^ZYA`r^K7eRS4nm(Dfq(Hwq#YSM_(f)kt{Px#w^Hbuup|rz)G+Uu&*fOVuEpxLUV` zWp_dUP~4g|kC5vuKcvl^kOo5}ebEp$qALdC8y4^+gM`oHo)+uVBl*~-gkd_K@&^uG z({U$Ei8WbD604UNF5?vR{gc4-BJ7t9QT#bYUM5;g>M{kcsbWH(4F^p~Uy;FEeIPqa z_-SkYYN5!(p~&>`FBKu&ePl|!K|hM3a&UpHgKX6w19`5>9EA4Esp3t09<&q3)kn(# zCA{aoa3;II5B4M|QVG$2O<*D1Gir;l(?FlLdX`(W7S8zEZ(+0)z&zKa|ian>?Ow2!($&cuX{?K>q%I|*CFP2{iA5E6D86aLb`)^ch5Csr}zqk0kq zTdbKnMK8on*!kf(=ITOdGG_{~YW#yj{X|fYWp~CTd%;Yr(AX}2F7gq!N{^{V;@q3p zyd8rYX!W`dxh_~aKn+=XtWsO`ld)lQ6BB=Oj56sjo2Kqg1vpe;gZ}v@olPsORK@*G#y+T z5_Cd`-j9ZfM#=)^$$DF?G_|+??It2U!vaw(qq)3A^h0kD&?&5wh)?pgs?Fq)Y>L|6 zce0WpI-X|QLS9te55ludzI`Qbh_ILmJc`7YH*mp+_V!mckyl;=R9DAP2~}* z+fdj2TYewPdIZXoqTYzl)Gl55Py`ftzqVIIztUuom2mUKDs@Gqj|g$-Ix>+&tyeSA zbHd_0lOlr}f)vznPL434{it^M#7hwF@^uJAtct^zp zWfL&;!SA0CKv`R!=GF><{DPK?tn&ipSvz_ov{87yGX^ZQsEm7ru~IAu_dA4a5pA4jAE<`d$Ch511Xh&;l3XLS#DOCW|b5$&t>TY!8&zb&GK_eA(+#c_aw@62V&y z2sz`qA({4#e7N9uN7J`5XI&Q&!_UF;u-61kb9c>6=ZN!I_*utZ=H^~+Uvl)go==}lq2trO;4qJ|o?^QqWADV8M&uk5>bQk-zK zXeCAI4=e~Kv?(3IVp?g$dYA6h#!piTByj+6Y5u1z~cI2$Es`{YbNoUXX5(b~ae1g}~+v9sKNzxV-Q= z7)qM57`#&#=T}iLqaaB$VXRTeaW=Vus9bEAjs-^@nAK16=U}h%a@_X8Di z3ON9s>UKUbi!Jj-`H*02)$VC2Pkhk9g`elo`D#GG`33pLsvQWUwh7slqc}T7Z-w}V zDnc&{&`9SO+eVc03H25q&(%0aCdc!q?tYY{6YlnRIwf{-&_7Z93x59VV$Zp(;!#+u ze}fS}IddWxHzz~oe7X=5MP{`}gIJ6+n&lZ#zm>XQDmY=2{nu1IS&r=PqI`vY3z56R z2QkR2UJYtRHqDl0hN1;zuwW@6vV~{JP=Cvj-uevn_`<;*4fnDd0-mB+bUlQs_+Xj` zOMdM{Ozw@%=-yhIsX){DSqjWMtUlf8__ef4HmQ#i_Yj>rI8X(o0kSR^(vsDj}RMY~+ z9Ne)U=rskJ;UW1?*yLLUYxdRwd_?)G>~1YZRmw9Jvvm()%=YgG|YKLH3hRbxq$@lJ+5<6u2h+>SBk>m;C1dsaT1y6YSkb}7v z>Tl>Xi5Fp)8xJp2`yQ;{4w#+8ZX$^=-Ye<6zNqThZgdhqr<&hOWFg!cb#$T-Y}Br@ zvvnm`BT@6k{Y7s`>%^NNSK_dDcKOj|{fKL*Ln=G;6a=@$p$a01P-DLTsvyW?7YHJI zK}m!GhvUzPDLTYM2Ba(C=il2r_SCaLWiR()gEciq6eC=GIHoDpDE4kA1Ry};q;$}46iUP zwrw{9Qlowbso8RwOgPNhrX`W;!G3&@Yoadp6YUaC?7#cH;I!{Pa5~FVBoR8fZ&@!& zt?-b#mju2oB>&ruOry=8OUtIe~PlE}2Qk-kSqP--MPa&iSW+0Bnufu=! zQvA4YQ3kK_hku)WBm!zOi~5jlm-#qHvrg&`;jEbYzM{E)<;_*HLfG}$vmWe7eWj*N zdeZRcQWprTe6w_+1aUU034U=K((_MZpC_AmH`nyLhjN309!(~$H|6A%U>ttkI~>0l7VOJQ-|w4Zzz=kCp=Xb|ozJaeCF6dndW|L9%oPHmy#y}c3D+He~s+Dg}x(6sqS z_*7&`kuHwaq@nXy>c!zXA|EA$xBnPJ={T!w6C#Pt;u^qp{RwdVft>S%i^Oh^3yRZ|t z13Cr@PW9cGkCTahvT-ehdr*rt*rn9l$6z<58k<{Fs(LI6f64rW2Q7@y#g#gxmac98 zfuoa0jw26yYC}N-p>>mCY02fGvh3J)%w;z)xfy& zHnU4|HO!^D+&5~2S!n7HHL%M}*14G*4%+by_txiITGAFDRZgh29m-OV;>37UHyrKY zc@DVACF?$QPA@7JeC$@>%kZ&}mR<2n)Sk-iYf3m|*%~E!9tWsM5!Z zdftldUDDZT`{>5EiE7vYGU0j<96HsT4lXGQWzJm`ZsfNp}(pegzLz4x=$Ay zVupAlWg&!eb*-#da!A+U%H9gu9HHf@;{IYvG1bYf$T{_JNX_o#CNhm~EMhj!kgt*q zC0w-m!+f%_PI--B{B#ZEp4?s>KuPs+d@r1~1OAE&J3AH*zpwN>2*-6CpUSE?hv9S! zfHT9LjvCS=5PEmIc2}6BgZ?;qUbqJfmMaJh)1VMOSnvK zt!!F;jqkq9?!G8>ik`3Vm75@r6tp+jPW>$R%L%P!dR7%Sj}vfb3ObOCsgMXD+;r>H zp9TbG1<38Wfv}fnj21Wfd9=Sa!a#Jn3<+CY;-m&e2_KJj3FDJGPkz}*N*_JW8nY-m`jdf=5V@v2CHp9P#-%9 zhW~dtlM`l|WnK}JnwvklTkA1W)#aQ?XqJ_>or((QD4Bk#TU1wHLWBm~F)W@B{yk27 zt;u{hV1CbPTs}MDNWh}}`8R3i!hzSOiUYH3COw!dFwy@0_jl{%Neqf7_~V-WXA2r- zAJ#V$>+*_q1?vcxcKiBDUqZ(m3v=z&A=2Iw&UkWgp}sYH)~lH`4cSN==h+d9Sek6j z8sIo)L1C^LyO{y+#uknPjSXSey9>{$ZK2rotVMd&VcP{YX_G;Xg-&E9ynHO6hghHK z8p<74#RF>w`y8E~ODZ$n2)<^^HVE4s>Fe~}Xla>iAO;{h4abpxk>X64vS;%U5n48F z0C`3xVO$r&g-%vZuhdV1;&AsF2v9Y*m=5gj291kj+eGoW`A_bGV8R|A9*Giahl z2v`2_0)8#M4VArKURbt(QElu0bvAWJ%+N`o=EI$axFJu})V0hpcRDNUAYAq0z`OFm zvlFwT%lzIOHRhb9K^t*(@6!hP!cYh*x;vxBXqJKj(RJ@Xdf*Uo)$~U>6%!txJ$8Ws z-8VO)b9X0e#0Je@&=R7Zu%eVm&TGWvsc3c-}S%B`UgT!PH)wi z>!L%uv})I;v-jxq(U+v>LwGRjbOU{hBCOL5g#2{kz*1Ii2deyJgYz9vq+us)=62eX zIN`v23T1SLN-UcHJdM5Gh7x%@<;xNDnaT?tNB=H@m#>Qu2)eLSzJ^E7-X#JR4*McXtj8|e4&dd4(R1Gi9-2!=-?+QT(_bA{_R%d-9Ta| z8Zc#Fx65H_4C%d;diIeRy<7e`&e0FGQ2z;!-I&mpL_rw#iTEYjp+_?waL!w(;cPc$ z=XT)9kg7YS!qEJ`W5ww-_N`Ec^yi@1=IooJ*xNPb?W2g0w^Pu1|H*B8lEFuOb1R;K z;MM)OLvmm(3NQayZJAz<#MTHY%+K#GO*5!-o(s0Lii_ly$}?o>HPU3CIF-pOMuw{D zYw1f6W)3geX&@e6&6%;<3+1Tygn8A|Ym&CPv8vmo0c-?*y_{RGk)D^vEWDiksVI{5 zcj+}f`;FNb7n~5fU0qa3*suMVWkML{Z8QUi*+Pkbipsx*qo)(W;=&rm9{MSZ?gU(3b+|MvhSC|4ADQId6J#mq4o=$ z`^S_whTEPUA@iePTd3EB?Og)i{Fhwji30)j=_yJkO#I_kG1)p-mX(8Xzpy}(umK}! zUEhDVLE2nTD7B?jTEfFs2B(%+U6Wh4+6$$S96;3@POLm97z=u}RKJ*YMnI(OZ*(!C zc^dWrX?Y7YCXTpSokWY!L*NNfM>yE_imeb8&v_bC%Eo@nk?LVZlDRJx&%n^FEJ_z$ zn6p5(^B9hPPn#R5Vnc*yh?_4TRJsPvtP0+%69UKSLz)#kIA3GNdvbcde3a9-E+Wb| z&UYq8h>HnRL6}v=9tosLf_{dwMr@K#j;ZByIgb!-i&%y`MVe|=+oTUnNGabjoi6)F zn9y+fV!c7C!g;~ww1?Ja$we7qg8g}UtC40Bk;yz)W5MZk&6Nk76VPDQ;VJja2gH;e z&IZ@#)}`(GY-uEaK$|D38vQrn%Ic8Sj@zRX@S%FvKG}?>UfDNZjZa-n+xw+&K&acd zGhJu~XCBWK>4AOLfsz4)jUI(n5+2O!T+9ktxl)_YL2QrgejY8PgQp$H)u_Bf=W;d8 z_#dW=S*L9NhTbbjV-z;&*g+Nvs=5%Sq^=@P}5u-_9>p4DS<8z*!5q-nYChW^*d5XUs#~t$jx{fX=k@} z(*&~zZIM+PgAbt4NP&)>zF&hkvcGyegy^L*^7fUO=8hte~ z-WyKbcA?5GSSgb$8OT{ZzWqP_|*4qOYmU=^2SbItat;s~4j$KD5^39T-XpgcG-W=H1{6A*$YJRDS6N_PW zL>|KWcP8C57-VEJXE*btlvKwm#&veb?Lvf+rsEd&0~9g(sf)W9KVGl>Qdz_ThN6Sd zk{J~3YR!${#(a%Gg1{huHpZQ3BRpjLOFiOeefF(-j+s^_u`^3FA-t3&m70&F?@HZD z{fJkTS4)p#D|l~z-DR^_zZ_YOU3}BIc=*xpIvghTB5N4w;jQbYpRAq$O_Ggf-0@8$q=fRH8PPYH<4AD!Igavr4|hXcB`XnH{p~ zl01nj^HxFgLo~4Zcje?oIP7c-&OZb{P!Z2_w;mR+d6LJ3o2pD6CZ0EVQy>>;MVL^! zzEP4zB*ApG#)=m$E|7L~0w$CxF0ESq*E}omWH#zzz4Hyu{t8V~K2S+3G~yOa zIOc-`4eF00FGEnZ$Tvr`Xc>+2lf*UT6O)BjU(2$QKZg<`Ju9eZMwUy5N0TR zt#ps+A@(#oqwCZo5%Q`C&5Ws;h2;qGDQYbyyV9C4RWr~ERYbV+)F+&FS*PJ2^zyu+Q9z)I_dV%S>I2aeAbF{A%}wG6YUQxVdAdgA4SJGMEGeO#;M4o zZ!n3m4Vx4s-AQ_`Wy&lym_n@$SZRb#%Pw4#Ycf|jLgRir*M}m7GA;9(#z@V@H3lM? zu=?-OGbxD1({0r0is%jDrQhFQGAP=jqs~aZ5h;ptoH1xEMY(O6dIetm1!sBK`KlMT z`YMt2NbGsAV$lMmW*;MJEG_%!s1hGSEl(_t?YvRMejp z9n)y}8P%^+#t3^BpMP(__3Xz>tkvqWdcwobdu+t0O?1e${LT}a-)diL3KKS9MZr3i z#hqJW&VukIB+l&au*#;VYbew!F#EE`mD`C`mo-s5Jp=LE-i6&K&}k4nRdE8dX|=K? z8ctsk28tL;=x#HhHU%^rP%^FyUzZ>2XaKG`M5vEQDmd57)lYRqF~Vg9{ynAOQlv8#Mlq;JmI|#~D=Uj0P*1fl=o$%Sv?a%SN zBCezaJ;ZauV60gEkJjM6*|40O;??%3dzzYyvh$tQ;ZQ2-58>&+dMm_jmhfAmDArpL zHQqEmzrCo;v;w<-Ov%MJ0qPFimV2@9*5gp8(rdpj|}!~M73PxIxkI2Zz3+X z&I-2WjHWHi(&biFCrLRYoFBQ$Sahts0`Wdb##xQHDM&}6+?T}L3&v$!l!hn?KPPP; zj|+qsG)bHb^kwYG1cz?oC^xU|f@7|S`T^Xf?h@A9(-4o$)1{#D)@)g^ORfzoyC5f# z=P(P8=C{Yd8g>d-asFE3q!!7l2!CoZsHI`13+VZ_bJEFq02N7RUVpLXmo&rpI^rGJ z@F1nfit=?tG~01pJrhUi&g19) zmaVrLG!&bOhUoq)HAHyx>{BbTc@^g%H?NwY@AEIN!(;8wGyz1KF`E~qGgfnCF~Y9V zr*Wp&5#5UZ3NI=v5C`I>$!-(AYBL&d1yZ-Oy>Rer{wFyzWuWZ4Mt{fXDXqmyKS9DH zM!;CMmkc0W8Z`WxUU9`l*dFX&`jv&VnAe&Xtf(pWEa?ab^@Om7%c+B8!&>Cs$CBb+ zZ=F_4rU%K)paJg}HDtnKo%0oyt`bte z34dt1tD7hrXODwJRD_ZU<3Bb}*R#Z-;~2i;kW7guypgz~KkHwriD0kn^R;SAS(b2R z*zOcP7lgf~zK81y4^RotI14pImLOam5pE)q&YrJZ%EWn27Ctr1SS@q!gRfceaC zO{ytV2yg#}1AAO_?l|Y0v(hKhh!Dds&fSeCFC=&HQLC;HLRpseD8vtWJ%D`SX#c5QW4#Rm1hRy zMfPVX9sLe^^*UOoRhvk?BFxG6s4A)`t${sv!`e@2dg4ID2Tgl!+v)MZdI}q7q|X8 zh0Te9nJM~HW>|m>>26oNh|lOrCmp^m_ff9yJA+3L8~%vLes3c!vp*PW=zw`P*n?+j z$vK5(70W(9)OPgskzwRikaaL(ecwxUro;1lY#N0MQTTj|=7&x?r|-U6v`hE*alz8K zRGqn6h}wwTghv-|A1sngym0U?>u*Uv?LrTFuRTkqN*q~w3ZuAW#a`?tltFjynB;4< z4}`sBA#XKN_Q~-ylJci`!V?Sb9TEL68VFA_(>qsdAI0COeJu*c6M7fVdZ`}=+~^sg zGjfa`K4uiv_E6>{G&Nb#Qm=txr}!m)R8=~j;=N1PLY(u2usS~=*qSTccfR5GgOK4aVPujAS(%O5e%H`mHO zv9E7IOL?_g_H_W{*RbxoZi7A;w2iVFRvM4l$uLtu+bPfaV6(E%a-lq}5_}r}xPwCE zvfe^Bl44P;uG9^}rVV%15q016#tD4GuZXUg*U^+}jNk^w7sKl{s548^;P96E3Uy@+ zg)>jbX951RFBlKNWl$w3P$W(mt3u-p;d|)=gTTa!)42SuJLegKWbEhFnXC7 zP~r&T)xddv9L=xNoMH52)hox3l$PT^G^x*{2$NUzw$SE`MQPeItp<`%D zvmZU`peNXiy;N{YWQg>m2_uI0`&FOr!Mdlw1j_G7#}iuLY#k=*hpEM9{N8J-@I}*9 z8G#^dvB9UY5R=lX`4(CxDL457Eyx~@fj1=R*6xzeLabLL>C7w_pbg>xVbt3WEOZT~ zJK_?%-Gff@N(K@Bd-W%f3hPIzB{rB1uP=nmd3{>17}(RQpIb%M%GwD(n+EcueJz+p zTb!2(xg)=}LmKih#f(pgCOz?nY*#~rUum?t@1*QY4jIc?;H@x^( z2Cuc>be)}QCOJUZVo50q`$qZK(<;5-+(=JP(&x*qZ3PiX>n2CZG1}Pt46aZTiz$_14?&g zdTpmV0@=g~P(Qk`LDdt!80h{$bb?B;)1z`#E!}@YIvcN5go|?uKU8f{o87;!X+pI- zdfD*m{vFHF!kw-`2UQzZ02q3)#LY*Q! z7t<754|JK@>ub5MgVApmx8dpku!*_0#R+w9S(b2Mfm3(V5x&;Yu#ICdNQJT!gzF#S zMYT{<1&%^gz7XyiGMVrfo0yKoY9v>YCs}EMYyHw?A_+tbhxUWGVXG&bBz&0p<_neS zz>P(JEKr*|pK8prv*^*7lIYPL>Koy}2sa$oCHc8v3MRX?0{w=r&`HnpUpV_%R!F|F zV?^RGehH_VjFA!s9sMhST~uUyjY0LDe%Oo00;&bu7J(D9>xBTs6Q-~D3%AWQke%}; zirA7ZHBs8IVk5k8RcfXfbE4_qndYZo`w5r%LTJ9DI$d&waOJgieu8Oklb{du1UmJH zFw@crJH%jEULr;@UZxPHUti@ai25>GXR0=p^%2e+{pKz4N4(fUZwD-U6}-h@*!GRa z#gcil8-%kg6AP%aa89l}O5EFIT}O^oRKCWJkBX6Op746g4Ifcs*@)T(UI;=OOuW27_K>BXH&MW?2~s*c1_11d%M%a5-WF?^^MAJ0pNh3X@FMmV=e zn=vAt^wB9Sd2}+TjK1bYbr23r+&fcHUN#OqTOpGOD?a%Z=bQD?@g@t^OEVu&nAYm< zM==m7sThb@$Qsp3c*}Z7maH`dQKB+)d7_fUw{2iTgeVr9hPhy+Y?07@Wlwhh103Kt zTIl2Jit^F5OGx^?blea%v6cs!?+Yh+HI)+M$`sVVy3Q>rh?Gsn2(tlA+9P}X7Xev(dMb^y-WyK zP(^tdb|ZdXzrg+%nz{m5(Ns*Z+azs-$2TnQAjCVR5yZPlCJ|OYe7Tx(LH;Of;x3xUo8I7M`8;!L9rj7@Jo9wxyk^jH!)4(u z=fS^_^B6$It=aq;5HrICrS-~h4Mlp$Or49`S{e|-R`X{b{-5fZ+8i!Jv8`k@HMF~S zOl?s?@qkcAwg>1j5#l#t-Ah9wNSb9G7oIP%P~D~660+$B@cov`=vp}qMy9ls z^AUBhe}B`oa_*QgdWcvrPCx*bswV93)x4&dOZl!0FCUC(J@4dEL`Ub}^2c=#ecRPc zaapFw1U9s>Je)#^(qwt|{W)E^}>wo+-9XzWq8E8V z*t(%}?L;YIu;YYGnk#s+8Ot)mL7c(ZY^8KUvth}{^h~f-y+J!A5th_lTdYqqVu2^+ z@~#E;4I*?^_UNlMVl6DuwG>$`q210A&Gn><$iUMT*xN|DpcUJz2vFnYhNBu&r*RSe zM+_#u(-k{voA6xelLfTZ;Kd4x;q7Y%UdvusS z)m62=FOmp*j~(5cE(qANgU1ojLc>O^{!xwAYTRV0RD=bsGH|#1sN7Mk2l36F6^m!I z=mR$Of06gF%iy!Ddzf2~?Vm00@K*+(t8M#tAe+1iZ^~vwXdSs6Y#ds#LeD-cOvTT? zwUIvufqmD`n7(DzFC%xYHd+^+JD~-RYOIZ`FLHMXm${GEu28|G(vynf=Uy@L=P>9< z&gP|->>@S!XPDNSKcb!(fZf=Z%-6WG9V`8UD*!2Vv`*|^Vu{Agd(`ML13Cyhz=A!r zVr@1bDt;#G0HQb=trz94!#AYz>u4j{OAq;Jl4z8geXG+4aWX#SQ+d6=4K1-`arLxf zf7%;WonO%_NZ99ES5@okFWujO@tM(nC2mRP8R z1dZ{8b345lAi_n__eD-u7CWrOR3(x~RtSSXTzf6HDuP>}x99}Vq_E%XYHc`gMB_|@Nfp#$8j2VKQ zU0byKSiTw4omu&5JFqRuC90Z=G-4cKuU%nBSn6%jcTS@n>+Pqt=C!5x$#$trM^jQB zv+51CV)hHcFU_`|STDAszTPzGq!D|WT4JXSLJqXT${K3JnD5{cGqob}#`r1K!9AZ)1$#bsD^o@9uRG71# zN$6%@BvLmCCsnBcH{Dy?ix=yIUv9N9!DS5kwrFV+A*r0}S{BquD^?QwVEcS$-a&+b zA(wi#oVC&QwdTBX;t3j0i66u{wFzA z7_0$rws)ng56 z(u8WQc)9MF$rxMqS)Udy_y`B!!s0(w_G1b93hHaK>}n+%wjxB1#0MDlq6$0A*w7&D z2wub(6l`C)zLcK5vSBH~+HPFiI%AsX^JusJhDu*{w7IrDJ5sg8L4Auf>MEi27N^1D zRie|)wY;mwEGkGVe5$6%uwhJc9LxEn)Muq3T6gB-Qevi++n=nkxi*y(L2;a`2giQa z6A?^w+o-kiJGDf3FQ^PB$@OBE9Hmv+>yDCF52@q*>ueCpz|-1AN?tuc4}Wd+<&Ze- z=UWRhN*SD@$Bazi8Z%prN<3lnU-Neejp3E-iPk!B3QrheZ)QOTqVHridD`6w*}xNY zGp}QZFKn`9d0Ovisn}OBPzN`T$HTb#w1AE>ts4fzCMsZ!UgtPrxS1HGwddBVS(G+W z*gmvyqJ?>Sx$W!CD(*t8EG0_o$TmmH&o6yMCZ~jkctoCL2_!nP_fcAL+JJ7|E&tX1 zh|r`ft+kFk3_S=UcE1I_PqG#tu!3GXGxwwNan{zJ2wBul_#{gdOWjKh!&8QTEyPnS zawNnNr#1s&06YD3OMI5fd$UrPbL|T1w+@>2l5H=7JU;Q)ieSS>f2~;MH$-}z4c@Kh z3Vz`pUUMG)hl1c5I78!3SmpJ|KZQzDx^v8!1l;?kIcKgMHo_jhUG|Gl$gMaG>q0s6 zE-M=6HX}zSkL0=Yq$m+aITkG;y>CQ$be+Tp`KU@J-6q2Rz4o~ph>Wb#$}-VZ&_+0_ z$&c))1@>x#Kgd>D+Micd)k@YwSe7^7s4#qSua!pX0_o)vI^7lGO>Y>Odk`NPXfdKuFXs2MA|qL_Ra zYZ}xImkRl}5VJ2SUg|dw(G|jA^Rt!2X~>ED%7jdlG;^dF3icO)o3*AdMSF8eznO-w~@kMZ1S+QX~n>TD?_gr9$Z z>t!ID$Yjn|+`Vd|E|hF1e0*;^&gbIAzEW89;h!Gxde+*<2{q2j8H!Tmz^%#W`_Ac!E$W zy1P!IK-jEG**ASAjjr>!qyfppdG`mxs!=XNk7>P!8jKVt&-1}mE3K)}IJW<((vqEi z3BEs+#R#+PAK+Fnxv0E^*AqPT+gvh)Fz%4~M1A9?VvaQ=Zd*{jJ?!lXgYqV<=$Rs> z&L-g44-tVlexPrl_r0qoqLv6Oxrlf|HD#xTP|l)9;8Fd@vVwk)@22;yGzMwf=Zb|o zMfQO3dUHHf$UPcfcKAc2kCW+y9TJxo7!29AKdzbzXPF-SA_55g{s?0`!m#-f^-6xd zApyfPWyiWC@!0SYa<(~#P~J)Pl!lS8f!AMf;_0)Q+~!dxd|Y&JLOLI!JF*eNF^^*L zcBkGojeCJ-fQny8w~5x%ZA@>b=tZRttM^)7mM1X^+dgKem=QS{k4j-M{*jVN*ebTl zQau|Qsm9WN5vJvBT3|3n7y?JjY}o_CzERg%e^Z#xvP0-4$P#YfY*?u}9bVSg4?o@j zc%dj_^bG5-JT7*IUO$akBD6G_iFYPRaLY59&`0JiZON`U$mR%pWfuObUyOLN!#CyKaB|HW z56f<*x4k&pa0Bl<{QKmpqv|CqAT*!W7;pNKP2uTYOYpQaHA1Iws856))oOeHmzuse zL9*eAh?WC0&wM{8$R=Aozp7IWj{}{1HXGljp>KKjzJnQyxBJ&E=~9ftxE@{q=_z@q zaeNkN2MR(9T=331Js68Mmxuu)#86>V$E5entwia^Gd9LAmBTmUK0JBd<&497H;upH z@`tfjqlO^|b&4=_xNhVBGZ-eU^ciN@A#yMX2fk?Y$UxD`D+V*KN^42`-D@7lJ<`va zvR8?ZuR5sKvQffa`=@3KF{GdZZ=b=W`fr(0_M*`01$am=i+d4&pN8HK8R{| zOx#19yAw?}-$SplLue?SaNbdq`=V=`cFU>zuua7Z_tI}0lj?f00lz9P+|TrEiu;JU zH<;UHtOG*#$+Z@}39!|n{{Yd2yjF6(`xIo$ap8J_uEd?O)E#suCfwmnB_jjJ*EkxF?xp_;}=*< zH%_WDlTGdc>5A{5wdG8k&_UanMfuCJt1e@wXRu3#pw^^NGMsi`*x9=~MOpkT=c=#6 z1fvKKjQM4NU{r21DFcH@87lt!UevbvNVyC^kYYDnJ0g0S)?W7V(KBp{gg71+l>}6k zl}z-)G2Ih>oy9b_}9*IBoVTyLd;&VF4-Z!#!6sl0GKL|dBQbSu=i zSB>53ESH?`a4_F2EgK_DLwRhkbd&yQjHx!qGfXgWPHWk#RD6SNdLz@7dM~j7r#t|a z)Lgl$x~ODDEv+#Nbk~~lv`sY;2i`otKu8wSgvXJVg-h9=hHUw-h(qi^u2JqYghml2 zg&K_#-tZwEDs|P#j~DB}!CF&hcOcG-qg9G`#R{E_emKpWam6{k;Xd>quW=L(hmj5v z*6_%Zi@Hx8WE6EfT;Jo)owf@KXSS0R(u4X{J?e#uk!R_6XtQ+jJkHVKJqU~%0+ zO~V^`R6pUYk#;zD-$PrUO*|?sPb7}>k0@}&%8*!GX`5tmXbo(dg`bzwW8XopVSPx6 zD(#k;Hgv^vCqePeq#&P{X5()JEj^YR6&OgY>lQg{4D!L!RUM!c-6`rIyE7g^(vusv zjT4r}ZHKfe?J%MD$~@ReKccw%`5Ala?PlGzP|t*ljuD1j7?*G0wpv!!I*Ay~0*nQE z&#G0@iVdHw5XCQ6XYu~&30R(@N?O}RA7u=AEs`{2U$)jeS9RE%Mu?^Q`y(iM35mo; z!j0Z@w$W7V#R@Co``Ag15$!ch_x#rtpFxoxnyh3$RkB}JLRdNcFg`({kAU!+dRCMn zGjb?D|^^b`hTHxKVyP;+CSVi<65b#;lqz7<4)ANlD;Tm=dw^lCn%^l|1%y7P4X=lAZFT_>C!<~sF<6W9ma5iAAS*@k zm2kq8*eeE$WPdvl4MkQA22D$zroNF6AMO2XdO={44E4&x^LmFPlr1RoHd1t)ca}>yT82`j?hb#1zQ&rld)kTsVx^Yt=k$*KilbBaDTN3{{|eB5=pftlkZ{ZkLN@Qtv{ z@r0*cX0836>lWCK1LHJOx(V-=y}$Us6G4xGH!Rd9n5(EcLjQ^HD;qf2Xin?We|Td5 zQ3<2CzV(2YN_h!qthv8P%tMZE6tSaJ|Bcd^)i^GdClpfCu1W?1+2lgi-7ej_hd6%m zDxy=2D4X)9^ins4LqmJ*ydrX2_K?!P2Q9Uq?tM~Bu!pzHx%2*Dd{SiLyy0T*oVQud zopgY0d%$g(XXzXi5632R`uoWuejEFqL=&IN~il`TNxX+7*(-Cw-wL-6qNRCBG*(8Cc%Ta z{_}K$g~{>mGNAq&+_^MmxUJ|#tDj^qHpBd1OWuidEqkEzZH~#aK`$UiuPe6PA^3UW zwdCjUC2*>ZJJ}0zf3lL~rk}xCyF^N$|J&6Nl>4#J3Z?VdMNSzfTw3LlI+PYu@(|@<(|6OiOdo(h`5! zQUMIayF5F-YV=~ZJ7q5__(G8$D(6IP9m-cxnNZ8SUDq`gmAw8xwypxYs^jVNUS8a8 zLR?62hu{vu9RkHIgcyMsB)A1A6ekqfqDg?_PN5V{aVJQz7Hg?MkpP7PMZVwMojmsP z|2T*I&Ut%xcXoDmc6N4mwqOynwI$A*SC5DFO3S7C`7FPw^b?li@JN+%yVmw z1?TJR-LkF{-*H`U&Y24Rx2||LF{`F%-;;UR;cFaB%IIvNpJjO4V$dvK=ETmD4c^=X z8(um|CD3mmNx1cd9s2q(kEI>ZT7j>so{|k7QH%FOTHi%X)2BG6zZ8>I<}NIHhi|dd zbkn6i^vMF}!y?z-UOp#LlzmPtCi( zvFa>;(dU3&ur3hv(Bk~or;{YN>ThFimBxPa_Q~Pcj9kk!eJ%SC6&uh0ox}KBKDxCe_WL~c6^#B92E*0{B4fRsG%@Sr42i?&BM3xW9Vb?>x8xr< zbXam1*bh+91N-wtN%(W;(N$z66D}}G6>H(>f?qL2cA#Fu&pfJr#*P@Zi*R7k)Onu@ z7iWs_(Sut>ATqn5==EL-hKl^yZdo@uU3b{U57sY*qr@)x!eprzdavin{q9b98veK! zZ(XDMi!(pk$#_MXuy9?!%1M>H^gGPFEPoihT+)^WCJ~m5tAkHFIUcg?`R9u0%HvPl zWytD=ALZ&ML}9q+O?Htzm)@P_`Abax?}BpW9#u#)dl^HmSlL2_9D{E!l|1QCAi2|< zVasGuu};#Nn_0(RMv2V5Xet!5ZnTpkhU@Ft<5+#2g1ud57@uNLfj}O|iMKl^qJ)4g!d&$aIZ)NW8FASQ(952f5JKdUPq-blL99Xw2LCVP9 z{pvLPv@gOF(4PK=PQ09d&>k^g(sKgj*KRN16g`T$R<{6eJm)iw^d{Kt-%ih#j16nY zj2(}6A-B7&PLMzU0)?q9M#D%(2oF6>x-OG$_;Zdbji5trZoEbcQmER;pRdTa9a+bsSqxLh>JPDgimemW+P;|1JbKG$#Dk)`eybqL)nj%P zD}xR7)wuZk$sxEc1dfEQ#d&8nw>XZbgrB}@XMf~NsrOD5v+txcAh@`FC%x?09JtrF zRzL_NS~%$WBa5Msyu;UU_Pi*cb9g=z=YT6+I;K$f>C@a$=J=}xn0>k*nrkdeZt;D; z7Kgklx87q+gS$5Rnw{n}O7fO)?t?CgQgBg&llX5T%(%&54)LC_Zr%EBQn+*qdRDvT zW>-YEZd6ffFZSu|yI^gC3}RF$4$%A%g4H}_FAIhE@cO=HpVJU=z_OsEH zm2E2Y{N={6vZbNVd5+a8;5e!8h{aNrXB{cAd)8X1`)< zDXw(R&PB91&tc#P!@@3k>*55KQR1NGH1A{2hstR>cJq(&h)V>17ITVUEut+z9;$$_ zVuz9lU{0q#>r(2fm;WgKh_LDG5_3PD80oYfCq^>P*frG6nYHNHLz9!m zkUX6Hz}}<3r0vd0xDn2myy~h=#&k!u5ms*fqNK7&)CttT+JyQC z#78oq&PufKcFrt>3_oGlRTtS{edc#&TZb+v8n$H!vyoVS5 zMZ>Fd`tS^46T@^AlHO*TkU!tt$>KY*I!+mMK_CKs6jgo3qliKe+eNI}L0?xCEYj#c?0s#0)Ogr4bEws89U@; zapefxvD2Sn&HCJYLh3QcgFJ8Vcfct$ugX(-^yl*E5A9v3P{!J1X}uRojEPFEOn-EP zHtdz`7{c@;1B*xoJ?qNeU+Bw1TFBla)^)GHnAwfBAtuv85hL>>B|Gplj+1odlVQz} zwrbJvUgRgJAo3mTeZ*rI$iZs-PI5pvt9Xq}Yk&FEN2N4&m&Oq8UifQIYks^GrrCSy z!uB7g+=rEVii;*}bn7R0k=2{tK$IJjspxB}gRpeS%@C;r^l$Kbsl7;Y#{oL}V50@L zVc7gl%A}-!g?B$4HO*d@LfEJJj!f(L&?)s7VR$LiuvuBD8up&<<J?s+@vY>Dyd-J(WFJq<@FB>}s07*eESHIqrPbR(s1bM;JcjY+GVYV?j^E3eBAh z_!g@~-vR40$Ww^iIa5sz5C9^rgn@L;Q1#Vt8#~+0klp z(B*E#8LkN%?QFHLXV~bRBAm8p@2}GO(9=^kv77!378e&9F8W;=%=!mKHu0?44gwYu zcNnV#>p2j7Ah$;U`PEctM2GeFWx@BGvNcMPPV#ep;f1o_F($MA2duK{#NculZT6fx z%Kjo!CoR5gv`12p{c&4yXCM3bpY6kf<(th+%19J&()UWH{IX|PdoR6{7QmS`Zs{U% zkzNApA7CFSu5T!q@?oC*cK+1QGKc$m*3L)KBil+O-z3qgB!1m%Cr#piYQP~IyVxX~ z^GCrZvQIno-~2ceDOPzMr&v!M8vHTrq137Fwe9W2`C5Fo{bnupF4e>-it4!AL(P@Z z>{`Est2Q8asqAd`0vA{o7_ffmfKyU&M|#>jh(`WA?3NeD9Og1-o|5+1kJG%+ipLL^ zxyj;?&z)VztfeSY^X7W_m*|9$ylk}<9W&*J3wT_B=XHO9Y?|=1z3QjYbzK@)gq^P6 z^OW|4p1#ZvG-(zX%|Q@&`iStK;ByTXFyZl2~FA&bZpZ95qNmkf{lK+~% zy`c;oy`~lxjPS-hJPDgs?zH9ekMivCk$Q2u@cofntQMi(Cb<=T0R_yyHV_g=rjcI3 z8Ov3^P%s3hA~l83zQqRdqXizBkPcAO1#OlGp}zyE3%YFYNo=eyD%oFkkZi64_EUbs ziFbCOpRJYPBTp@g(+QvaaI}z-Kuw?(wjv9Ev@zUX!Z+z-8hqY8Nj|gy^Je4!Iq2Em z&I|UQ4{yVH?NW z2oOuwzs`tWw(!LdW#J$kFlBmos=U5zLU~`l`4H|4XGZMz{0s~A&vAM>QC~n$-OYB# zrAYW>n|JCjN92U+_I3fyhZk%-Jz59w!3)l9ApF$N`}bKzTfY592dn%Fhi=l_ zvnb!rUP?iBNy%QqW2JLS>8csYa@Jf8kE?q?(-7I(elJ-63RT*eeOvelDU^{;HwWXCfuIK@ka$JrN1^z;u)X;rvy2;E=2+f0YG^dujV`pDv~ z#d12~M3)T<#l4?RTu0(Vi>KCw(+Tf)_a9Fuw?5GjqQNJk3p8Qf&5JwJZYY=U_{idA zxJnYcxji<&ddqaZ4G3g+IkvD?lM5ldQ8BLrj0{EO!3Mu_NUMVkiEZ z&~Egq6ncSFuTuZo-EU;9Jcyx^R-$HhlC^32cR^ZHE{D)2u6=^Y`P0%yYtFwCMtqg_ zimusyDqYeNm?ZC0(*9uw{+@91?;8hOdH;!a1dA%pO+c(r=_sgl0PEcyvbqY|HCwQtp$HXc&SH?rqo6}T|X+$QG-FKS3-F5 z%PA3bXIp7#VCvA6q*TfAI{Yc2d*w)dgPcEI|IFenrvC#;QaiDB%!)Q*;uA|XF*hGc zYL88GNXS)qs^`}w1=GDw4`CtCA;pXzg=pP4ov`N){oHu@T}>it)sL=Z0NAE=y+=b-O@deZPwQG+^p z<@P#WfOYK+@?3RyrCuVewne2X^Kp#V|2ExFw2#>P!s4v;W6}vdU9uys>P9EhM}$7N zxN8ag5n+V}k-sRM&VFeLF%%XRRJPLeBr zRYx3-#P*Dyy}ymEt0uo>UYmrXbsz~!&GNGs> zkIT>uvF>Z!Oy;{t8mn1ql;exi~-?5(BNUoZ&V{lZQltZ06 zkKaNLr*k@C=1*sTl~?t%ZE(%K=K&OrOb@jfNJ zC{zIAihi(^)m*X2qa1{9?pGKnnVD^G>!o3#tS1p}dNpgg^cUsZ*p|^UIf-ymr+Ib? zoxR^%+_Yib4#G9%i;Yv#uQ{O|bcc&-B^=+hVFM+-y}d2(T{Y%P2pvk)$dMDC&a4zq z4rYpNFYLYqRFsUQeikQCV*+uG(l$C+t62yQ1X3<814v!QH77 zNce51>@+dNr$EML?2Xa18q8?IQsocK`6OpJP#UXg*vr%N6aMv2hov%dXm%Mqlw!gH zaij;HGibwQ5Sr?*z&Ytf1$Df&;|R6uk>Bss{RC^b;H`vqvAB`Tn*E9MN$yLq9)?OU)vXz>yBGPUK7nv%{2D5ENg?6#7 z20Q1cDQA8qRZvqL=p2hD0J&JgX@MTNM$W?RAoe_qbJea)&j)tr+aZv3r{$?dh>eIO<9^El9Q#J8bz4IpY1`PEUO$JN3TX`W_RQI?MV5 zZ8~o4n-Fo{jYAZX*_P#d?5b53gSGzniNuC*Y9kjY<&oGxw~jSTTXsG%x|G)CFA2jQ zH>sr%o&u+z!D`=IYI%^--v><)uEm_6aORE+iNw=(26p~F@fRFZH`Kq>0b;8*?aa7M zl|GG+qS1*_X=#zMBNOzE{?AP7vzKqqqn>T1z2LeDTlr2bB~?3S9Y?Y6qs2p;$mxVD z%Vi_f5Diw+mWw`EWR!}ANb>!y_D@n&_SnRGYJE5tVLef!wzy}qZKp-^uY?oZ{ymsR zLRE3b-PYeA^2?@w+e2YtgSW6B)B*=h@0O}4rVbsTn8-Gu&LV7bA$5-;Tch1=-L)S% zop4b1h(1<3!DzqDUig|PH;k45?F-IDxG592cy!YNvzUWu_ZkDW5~ma1{@rP&QfnP( z4SlJainK{xZK~HkOMeoI9qMMHx$hUQjLSD$!i2#xN^cFoNvR4{bR=;mgN8 z>R8o_r@^AHTWZ=LO4j2Z$U2O(5)O%;HA;$rK5zH_h-HylwQZF#T@{Y?v;B-?lY);$ z&>2@L$qU^$s{8^J{r%g%C6%K0o{I5yr|Y&PU4*+T{U)|wHFICJdxJ4T<})P|)~R|V z%W9z72|rJMooGDLPJD5t(-BjYcaGOE~t)2U{Yj ziU`?ewiVfH;ykq!PA8mM$h*H%QR}sFE}A+e_Ys+gmGlfs@6P!N-+hSu3n8-#2+5mb z@zLOL*6Sy1@MF3El=_iwFD6XE!bByq{-U+LX*FF{WbUxwU4ti>g(A2R!f#$pcqfMR zLM4>$7n>}V@=^2;w<_-`OK85)N09eYDa6WIQKMRtEqLmNa~R*z#zIY zKUkhA1^&4mQlKstJJsu;S<~%Bh3yu(g-^ZH`&P~N*7i7yb&q4+v`8kFaQ35nQDWj) zb5)`3hFGhU_3yr?{*e6oxDy@U?K{kF>arz%%;GaN(5ncfyBVytZWGob;QcCewVt(& zJ0|1=u9a|jlXlO~0LF;Y) z$nkQlpFylcclg1Ops|TU>_x@%SRSY-0)`U5X7c$U=n%qK;C2)-|)A z)}M(aEU`arGr3yy{GQ^Mi?O%?ego!8WB!Qn-|yZXBOfDIQs;&_K#SsZ!usFu8X}4w z!D8^>b+e~%zK-o(nu1Ac2n%gb|HVpVMS}%c-P{jRm<8(pd!j|2dCRrO)q2mRy~M^M3%z?yC^!t0u4@Dw_tKIfcvWIk=8SJ(mHZh!s*$k?#uFX>zhj&k~;Mg3zdE^ zzY_hf8Vh$egiQU^K+$Fun5Xvp5TE*RKhi9rGiXes&*Y-ToW^UE^hY`995sLK%-^5O zF^g8={jj?@EWadNTFSmG+4WTx_Q$Le`z2<_c&3=} z+tE=_(k4qCF=1+~qqc;T2yeE}pD5;eTkv@3SmfHtNrWE1{j;y2P`p@Xu~MJH6+^Q(dU|rhf4;RrRG7O`s&LgbAIJr;&q&$o3T5j=6J; z1Jy$LFS!w}rxXG0ZKlG1qAt@PeEOZt7Ir2k$u zy+17I_E2~@q5O{}V7J6^0fbvC;SMnu;1HCa9yee>iVQA+tuVb2gtfz5BXky6tMNmG zb-k?`cP3%C9$t8S18o&Lr>0rpbBN($2nTHaCP&f{IU?3sd(TOPsr%A{W%peegYL`b zB*K`*#SvVVdbaY2SV#9aoJ2Ts=p%7)tW8y2BzjFm$Aoh#;o8ML@9P~S+=DC*1_ix1 z;@bc@<>#4U&V6GGLu4>#C0uhi6%X+_S|SW#=PvHDv>=0BZ=a_&fin;$jUKmM%9t)h z%SXV5P%Y*1iAC&0;}A<@Es=8(mR>deU%hGm(L+ma;SwQ;vk!yza(JuQ7yqSPR*_%p%=4F@AGhc|j{+oV{#pwyJa zQSm9sIw9)vtirBacckct*}w-KJO*-6pNk<}apihX;!s_`0qiL!JC6nz;gTJzFg=rC z|K|q5Ry(APE#kg`;dO8@37!8f=OT>snEzUm=IDw2jrN>GIQv92!n2k@yY+6oJsJk4 zD#5RtY#1&lUc6lFB(_eAb#}N|6F~Q9H2#t{=GT9LUi!}%v^db(~6t*}S=w5oSRaX+m zx?-z`#Wt(LA5~0FA~Pe_VwiHK1TNd~NiKyp6>L?#LT^6iR-i`J^<@o82QjFV2?rbr zdt+5mf$_2F(TNFitf)nJ&MqNxhMA-)7@l*D-Mp$d=R@F;lTunLehD!VmZe6O72)8z9n8(}h)*;5|^6zC(BV*ophKQVE z7}l!j)!P^T+}cdi#OVc_-xrt~!a`;85be8!rKt%0aezgdG^%)%n)S<8$?0v-dE&%m z2x|&Xf1~BYz-fF!KQQtAsicANHaWhxAwn*_%hY&h^TvAAp z7rl^tTZ^%f-0y7hBnOsq7z$3}aR#`m(oumHyH=Sa{awIXb@H4zVe&1VCvrj==Y>Ju zmnk7^nRdLtoEkzyEslnXtyh)li={%IK$HGy&PCXD_l5&H5B;NtC&4dqWikGgK96mLBH-AAmvdJ80tNe*ZxL|JZqh0v>bu)$duo)m;U1U4I`$u|dbmBX@ zgLu_we^t@}&tZ_J&d4a3aMYe&;JP_OGClJvm_TY$^v>@QB7|HG85W4N|8z{P>iBzK zy$jysErCV9I(Js9SEKr;<}{oJa))zk38#1Pox+Fqd!XcbX9QXecUoG_`D=Hdyne80M(7w;ceFxAmqOnfFRp3tJDG;Q{Kf>ElD zaBzw)EN7iN!(v^svaeM!S@Z+fQ#n83zOuL{jcuM z!2;{v-hD%Q>C!tNUK>WqMe!8H+e?v!ix|(+QV#xp;+kEvtyUB5?Jn zE5Xf2N|{8baY(uwXm%Fu{LKzpch-)CqoX!E>QwuuC8W!dcz{bL?00W_S1G`H%^zE1 z!cku;{3~&+w=7<7*@tFGufoL>b{=wmIyv*J2t9vZ>sWhDU22R@Iaimeuj`jOOs;%z zt5ok2!r_0E{2*C63+>h%If<~UTOLkx5VsF_AxWjVOP|rWor5I*q?mL$U#Q7PWAmF? zIZ{~b%Y_o&dUt54Y^~m!hs~khf;pYAUBv(?V8l#E|3vJs>C=%5e?!=|T%o~IF`*2L zI8rvgutDe4OWinA)`7lq6#d(RW8_*PF(hoXDb!z*2aXliE^`v$;h(nVN@fyyeyJm* z)wG^JA>7vH>S=0w6HVpg!71~CWt}7h{&5AoMw|e>Uc!vxn@WBvTr3ZOptR?7!UdN) zH2ox_0f{N`33A=>f~zMSHP&mY?3KZv_e#eNZ-26uuNjJ7UA*CQ*tsluHzPVzNzW~e z5w3RaS@Y}epL$4CZUy?(-s#gRq@j{OGYI*8xoL!U2bxPeMdY2sbl8|lCw%cHJ%+qr zP!8vC0yOIaOpp{#C%pexIlRcBD-TL<+YqFW<#fVw^=)oQ6NU2oCP<-EotOXRRKugu z-xt&{>pYhIWb%aS>H33~ZzQTbQTj&X$$Oq>!HK-=wmU=J$ zlti{2VwPLa!Ugv$ejEEjTx@NwC$#3c@Y9|vCH(rH=L9-pixNAVUBuHS@p$H;Njx6} zO6M;L=lt3W0WMmA{D@}eKy4u>5svHIEmm}DiSlRFiE}rY>n#txUn{*b+d4t9mTYI1 z0e8r57?tcaNM?Io57{EQL_&`N5C4%AAFPFKnBJU3IP31Yv7*yFSUuTIp&7C|nq|E8 zp-5XlJDg%Pp*0yD;JSYDh1pG;#d!(m*nKmPij`3y7vYx?>04gQ(lT3_HMyiwoAyi6 z>FJWApx;kRtI)95N9R46qkrYO}Zd<21j$-phwl|J#g2`+p_50&CJHm zXw&UWJv4^wZ2zPrRwHe>c*1XX-1Vo?uXnSPZ%m4=x+n4%gtNMJ$K^kgrn+CCZq*LI z`RAlW9t1?&;5w#t~Z&}zn6#J<*M z8LWlW`_HvBTpT=8@lfC z`!r;N1|%dW73_UPaW#Zpo0lFf9sGJR{TswNipLm7dP74@I6Cxx*Cg7j>SyRw`!k!N zbZ9RRohonRZboUxZFawr45x7#5Ni#Tu6B5*wPOy*2_vta*-Z{Vb)|IAw~4d0<&I)p z3+xA|Iy2|nOJhE@Ox$dTNlzUtN!tCX)~@jo=j+7T8+@ScerxJ11y*lzcq8nY{KzaJ zY`6RlI7mbVfqBd**;-V$po-jKp{y@gqxblHiYr&cKG zX#E;ZLT9_jbCrayxUMkqBu>Nhy=cPe|BEL1)PcnYJ8whd$IA^@q{*GHSFX6Ol{FJj zL!E|b>sdx!GRgJV&lViipVJQSrX4ob7uq3{lNQfp6YecpYK3@q*wjEYI%;y(C?+no zh;a4X8dHU7H8w5tm*F1ij2vWb#_5D#)bqB8Dl1HF4cA?BM(j0zt4># z^cngJF`ieMT4;N?7($!z4tTtI8-5+hzY_ZQsgGN;OH2qR78&O(4i3L$C!Xe*Yz=G9 zD-S0^lkdStbBD&+i~1YU0(UNi@X6L4-Don!+IXu8OU~73!6PP!u+X6^e{&_PP4;5j zW|O-{!Gehcgw3n}a8Raii;1%nJ>T}>u&X}&5#g=UnST-o>jw>ujf#m%l+iO^b2Wrx zUf16vJUq}fIwN~0Ky+SmI^mQ{+i{KXFq#pXWx{>1O(sVzlxrY-pE_p>t>xNii1e!y zM;JS#s2BZOPmCLg0=IC1gd_ca3nvSyuIMlfvaHs1DsTRLYEpzYm&+oo9(#11LP5QF z^qfk;_Mf^JmJ@htmdQ~xKWOsOZgYi%OTVB0uhPQP>%qtkoKBe4co;69QwzaJd*751 z`h3!rDIi?8d_|TlA!3io?bB&<)x~hn*>j5Q?ksdyU|Ran1iXGl=U?eXd+Id8^GUtG zB)-%Yw+BNgf=CLpnHECx%&ik8bMmqvFS(qRut(Eb%}AnkGCj0NP9hwV{rd|N>lWHK zTo&Q^T0<{d1eh)zsNldH{ToS$&$VTYDdDd}Bu>xjwQU0rQ{{X9U-yAL;OYISoF5wV7x;@_d~ z8l~g#ksH@W*l5H|{rq&@AUL)oQ`u%EzcX=^@aAH3IVowmaTo?2<3O)kg5RdMPp$Mi zi8tVadr`B@Pk3^EDRJ*1c6)V7pX|aY+{?ui=0!M_Qd**qclWMd?6pw^;LPi&^3-+p zM7{4&$Q>?(aQm&_n9~?TcH%}XdZIqJlCXpGpEo|y7#KS;HD#z=K6x;ugo{@X-b5Oz zZqTq~9IuX+Y(LHQ5dONZ$z{2?pvL&87D(Vx{)TYHtBc=Q#mG*S-2gEg%(M_bsQcn? zDeHGvp<5b}cKw(ZXRH0ng%AdB-xy7&I(B((3;6;IaspzFVN^4mc)8OPT}t z8^Viwd|Y*j4@`?qjE&}1BY$uPIJdG7B2dz@|KEtWdT5HA8S&3=1(#Fsn_44UU>? zAq{ov8i=PfCst;v2B3ZH3^>m7ftjWA~+jQt!-7#wg0# zg~_Z07fl$}VHe__K}Qxz9+niB5SthyPdl3V8^Q{YTIzRd>I#Qc4CA+4Jz#t;)Fw6KlqgQN%VnB{{i3;vR4bgr2*d2g%Q%?p^)RVqK31aY=-4 zJV*AI9ejHTPVubZB*F$QFBX%miiX>2SZX2%(RAQ%2&?uQJxum5DTH9Uz7(0l%I$Ba zgz(^iiCyJ%K{kYcT5RlKos`4;4Pi*JVBU4l+i!CA<(r;8xi-RpYvV5HibFVVF}Y}} zC*|GFT>Y9>U6HsBN%y#1!s}0_HxGC!Rdt0#T}884K|lQVsg{|;Q9z1 zHYc`FCfuj60Nhn|7uP96gzqpl5e;LYtjlvwLd%0Kb>z@h5ksVLo=l83D-9J zN{?_Pjg?>=6OD{cNtMsGoMqYwZ|(GMAbU_ZYL=&9g}#Q<31cQdJ}tX1G7{Z)kdp}W zJKldFv%)NM3LKUU%_f;XiU}c1o%`iu#Uik3Hnn4XidB9jJ8yR)1aS{nLg@Z#VtH|K zi>ZZsI2TGdc;p!I;{_OmI>Ys;A}bbaYgOA-D_SStN}i)wF$g0~)hzc4cl<{VoX9Ou z4`aA^!s=a~|4oK=3vC|%N|;#c4esTWSuyuJ*msB0P@rl-*6A`JM(NC-cEEa4_4lLZ z;f-Xvw%+8csZyReKkpx_mU9%j{m`3gTjDR7K1zL+*dK?MRo)ff)@7Y_R=0?EyU~`f znQFrHl=oxA#6wUhDg#eV?ojSiTY_S7?Rgmc!qq1Ey}et++IhYP#oez##(bHC-ggug z2H^zT74A4fr!#-`(b*fAken9Fle8)rTdEXmD_1jju^^DkMb+KCY?2G!LBNtmo#jt( z%Lt#8xqFzHQcKL)2wUMpg?M+v)xuukj#a1tJ>6Sh_@;xfwn5{5B*Hjbt4$^sJ#7d{ z+ZsE48C6$QNQPt~G$5k2OZ>>^zp%f~`G8ZxznJs<5GsPxmB z6((o*Oim}fblF~*E@E+^+jytbQG7*CCNyodTPTM}>>vygwUgFY*fL36{KZmrQ5_q5 z5mp+0T6MB{_H;^HYA+5Q*S7I8EOxh>CQXrw3rP;2ocpD@9|^alO~*rdbX1AH5w5ju zoU~tMWjy!poA(MHBwgce9r<-Bvw6o5r6KKD~3oVyy-1?jbn-p!&ipgye;ai@hWjE~0la zxT*$me!_`g-smXzKf;TedC48i>4e{G{kn#D<|kXJlj^*v7`%|P`5VIMxvjobIMKc+ zb^%6nI^lvlr4WtD%Bi}cNFT-NgtKdm$HA^imRh30WNePca}r^6gMXjPZVmeqo91&S ze|84$PGWSQPbW)+{?Xz|7TI^}C*jnM+L#$J6*}t`1&kP4u&p?kYa=|k{7?z;>`R>6 zQ)%e%p;=MNRo9o_n!3kX2rFG)7fFeY4TsK-{*5p?)&nm(S^ng*(9NBGoSiUW(m|Z< zChspucN85=*p?<|9+?P)>jp19Ls3DnPx=VgVTx3=!IAdUxEIjhS$;%#=HG$#Vo7V< zvH0|nYb6``P~<+8(rEVYZ$B@k!C912hQ~kQ!+Y&o7)z<5>)gp^M73Y)j|eG!N%K`e zXs$c!ablqzlSx>q`3N6j^0nz=kS*{1V-Q33ow@3)e?D^;xmn^t5WE;n+}vZmn;Li#>5rCe((bIjKi@)>qwWBc27L*3j}cK?XnQ z#^LX_iS3bK$hOCDyjQ$|!C#l_Biy_S&(>mu<7nX{9NP{p19er0(+Pig(WQxW%%jWf zMP3=GZRZnL`5ap>{*rK7@NgWXwYDrZ*v7+fzAQVV`9N#ec=#2B4j`RILPY32b59+S z<3sIugB_f0jG&GKES!i)>cJJo zaQP#wSgb|#ceAlITti9zVsc5**qxgb7>$9&W>Ex}N7!fO^I>A1qs(ob$`x9*!0$^OC-n*aGC+LJJ}n=MZ$~DK9giC!dz{fMdlV9-8ob(imjsg z{3T)jFI|QFGPfkY{P+O7Dy=!4u>YA(gJilc_v3%Up#MsXL};_J7!9qs~<|ie(A|& z5awUbJ}xeP07vvrUH&g7(jPdT(EitZd*w(7Um5G^-h-0}g9rJEqIfV#geT$<(%tel znqPVX-^1w6-w`J5d?}uhA2GADsfY-BZ!TuIWPI(fQ6m&h03GKb4irb{t7GlRkOO}x zAKh?=x=GU_^~x+G_H}f@t4>8b z2aqOhC?ZS{ig%keKXK-zS-uNStz93z%Z?b)%CM#O?~oJs<-WJx1xedt{S6zmj{nZc zr$HSqmc>Gssw98^>!Es*^SWl(>jA?whuKE>+t%e3t-~$AaD~U?%_tvI0yGp5Nr1f~m-Y`(sdl;rtO{hl!3B`ly{@5}7`u)HoWg4QK+hh}q@A z@#dV1@NKth8M5WuUL*2oo+;kPaE1M4ySZ*UjiQYf7i>6`7E#spUuBe{d|Q!=`NrUP zx;w8`BRK)&KfuYJ+q5^Z`tC{u7=eO^S|Ifp z`M$rK)W7Pqc=^u@L!?O=@zCrV5QQf=rJqyPmI)uuAru+Zxvqrrzs1Kd$WCDRPkLbBgBoXGHwEU$A_KG0PW^T4Nj)oypW3kC%9epk$wT%ZKGf)>f zVei7L>DB3tOMPMXG93EP-2Cto>7F)*#X`j+<8V6!hL@hnf8RA$8>(uGA6+d-4u$Zy z=+#g=$j%0C0^z=8FHJPfbv5dd+*SMZQKk!A&j1@A!vt#c<|NNFu&I0ur-#1j*u;hU zwqZy@T4Z8uvh@uy)!ZxcXLnptgVGbBp)fy^JmHN}`C8%ED`n)6$?%Hv75UIwx}i^| z;Oi=-@O)0NO=p8}+Le5b%jixvjl_)OSJ|3SwP!}$su#qnj)rC3xu-V=>DDz(d2C+q zV&)L~o-00-a@7)=2fX6jJaJ6pXAih^2J%OQZ7v=Tm(rg5vEaOrTFBLZS}h>C?xHtg zp(jo`-F1gmLMvX34`_rWsS#>$p@h|n3WR|un9Bo)#>N+%%Tvv?_RAx-%BoZCV1cD` z0fhh69#n^v5-!5H**Ir~Eee7Z>V|3q{)%wwiS>SZZwdEJvBtYwe_j5ehaxx|LUBhX z)+`4I;idHM>lCwQ^9GI0nm8_>uwS(`xY|J4I)8O+F+(5!nKm9*g9>aws9#URaNa(2 z%Mz&#Fg^pc3tTAS&T~`Oe$uxha~;%=st&JQ6*$`>6}yADunKx4m9rCm9A*1E8|TF_ zTV2aR!|QQ6Vd1@Ay`=Ez!nvX>^tmdW$0G;qqvAUmv{%=$?ee5?gDpf!*6QS4t6hFNb*y+@SS&PydG0+$(`OI zl_l$>9k?3}Okq+8=MTPsV|#uDmNn*VKf?jNV4IMy#l#L+ti$$l6?t2*#7WtVoAPSU zzBlj1Y=9+>t|9W)#X7iG;yMUFoXiy4bhekR!Gy1gyH)gcx9xo zFK0Mm@vZi0yO-m~(TbphrZVzuSWP^Ah3*g$`B>|@=fjfiz@!nD`m5S$>WyaN&JI6T zA1aSh%oRpRHHVJy5E*}JaI8AQG0~L^A++4snkIV#y3`^rosS9BUfD^~3AePHf{?k& zI)u+e_2)7OpSpYGSu1i84cZnMkm_3K?;~qFNF$?Q&1Nsg@4v<#wQspN!VV`F!3kZk z&RAX_3Fl^wTCW%ax;Ywl9oBLi{)q7FBF?|a`BN9d$HifDuH$sVAfL-kWVhmP^N}3-C^X< zlEpeT`fBTGxD#K}R6R5`o|-qa2j-#K-!P6(Jo(s*ZT}FPa@ssDpD?W7x+*jWHINfu zc}&%Y74oA7)dGzwjg>`yd7C1J&MY;mDYoZ{Z%?m7&(Gva2z!j1;4VjQh7FWN6HX%R zG4I1;x!`gpU$|?ynlQ|jwyY(!<2Or87G{0^mXDo2w#U< zaDI+;od?Y&wxZ!WOgR1dBf@K~*L?g`TicD0#b{0@^l#JOUg=NW6Y+j`6x)l7`Ab5( z;Wk|gym>BuQ8CinN=s65tPnmOHT^ruDZBspTr^p8(SPnlgf?$zqPtaLOsm8CY-HW$ zl1m$(!fUM(7QEq~a?-phu*2=d>~tuxU0fsK>&H_{f4;69|M|M|-yz3bBw5+tp##-{ z{{BMyE>au79pEC?-Pd@Dq&ib(7MtH%vWNzTNO83B)H0X|!pj+W&{!7`y~ECu4Xt)) zc;Y_1aX{t}+1LR?6H-(DH~Q0z#TE6XVKY&ArypWFlUGh9V(Qyn17%<9l)`DHiSo~2 zY0qLx2*>_Y8gVxZbYDdE&wMPmTvy(buA>KMV*IoOv+O#;#XXiamNcRb4x;1!7&p!A zDANgVznX|uuvK~dSq#(iFs_-fU+{nLq(P;x!gJ%2*^Z?n#v~tv)ecS5-Pr6E!`$tn z8i$7UUa74=NS-^GZR8o$Z=LWY`Tla4l!DnDeF(yzTo%7729YZnM5>XPoqNV#nXKOx zjw@`qDCh8p17g+Dg#q1hGHYw>|04lC{=C#l@wt^Nj@75SeCt(ZO%I}$ErPq1AR(&J z()|1h99yDFz@2i2WzeSPEf73_^eHR^f5VPo@AFaHWG;PCSl}{n67M%+%<6M7xwVM9 zgoC!`OlC18BM$oCPGloqq9K;-y{g9+%XzfG5#u6O^op|c(iODY1Lk*4>9HehNtB~~ z15X^xRQ30mvYuy+dfwZxaBO;Xx1TijK)0K?VTXNJFI!11;p%EH9!o+}e~&4meTBJ= z8bY|P&(Q}IQn-r9T5ItYjm|{#G~b(BOSs8~2|LJ0raxV(W3 z+!C_Y;w}1Ck7bpn4ywx=hjAhLM@81*{)wvc&fQ#6TyA*ll?}a z&L0tWd?V&H!^v&XQ*Im!~KU1#gMu--3;;Ix?In@ zChs-Os*lMdI2kCp_`PeS{FE%N0luF(h@_x(*H@4|8k7X3mBU zhjG`P4!(!GU?=ct)p#evdT-6yr>U@uP>imEq3WtKK-$wcQy7CiMY_)ZzZ}k`HzWthD^y6toy5ap;d-iI(;T*ZkW{ zO^)li7P*;S{1c;w$^(McnG(XHN9L7~9h&a~Gvr{;IA437UqraOxutmOjJ7r69E6kG zEFMHuHV{sQak^m~ClRhmDvT|gRora}ol6FZ6U0+ck59Axv@3ooD)C z61{XU0}GQbG(0YKiq475?r^R(=ZXnqHSec#j23XpUfgxUfr)DT5n+ecJ0OGw91!nZ za8-B#rxWI_`27nhGc$YPwBadEB5YbQQ~bEvRE?y~MKpvBWbo8gxo$Zlj~DCJ4{|em zXkT-7!bxuT8W!8GiN0%bMO7_Pb?KDd!b93 zaXMkb_l-FAs(x)hJPl@A!(oVJ7r`G9?%efU5AV>@AS|h?qW96=eVi2>ja=jUW6jo- za}j=hwt8v0B9Gnn@kmb^fKw7`)y0=rTT3AZ;1C&(-Si0~uth>^EE@ELA5W&>eRRr? z@}cHOgDTbh>3_d1!gkT|E1l{_>DU$S!ubhbq|_@$!2$I8-9)1Sm}XU_vSN0#R55Q9 zHilHH+EqWCO-F0$h)qLqLroRWZ@kx>mPvDlAxT{`IgjdcL21jZ_9|$kUiDj+~U8yk30y4bVqS_7$ivb9``)b!$v9Jg~}hv zydXTS4LYin-#Y{4tF5*xan}1&{=oR?n1aYQs__=Jf5d&A0e-1`L!}khL3nrH=3`bG z9mM#NSbC{6xct<1tdfrYwiS_mFn6mTy}tGsk4h5zpFk81JRW^?6e91DJm~ULaRhjv zw&8~}Vap|TiP8TX*`?&lM?cDo-8zS-M!}+2jqSHvn+AU3fao|B(m07*N0>DI#=lg0 zUEcw6nWaj`=*nC1^t@Hn9;Jh{nw*(1W>WfYMN~t^KvW|+op8sJMN5>*2T}Lc<8;E1 zT3_lR_7M)E4@S`(P9n6Qc^R+vjy2a=6dCL0uC~as)=6|)L1(~*V?n1*mpu;KHL&)C zqc~3^LzSk}J?4#7$XVYTKuoyU6Ps65ciON4|5Nv}gSe0Uso5R+LR?g)J^yD}u(V(! zV)2S+!x)pFVS3B|DFp|X>GllLokhoiCV9J^ERKjj;xutD*3?XdM&oe5YDksIEhg@r z!Eo10eeV))Zx(DxCT{~dw_GpZl~soKH#rz=w*$kP z{HiDU7I1MC3kP9O+{3&$(9~Qsj7L7z$Sv_rDO|86(^+rffim%ahN*D>twAO$2MUY3 zgK%F&-AB$lnzT~3r9iQ&ZAtSS2kV3)_@Z=A7rlR`NxDR2l&QU6)c>QB=7=1Qqkv3a zelZEd^?d3ue^Y0n9hs1l>cE(k^km+MU(T&2{P4PeIl3pJe^uB&I*Q|zwBc_Et2Np; zPp-@K_TO=ax3Dj#6UMBLxg*<`z##(F_U#zI6jALdtc;#}!u}WsZ6oITye%5IvHRa&N(ae-sC4--TR}+7`1k(g@=gt@|MT21nO=l+@0k5Jru|RjuZj&~kGSuP$>H zd^4(&o7LprB00!p`f7ZXyCRKG7O0kd)%}i%G}lxW<5uGJg+oj)VTp~E^l)~1lB1|c zm3+nNghLX34v_XVvO0>))i~N*fzt_X2cNnkh!~wlot?XC#~CyIEIEg$n&~vg~3J)dgvRDJFmY zY1u&#gO)cZ3e!=PxGf3ZsFK65i46%5jfR;TiiHzQGHCs5JG@Q3vJc*B7-y<2dQUXT zmEp`?awMcZk>eFagYK?*Z|g};R~~P22u_UcIABo0O~GUj zSq5SG%)$uI4AvovD{cx#7u*%Ck1}W!5>8vNPDG`et1g;kvS0Lj42~wDag<0nf9RJN zB;OiNfIBVU7MAg0&P@2`;xGg(BlW8jNwtXgEqootp9M8~I`3&|^q~8>hmx#HL%2J0@U!nW->Z_E z)UoKUrTb$1wU10K;e5yIHWU`Ss#r19q=|!9`>^v*o%#B@tQ%qFt+)GOriSp)tuMtr z2ORqhZEX`GUXNhej|QV$bADJQ+mJQFBp-LC$*=0av+(K)@dr{WBYX6~*N>jueIvhq zm#BQbWo)a?QlxZov!7&=FX-+@NqgHL$D>kKPKSMIlD7d!m3*D?Gt{qDRF)mY5f0S^ zsgl+w)0!Tr56qeHdiU(|ujt8$VfNIQ(&3s)ZJ~9G9^!;=gGOSs{LCrdy6SrUi=YAb>& z;bAG&`u@9C{5dgklu16OMsve|lWya@H4kZ5xLcT{Z;8z{A7dcWGcjlmpKwu^nIq0$ z-l)tcgU6WM^hs;%7))9^f#vLQI!iUNchAQ0Dm~o)sB_pstpKs2wh>)x}+=6Lt$&5icKzL8pi6%99qAC4!IP#>6;G$eWMA_g3j%jFaZaeL~p(!5@y2 zNIgCO9!%~l%re3**T=%EK#!K_>5=y^@g3lF!V|fdx>?JYtGNOA`CM)c&iz}nxg0Ue zeVr>1q3csFW93fcc9&gzh~ZfCFAq+dlx*+s#yGn-VaX(X-vpsvoo%WvItrK3w!?TV zLDdy;AAX3T#Vdj@{EYOJfjF;_ci(JhIBRye)1dRx< zrZlF6aQ>B?cXCyx7ZQ9I{TEsuB25b^5(~oo5g*|Zrlniz9lX7vuEk~-KNqExA4KIR zaaO|n-Dj1Qjut9EBz|-%-giqMICPl4K8)or3CC3(w(1klg5yUkuYst%S+{-iV1?pw zx8c54iS5$lSS7y2PaSmn=g+S1G#XW@u4w$Lxt@AmQZ2yQ`yY)yXkl<|_g*$x%q0Xe-s9mAN1K#yc$;< z9#Xor?ETMtlLOxlUMkCnv>3zSIw$6qQ{?*iKsX82MbpaB6~y*SxV_Rp#9Ty*ZMolg z)Dr1G`4y?D^j**|=(}m$G(zv9xg2LtGWiz2HPZ@dH(Foih;Mq@nBO?96w z5(cgD(Tn-@CY1Rkdm@O&Ye%k^aP}8#_y(+A_J7p*(VR{=z4#pj$Dqe$ax3BfM*j`i zrF+ilgkQg1zd=4~QjiYKvH>x1)YVq~13vTQG|<12IYi5ImIIJ5ultb+a%qD6#kILy zG@<>^t8mPi6y3Xu@YNT&3oB%EMYFU*8sGyb8}kZz!9Qam{9$?XO)iF;N3T0w6hjU` z_l7Mpx%dxG;D}jqTnFKxtRH97l-3|HDmuDA1>Enk=#_z$zb9;2>$=3O`@ z8b@G$pgKf@N!V6Wr^G4`>tQbo<%{-nG2@iwstNPz-|r+>z&iDVmcT?&C2B#E!&RAe z@f>6g4#pQeO3@AN-Zrictoz;Io3HBJRe5yC@zNZThERvHFL(HQ`G!@!snzY`CDW_ zrqwy@cEZ^8QYb*^Fb?ISc3tmD(E}7Ff&aF`Jp<7_R8EzseJX(@r=>wz?(!&l|5Fpi z-g)5EaHgH`yLS`*Qi}dK4qe-w(+RITO--hu6k(XUmqixS*T3O@X-uxVYVH5Pp|a9m z^r@{#{u)t(26DlKO9qZBrwh7xFW^-j&q;(4$4gpdQubH`H&W$$V};9abyh9PM6`%V z&P4d|$zLM%8<=VpCqf&jWA4Khr%4J6X3qu-XrW3XNO*D2_OVoExacz(Jgvz|gb^)| zO_m$q)bk+;$qDK4LsN#O%BdoTza)(R7urf6co`X}Uo|Z2J6zxhaJu;1oQ3+^aaO`f zD=fh>Yw$Q^t;$J+x%Yfgc>?rV@s>=C51*w{$zA)s z?%3=NZbTZ&!q+A$NnZmynf-$RFck#cI9*L)^mKGvA!QyW{y_>>h5&n1TMTn>} z(9*+j;kBN<+XcD4N5S5rLMH^tr)iW8Hc^`g83LUii_90#&SIiQPB(FVAOdcyI`a0si#x@=&US@G$9PLe z?EzOx=)OF0uhW$9oidY?wmtAF#vbqx3eDEc_ z_*_f1tdN>DV7G)1vGC=(1zaBCqYv9~TIn#Xm(VyIzROC3Jgbvbx`%_kG|Y5Xq>S`o zZ>cIY-#*>DoCLLnDC>U1M;_iw=1K^)h`=jSWFxvkWYvji{Vu;&lGUlbEk5FI4Bm@t z&=DT){+ypMxK`Zv;$w_ufJkWrhA!kJ!k`7G>nUCJv~NLIP3MmY*Q{MIlDet|$zO=1 zZw#jsPD~3;Al|e-CV3#t9DH}FnA6QN&|o-rU(=@{opQsDXMc--R(@~| zlf66&s4hF+^p6k|2f#sjcL>hQZHl8vlOyqRJZa3}@lZrC03+QRhNra{%=Y09`$o>{T z*{`Zvs$C}hFI_Dm=vg%D9hI+xhCMB3ZLg20d?k(@L@HlD_I>h$^`nxq5|yu&;tUINhfKNgm!udl&zrUNd6BiRP(>$JmhZ{Ry zN4h$R9T-0_TA9hWrC7==>R_=q7+RtG&;BG1^|GWI7TL=WZrm=aw6nBbG}OmKY%A&r z2TU7_+}I&?P^wI58>xx)&Tt*)!#YUy;7mJM`-*YQ8qWou>9_eYRgz>_Xj~t#xjFe2 ztBHu#c+dGv1h(o_on2ympKL|bkb3itk}}$pc|({}vG+4Y0fwIVY$>$rWv%@pwXY@J za2)b{-KM1m0j)EtwjzdC^k6=`;6= zj(F=@9oJcteorH%*hgIWBAO?mEUu8S#a|`Uq|FyP#1bl&UqC3oxtvaTVZikr(m{{% zVIch)<7F_n_AI;GM@}lPXX645E3bY2OZ@(yA?KJC_EU8ekMjdu6=B&~YfWUi4Ky@x zxx;rytbJb8H*KKqQM=6f2?UYT#XbBJ>T0yyQ zh4S{M4@g0+u37I^fyDu5Jy{%gTjSBvxvj8|t>Jyn)Cew>uwIGbF4CpKxKmIhb;y1YswaO$ z7;x@VfAMFu)j-`Lq>A20aEh&;RdY&}ORTv8$43>W&zD=|Hj9I!xEcrtQXR-WtNU0H zBRh(P6ASSaLzS7mt8A~34-;=xExe~wrnvZ34uOqy6UvJl+6BeQJAu`&S~ROy-qEoR>1|=8ZTwC+#^4!hP?DE~G5Nb@PnTA7B3~ zJbPKi=xoWwb0N6-lDr8`-RchrW?rZ|x2E!lr*h>1A32CkH_?A8eN?~L)w0fTi5-OJ zah(3_#T6nfGqvYSYJc-3K5#Fs$&4u8MGTx|ng-^|r+ zJFOx>w-@vCWAR4S*;~_2_7&}?Tj3z*{*Z!3PFWflm=+c&H>7AOf6l~Fm$b>~(#HG| zVIiNcW2w&G!oMJ{TXCO)AwhK&yJY=rDYx!vnIt#Fd}unSCmir%0Y{-hFQA*94QtaZ zNJg=>q{zR3ZvG#&!||D{dHDnSnpf{teUA)ngY~(@?)@Q-Hce!qqQ!KpCRA7KbeINh zP-igf{%g2K#!Isc%q24BV26x4m)ITqUj^BJT7&&&V%S#uK?LZgwuqpxf`~8)d z0xL`}>+;Lq%Pm{}$|OE=7oIDC#TwOI?ab&lo4Q#4`eE6EyN;MUHn(V)3_gtGS`n6C z5E3c*6qp}!KAK5{J{_l8C@f4afCj0ytLmb~!;}W+fyf&haeBf#S4WAWeQ1hC60LQ^ z?SeSNs%p$}+hy7%zFMOloTB9uFX}|3l4YU!zxKAVAU2QCK$SgUB|LgK(5zkd;#___ z58a&UgezLbi7_8w%6)d@V3Ss#pA(@1>NLA+@Jt*$nq<{l*T@!kE~n-6ioW;ja|wh= zV~1^16l@LUt~NAiX~R?0d#!Y$Jm7i+u9TxaQX5O)#Qc{_IJv5Zs&~HKR-IUk*F=ir zWi?+ekZ{pYpIx-Sxr*3O0;?rmZ6!AdM=iJdM_EM#-A3#xZYi(HErPU{))uX*6x*kS zrK7P}ZkYk$j(5G~g zMR@uEXF}Nh4f(hZ~v)q$Zry+x6x^Rm_ujzOTuvrYv1~X zLt=9|Z2R8I9}!OXPWUF{)EajtmqM?rkH%Iz*a|O|r(|=lTq&%NjqS6o&)UW(PzZN!VRSP)bDa{e2?LBBG_uN)Q%D{)DLf6qCMYl+R=i=FmM7i@4{ zI-1UJazBGH`E`Yye_9Y*`{|(;wA9h1UudvA1h$L0LHNM4*Df>jZA5Cta2xTcB5sf# z${!K#_2`Iu!0DtHGRj3C<>#WDoSyL2+3^Vd za(ZjwYJ>HIrc5WS=l*R4$!bFp`wcgg_k9ww@bN+mkm^d+wyk{h(U%$7hUA;XOBXQXm1k2*|#i= z;)icI&y2ot_Jmmr3zQQX$ye8!_H=Rvsb!h|rH z$Ee!~$+u$?p_Ry&E#<@)hg;xVL#7kjoaj)9lD5^k&C!iA3X^$iB6`_}@u}}NoQiOu z{o2~Hw;(OnV$oyd+KK6e>1A4Zu>w-5T9=>uiq!-)lcQO<(p5(L=_A{BxCN{~XF?bk zH)px*a!uqmS!05d^cs7j)is`yS@U*ExjXn4BdI#5H}1c;mzn*Jh2^u9asf%5LR472 zcCZ|kwPK>5W0gql+kk$yu`(Noj#1Rj#G;S-YLfrUwy)(;VlDlQ8`x|g$juWEEqSG-AO8S%^#?PZ@S^XiUep(zbj+JJpn0@x_h<|7<-7$1 zT4ip9qV4buGi}I1t|l?#8*=T#xe~s<(DRYLhYIM@m+p0oeHG1~BxS%T_&sqjVpe6U|7{nIoDqI zYAc0Dqeu0)&XYCuqp06LG$htF74ARs@vc@?LPET*?Urv(YK=U19c$pKFSa}I`QK6v zMtp|ws`Kp8#g>+lDi`<(XQ$ddw6M{gZ7rW?$1$am@3W9TfmuiB>N*s$7cw}zukllC zWNx?kM!c2AMyrvgI0wH$uzff!;lD4&&Cf9jV#*KL`W8$l4F4SROetH-B;ygpTKy>6 zZQw!{)q7X z&H^7Lr#3u;aZ+tta)Bzi+(H{&$v`goh;2N>I4NO|Mq9cP|9Q~BpkO0RUqksW;u9+ z)V~An-RI^I?iex{la^Z+?Q{!)XZja7AL~kiPWEh-+WY?=h z!j!cAcxQ!n0_Cs)<27Ehdz_EM6za%*#;10EW#sQgBflzW<17QFOZu6&FhXi{rd~pu z8D=3XrrUma=eI5KiVV*s{qf>v5I(UR`$vurxWvZro}X0yhOppr+g)byauk{ki~fpE zSL1#sHZJ@mKhn(m?ax?qp2e9E?s_-`Q%4$q!LNKG@RfzU1K8C8Zw>`7OqHVT{~32b zgmW^&%cqmJn!CZ-s7?d_8~*69>`TpEKPu;sP*2dAJ8eacdh<9ix(hR=Xhv-{_G(yGBo0h2q)XM z8?BTE?dBNsasG(#$f+~?%&OodOn%vuf>8d5aMY#zkCdF&-$Rqt!Km=sDDAbdhNA9c zh=|(cLc;T0PCw6WjSzM%&Y3Xpl9w;^N|sBkeTZR-B0c2W5{49XJSNRN6v-%x7%;mD zVme`?{4KXAvIc{0(p}cm$UA6_q7cpU^x>r?m0MAzFIJIlBnR6y4Eq{oIJ+5_MEEe^ z!+Wz->$&C z$&DZ9N*Iwj=$PcJ=4>p=gB2u|^M86d7Es!^F*i)0+U-e2pZLg_E!xKya=mqz0!kQm zy73gHX^uZbO-7Z!4{LW3RooGN(%AF$4rHPMSC8!tIe5so_q|`2`#7H?;}eF-C8*QW96b-0;;er5w1qMmA}qr7M}l^pDW4EHJ9*k z#l-|soHb#wBT-)^)3lFz6@hyn$#lZlz4v=ch0*AP-Jx~SOec)FxfKUD>CF(WYN-zq z2Uf$#-^LbhCbe49n}%D7Y7cOa&*D6ivxHq%o<7IXa%z9t#b36~lv%NPrc`Y$6SUt> z*k40fcmvmju=>ipf#yu`I>}`#2i9Xp zgx6S;aUH!9MP1j2b0T!K`<`W9c5SQU`U<=Hxn+Es(ie_Th>nZk2T!kY4utXhzT*`% z3S(<^(HJu7V2Fe1h_z%0p@rMu6ZCb-tDAs!jGH^u%vF2y!f$6Thw%B*{Fym@=7#EI zU+Hv}zalI>9Ir5=ziSGQ_pm>zA6)6d6+~R=v^*;6mXZlh)ZvtbrQV*pYnCKyp|xY- zfsouL8*T@o|A2B&W%ii{SVpza0=zAAnt-eKdq8jm=TA6vz>nX|LD-7A@WTE7y5T7y z?kUZF*tyg8>45AT>eX^C{;=*yW|H}>Dck5P5FmBB`(Qwcvhomu*7q+wFkM!i_};eT zuy2)48ff%8g>lGk^Hpep8qKmQe4}{ERjXdcIou4wxwtP`nDKyA-5{lb@c5#}2gn}Q6ag1uFJVt@#1Gd{_MVcsG{TPGKCd_TS#jO8vVW)V zxM}yERYTomX#2+PogW`u35FvrFWlOXP43yniLed0(*Fa z>reRj@7hzzJhaf=^Ic=7`xx>J)Q&lG2SbJGtZ&)1x^|8fi z&?jw}A%qWF)WU5uknbXqF*tK;ei|f}zajkBIO&bP^X_(q!tT1BS0O@SrCri z7rdEvJT=$ZzJS~9UCgQUTP3;_o*qI8>MP4{YMod5tYm5Ms9`~W2I~cmqB>4`#VEUChqW6LjwkcN|$dqe@ECL(RxYFcVa*p;Ck(y&_%FU?k6K-^NtmriY(n42h+uPZDf~I%*FwR5awCq`w#*h- zK=)}0UrT*MFxkEEKDtz|nnHdoy}*sf4eyI#^Jtz9O(y zSS~TC3Op7grziZcd=+1Xo#;CU-A>F)zh|xH8x)CM=iA|Z-6YPRFk?*2bEzF#`MYW$ z|NBfQEW5SfIcY&Oxznch}LG2a)9740|`VVlV7II(ADbdgq=(B-j|@=q9%HxQSamPSWp z`elc&n{s->zb}sQqf&i~YU|$t%DeCCM1A=~kNaXv1*`Tt52oqncx)2j%&px9hsH&O zN!3wj@v~O_W>7@`l{c)ZIv80s?odII1=Q2pIXYCnVxP=aCA8f zgd+_bzp5(f7pA|Zz|CdVJf)eF>Z6&VoSrbK*3EpxtoEi{+`oj6zeUf_kqqJIhgtm# zPDL1#XZjzCAfG7@|4^OP?7#2{hq`yN_!SNb4UQWcD+5_cTnu4Ag-ecf%~CJZABQ zWB6^5tWEbGi{vtb*0i;aaobKHXG{1z;pQ8q>7$#X>8hl?JedkhLf$6QqkSDAsj9G? z-S7S?C%tM6u5l@ZkDa1>lSnlcPkqsWHCRRomoI3PtT3p1T`(|+lM)uRyIN7vQX22o zQp$2xgrC~aMd*lb@zv^@=7sH|TRAI2SJ${Da%V}@BkaI*OQ{bX$?91a4gI!C4d5DSxbwIlYtaboPZ7BcI3sp_cWn66k>> zPD;2nVR2{ihRCzcM{ zq5kopWj21*K*puCye~Y$1$S!NZtsU+rHW#^M9+D;^bgLT&^>U+YuUqE9w+|AHiAJ+ zCrsUSHjk8$=$%&b{Wt-8@u{l^d_~H7L}g2RQK>SLsaG)cJGG^w$a@N5+L4tljdPcT z>tDa}91(-K4NbF=+(oyZGNHLufV@1;Cl}n`b+$NYo1eviaCxzaOB{D0`sdR(I9jQ` zc)jWpf(M#jZq9|%xT>qV_IbUdWa+AlBukveop(C>JV|aYgs}9e0cYfq0j(1C3WXOn zIWe8E)PJW3^Q<@*UTYg+WtmUwm7?HSnzx;=Qo%qA?B4j!93_l?yJ42(IO>)M*X!WU zU0}oUP%fAt`+=+0cT%deJlH4tBFTJ>_XhhjUb%cwFi7xV++5%$UBXi(NuWu zf;I3j8TdcW!mK&!qg_7VRJ3aC!jl?xwRA&?qcDcUNYxVUjpwnru z;Zq-)+vh4O7su6*>U{S|Le^)6NuEJ=HX_S2+*%jua;f|L8u7QOIItVzhq}hsu6%86 z=H@59?!sQK{@g2s9eN*ZK@4dsa{C8jdDscLs=j#H=d&?%(0WuhYniLQoC)FZuU*H> zOu)ZfuE8NegMzdrYc;39ph08IjetXpFU85i;dyi`9d$l@7FFopS*^6Q2Qeaa=Yj}B znl6bJzWXfwL~3O_u82zC`ugAxrHph}Y{Tl!=?OzpmQ9rvEuRLBRI9fpbnI)^*e#HO z*J*4L-Q01crq}0hY|}|dO`hSrpgf)PCTuXvV<5+>w^+JMySA9=gpV>-*_nmFRV3FA ze?(}t>-VB&Nsvr(ijB~C*?~VJ9M)#fJ9AkO_`SH@r7_b9b62v%E>$feNeU6` z7S59gHIuzHZ-uZmp^p}OVCeSaObETxXF4m)Tv!OqY|eB-kM?E4S#(^(d5?%{<5mob zb63)99e!cIC3l+|o0^ro)on9t@bGLJhMcZk5@BMOBUO~8y8bzhT z;kLRpu&;}|W^$m8I67q)?5`SOHMz!Hn(a(30cIF=N128WFx}=D-Wp2>=g^oit>`k9W`MND z4Xjp6eIHZoFUd+xG}=zIlt&s5Az9zvQP|Wp1<7Lnu*~Ha5g(nvyEPVa=7ggXJsy$Z z)fF2{A@G;9oJHmUXyYH0#|oRdBNvrGM+R_O!U9EFkCD@4t@LH3v0F^-=tY0`+MSc$ zH7qjWe=N=yyVI?n`6C?PEsweMon#CUQ@A9;i;11j%6`XX>+>QU;l*!nt>m0SYmR3boJdsN zm7vZ`qh%L;uZ*lGbJm0h^R-P?IPtA4I1$2h!l7UOj+R^=IvGw*HzpC@dp~%*OzJZY z1Jtz=$ofyF6PB8qF;mH!^wv2lNZy&Nn)N%~ZA(&2f>{ta*Rrr~YfO$Q(=Vy-4SceDvS#YuJA{M1&TDO zB29zOY)d!Y9SxO#7JVtD_>4gBrE)65sbTB2y-IB0G}Bb?Pbi2Q7D(q-6B0Ye~ctNCl|wg!cxvz#+w z_|R3ej@ydyEBS7zC!mGo&W)|0GqEhuno|(g&02BUERwm!mkJ0glRrRZ5{|1@9B1q4 zrZ(`~&NV1HI8+{37|tIN`lKK9po(KVV0=ulHYx-%nXtCoLu<*ir&XZ&qnSjwtC`1K zS-fT?i!6sQ4`Mputc+@h6tyA~ATn24vbiVMpDIe2|G(U4Wkq4m@rtK=7=NTL`wtja z#$R$DAGzz|=Mh&v%p~^I5!3&Kzw#GnO*rLCLIX`>iXq4v5*iEbCk(Gz>#;tG zon%;4(^XAjvN8gAaV3^>A`JhU2=#Qf z$uV*!ArzQKRFW3L_d92AGN-q5 z3mp;~oG?hrxLQnS$4~NjujcKVJYa>$wWM4KU))>gAi1HL&q?v+GH;-%z!CWN9gp=9?ePmTI(V>f&Gu) zG20SbaeNUbS!$3V`q|8n%EVw_b=aC!TtC85`F#H%b!%$u&;Jq@czsGNEoto`HVaEP zQQr%}|9VU&bX)eSk697i2gM~s2M00h)G>1AKS=|m5r~f%CONAb0k6y|brhEaW=wBG zo{zfONOlmsi99YefM^y-t>{6o{xFr=g{Y(}z1L$LRGGHyN69$pm**V1UC%8cyzP6p zmU&>a7gwhs#!{c@gi}BKgIlv%m>op_VlWw`>(u>(51xKLEG0VIErR>%j(gSm@JECJ zyQYU`4khGM>IC8m;^Ch$ju-#7k!!)(-S#e`~@ zKdVD(aFyCIa=~P?A1E=lEIq5c zMV`Vz(cuX};ZmXc^Jj!D-!$@&Q9TsnEGo3cu`M;5C0`!!&VSGysF+;h`JGS>BCX+^ z2rJaNeVMugcRcmLDTuVE*me}gbi#kuc5W>LT3Sxt?Q#4{^&76*Zro4XezgX<=?vnd ze(kYohd3GA5eLu?_Qba2iJUc|b(Tkllu=@5;XyHxF^Qq_32oK&sPM4>E>UO(fzdiF z`95~-t5dG--$wG(AK94j5|}&%qFVMfYi?Z4={Vu{1aDT2=b8{s9k&RtbZbSRCL*;R zHqfh8xGbjd31+PdnJsbi^`_gnxmIn?b&4>2!BzpBr7a>*7rcEC$FCQuQZziHi|}oR zs0V!_CjX1wfT>&;!iV+kyUV(O;dx!7f(8Z4jqbtx5#fgXFZ0T%7%G%cEbfji%c?zg zH1126VuoHdiPigKd67z8o}1-xzr3`{TB|N}#hK7HTnORU*Mm!&yWUx(K040x1=R@5 z@8!hmgzCD9q)$DqL~nMqz{_|fWRQg1;_Mw9now&pzhzhzDMT6_U2H9S z_Q5d&wN0gZRo1o-aVA5VaJl5=oBDNd@_X}I2hv#bj=&?Evf zaJhnNf-js#R8>1wN?8=qmZxY3i>B&i<7q%3>~b+zZK;DMe~9;#JJ?C7dL>(zZGI}l zr__;Dkd4@sfxV&XtmklanILl8HT5YZ7QZ-dBVM<~@z(}i5@Cq%+T+Sc7akwy7;IJk zh;Z(N8Hdch>7k3EhBdExK1UIim$`>>dcxNATW2ad((o~KB$4TaUl07?gR+|3_UZv` zj$=Au;>~<`K!6sS(OhRN_J&J6q&Y0HjIhLm@{6QxMjp_!M>t-f>ggZlu7>8&og=c@ zuJ%v6)~n@R5#V|;-3f#~_Y<%&k#?A(1}0(bX^~4eQ!f4HpLjDHa=T*-Z9qh}yQ!MI z<7e9Pts$CTBtO8*7R|X8gt1Pg*=Gs1$yv(;&u^FW9cuR%@vg!&!qWw;BCyQ$o_b#v3MSqma2bNwR91$UuGYiQg<*FU0GMVE47(OH`(BReS;KL!ik4wm!xY{ zn~4jNGwp>#4NF@sZ+f+(&5FzIrRJl^f+99*rcHtPK?!|Tb=jRf)+Bpa`{v;75IfUL zq$O1#jBGLdgj_Pw>gQ!|V>G>D_7MKN3se)p^OkovNtX{Nm_hR|bazJhXdn^ukKH7yI8Rv0Cn@L}sI z)s$wW=drOjHF1-4!Yhw%Jf#9VnXcxR{}S#?@0Ckd!!tLkahFlxPrI7Xw?#~KEoJe9Uj<_C;8ZgKcGwD&5lI_x)`Z*s8iR{6X_m8joP~YPbp+qJ zBM8r4?2PJVeuH{P?8He@W4yJUseE1qBBLMTWCq)Rc1~JY4Gb66vktOYDh1 z6=E`7WIADo;yBW#y=Y50x#ncz!ygf*{y8U~QXQ|Us7@266XqIQ9TP8l7MC&+BL?6g zj_O?1{kwY}HbmnrTy+!oyNlMY*Hf?pGmxqgkPe1IFpN|HJ0@BDKK9hI4NP>`e~u&Lm6=Az#rGBenGshK`|)OWWrZ% zn_My%VlReIfFV_f_|t8gIxGBXJphBAx?je=L$9$4{SMK?IDf*nj@9PTaR#lCylz^7 zrJk_GBAW5x!shdbzYUb!Y!xu7rsoHXjvZ*E%Kq!i*` z2}ks~7 zi01hRbtB02EGa@&ajSx*eCTXVE?g5;s|_B}9cEQqq&398Ahp-)6bRo!q~^Lv z(YRaf9?RuN{{)CpH?9KV{Zl_n%65a4TYMh&%ZZQOnJvzWfrEZ|t#QVyZ{MV=<(Y_G zvU}@cH{(&Z0E8})r|@b4?ePI!zmM(T=9_NHeRNvVlte3MlYz$@!WkZeQ{|1l&FHqo zM62?qGE64y-1s9u1drs7qViDm(`g>g2*WqVd(&Wy+rSf{*5&Jk7qkhI?G;4_TlLcd zpi>81b<{=oBhOk@qCpT3XAi}d>Af0+WA%TCmD~t17|HVo-DBq|yVzW=P2=J?1{KW= zC3MV8>@Eiv|3TQ?ok|Q1XFB1W$GITZ8@)*{F*J_J}PLLF)I+VASmn>U<*ABvTFTf>ghAd4!fNx~GUk zhYa4%aiM(Sejg?i_U{lQ+OIQsi|8(4cEY&Opr2yDZZKsTy?a$(q<1#h>NY$M{~X&& z3|xTf#11j!5T!VTU|yuZPRiG+uT7nvZhL-%ZIuoaO; zjFRe5Kke3`Lc#)y;hJ+S#gEeyT0h_2n*+Rw2801#K}A%5bZ}m;4WdeGLkHckBGzTv zilvL78i^S=9z2gTBwU(zCivVFq^zBWJR*4^!qVfIPB^Tb=_GYwJ?BAu-Agc234Ixv7VupGORNrVN9zqXZAV9h%C8{ocnU^=0lOZkB!C<^L0dO2i+{2-Dj!kOJ` z4U@w5^F4&E29pTKZ5)F~JIQcpn(Fx`jz{*pt1uyL|;?aQHaD{)f7CofY9OY7uUA=KJKJN+0R8x$;~ z*lJHMb=#3&u32wRG~^ZCFFV0Ae1_}A)lm1C<$u_T_B&8hhq|G*M%8#Xe%wP0d;*Hk zV)&dJ!@(nU&(!bd%I~84x9f`QM-BN*$y`Umz)1(U$>t@WH`o>KivV9xoK)$x{25{N zamO)I!y<$G#U#pbzgk59ik$8Z=Qcw_9HU02Mg8*1$oKUkB*qx=P-)$Ft} zQqt1Q*;8hc>FpzSMHhp$F;v7}3S~pu zfU_qo64@Hs0l&u$$0YlO%I$ipj<}94*n|d_mbyX6H2cDK8dK0A@o+nay)YCqrE|7~ z?w1_5v1X9Fwf0kpy)N=$Tf6XG$!kAcHz8to8?1GEzny=J$Gwx9?c0r6o@zC3*z}xa z?j{=%^&iIdX`VvjDy02Iu+=6p>H!ve2XHFF&9-f8O66G) z14lp=&UYtfVrM?7+>GbouBvjQRvkDa4TRS)NZt40P$zZ9`qicJ-%{k$2SOXRaDjxy z^S{BQh#WVqLeEoRnVKgcmaJ=8|?&8#hNk zga)XBlvK)~T}_X@htpx}>!o6LUyIWdn(RwsD+P)FqPGx#HAHe^^2ANjRnmm4Ul!tQ zstit#bE|JQ^LfP60VsL~XH9st<^1Z@CEjj>aMKE}MX7aL=h=Io6esAvhiNiT4hgFp z5&qGtrJ076ewd1@RFSwW?Ox=E8T5!P{j}P_$f5RfovX z4Hn;}`6v>NmGXw8p-lrhW5U%3J#n9f<|!A%9;k9mA{=|+JvPYDn`#il61trRl~1+7 zHO&1m`Ah0;a1vP$;YBC?m&8Ytc5o(yp?(!#Nj1=T?EDPotrOD;k4;!`i8QFC&WjF@ zIrm&DhuFsAS13<;O*iN-B;G#>nH6q?64hUJCuTQ`UzIaRMS z434@@cWGZc*OZcU`5^>+80Sa$a#8ICW&ySnJvtz%svCV5)tw+cT}@eOvL*taz|Zc@ znGk+9?7{sGG^5kF0G9w$u~2BK%8CcoM^2D-$p3eYBz}ouE;{Sx@>vc5Y38|rpZAT^&PU~trj!uU6Z!#Ch2XeWBKc2r`elXd>p1xodI=!vwE(aR|F15%hbt3((^j+ z#l;hb7Mdb=MZt$-mR6E&{aPFDn>w@=h+PO-Szu@+ifl(dW4OA6qi0>2EXSYJ?ihbm zW9awy-D6a`w>Y;1QwMcu3M{t6OAfZr4LHoCc8S|`yWP@+qTfAqE0v?`_v~R7iF_i@ zN=#JuYOD-Y_=zqU*)1Hf?MB!oKp>@ z_%p&zy`$xO0iJ&us_70ATfCWyi;c-LXpx1eR|YrT5N&94bfVN5O_DQx4Dv-@TPUI3 z!+norl^6RNavS5gK*FkqpQ30Ig*_tSQm5U4{Dm`_(6prh?xQz*N_Fe~;we20Y>exY z&Ghskunc6cX<|t@GpkHD88g7s(b7#+6}e;PgHN)DrglY_$8t(S=S~ytrJzKAg}0&# zN~2Q+jAr$B(w+$B`y{rYu~anS(K74sgb)eFj~VDERqLBoT{A&i_VhP+_@E6JOE_`& zs1w?Vo|1~-(O{+!x{q1BU7CV!Cm<5)NU>~Jtw9c_HSk|8Dglq0} z#cjLfb&VK~iIeJ8T^@Mmr0glLGpM|p>Z4e6R0>|6k;rfqXGqw3Y+^O)dT%ju&M#BU z#*a_p8bbW=dQ9EA%0Eg8cu-H zx8qz1qi5f7m(9Z-BF3m`*r++{B^E@Lzf^f-x#r-WY?5$y%NMiEHN?a8km-SKQi5lDl8ENK~J9mFepvrR4srU=8kZ9)z8b|JI&%QFPT^ zM{!{P-f@~`gM^pRP2rA}_;_88QVm`j_>A==^a!aq;j%9`BIVpSduH5_OCwC3chg;J zxz}De5X+fFIC7nDE!m~%Z!n&y9$47Fn3|h{gXv0aUB|tkai!(lr|1 z4f|XIIX&SKkN+U3D6jB(j>&8YXF}N3ZR>G4-$JB6geUcCC}v-;9oVx#?T66VyF>=X%iv*S z&V(?q-@iVxcQL8ZzY1Y0b@G}fvaUF2&+`#=yj<{N$tiK@CW2o5H^4xT zv5-ri_?5FTY8zNq@kfMXZ@e9-Sp~PC`1nu`Y!2lQ2nP;H=Cukk*oEnho$LUuIxiV@ zr?8zILl#yHwRMV;(Typb5n*(D9H;wbj+6c`tZFoWM7W_x;|-D%S_IO)Gh7-krV}oD z(kf*l6mb4P=x{NDZIZB(~+86m|?Q(OQ4;Bo|WQo>ukBdg1}q4i8G zpVeg&;q%(}Vzk~Bqb@?(M>B~qzT*_kFKN*AoDNHET#P}W2h#})Cihy+Q2VVt-%~}2g{@$*m`gOgMU96Au=} z;27TBqKe{mL*{(R=kLeiW*B#)AJh@#X4MvVWV1let8?1&kM8!5%sMhAyo#4rYc=Z+ z+a0gTtOq+{L{&S!>c_oB&+3T2v6)JUJ_3-FuIh}Cp7iV5R=*xK%x)1$5P>$P=k70mN zJ&dwRx$a80&-CdRw{ObN78lK)vh(7Pr7ZaAh>ASq6Nc}3&|Pv#^FtQ3`z17B@zED5 zLn;>=N}=KNP|4O@HNx8Gy=~0R#wt&HsN`~{6MpHk^s+KQ_M`zakm-bWi36s}N@~3* z-fu#R4kHs_MYjZ7wVop9=d^x-NUMdQ_uTkmpYGO3WaI6n@GSB+B< z2INh;Dt()*M;OD__C*XsHC1;O1v*N)*JyG&Ut;?Ck<$~JE|tYz7@8lX!YS3UJav~% zUdeLJo!_4cmZ&=a(C;i3rs2}y(Vx)hkO;XqUX4FZE*=;sW%1HQ*g>`4$4{@>Ep2+9 zj|MyA8m7Mp=C_)waE%Fr_qJ;& z?Fa_Q{H6jd_k~WNd6M_@5L0j%h=+21=9g9y5mV=2V`I{VY)v{kB)Vwl(M0n~? zJOH8Xt60(&HK&O-nQp?nwHw@*J@{$~dQi2W9c$#_XB{-9yYUR`K`Orz3~%xLC^@BV zeum`H1&2mXYCKqWzBaHL=OOD_Tq@yJj}bq~RQTzlB@sO{u4&bzz->0CR5j{1wvC*4 zVX3>IPMX4E{yrud6&9Uy+ND1iNf;RXwwvUEdshr^Ety1^zrLxL^gm*$_l(Jbi#FK|5`)}&?to# znbf(%q0XrsE6T*ewrhNBBtMR(#wjKk8(ff4o2XRq{Rrnw*!Ek#!g5jCgcVcWqV&Fr zlf9+ept*z|PFT<^%Sj0j-*&4geTU$F*#@RM(+T?xT#uL^?F#sL3t6i}XtlLhG z4M%dDU28Xy`Y^n8tL%T3t?vnf5q&pLEMmTBHYHhPdx3#u`;pes>5w zE&Da#Bl=afWZ#zimN92%guO>OUYB{S{tF(zsu>d|#7`jcZlZH# z+*9!mt`_6p+YOSb&PaQNoOz$)YKTo+5UAh3;`@DBS_hi{? zKYyUtd^ss$N|h1@Id*EBG}hlk*Qo6+)*}?J&zSdlUF`+aq_$_2glQh_fKLHVRG~B@mgE3 z8XDU-PVN~|?eM|}Z{Lx=Hr9=K3ub@aq-lizl<)+WxCuvmdBb7_gDkftq;yRv5golT?rpsz*9$Vx+M0|f|I$^g{ z6)S3eP&h6qq-sd06js%j-LSvUJK2l-;077h;j<>*6U@;UY=dwxswSm-sm|hJKRF>Y zisTRQCsgP6pOc+OMU@{8N^%? zgCb?OKju6LN3@wE-8JF<1>K;IahH;>E|7bi{GTDDJpUQ^qYh#s_IE^$Xw|UEB&fS8 zZO@HCSINZI&A!L4C>Kdsr@`g%)V&BE?ndlF9ie_43Dq9g(`Jt@!t*T#*AASN@ch@? zrL=hoEfa_fw}WyC|F#A@?Xmgwpl|ZVI^uqVcj3t3u!uOGe}^N7x$n}MT9=1m&di)k-B%k<@VzAB;j4HZ~Sv?YSN zD-qXIeG!}Y(IzRMn#0h;3Cf|4mX5h|wc%+Xc8$6Z4vGs1Nr;NoTIkP}CG0jLri2`b zHr)PY1IYR*fAysBb32`y<}P~et!&-GXz*kK=S3J%b^d0_=6#Lf`lz;lZ>d!^*wdg* ztl2xpj7HT{S+)I~xOYa*cW}BX7VB357Scf=G`4B_MG7T3Zf*(D5qLRFYmhoCI=1?w zy=+k68bndzxqgIy9+-Psk`Riu7T;Pz7Sws%)5%YRWbbHGWB9wdWvC>EGa;PW%^^9~o&d-8b#wX$SzTZF0)d?OpT4S zg(@ak`XrS&W5VI5(YKm*o@)Z_RPDl?RrPa8v7C1v)%nS(2tO_xkHf~~_m&An$3-%U zu=mHJ^`&b?Yr7))7233JguzK?*WTRTDe@M_%_yl23?43V+4l;l7Wv_~t8Zix)I%<@ z+1K8wOPA$8mce}zT1b&3Vbv{++$z^vgxO)9NKq!56u8Co?H|f4P{$d=tx}b=TvDcD z`1R(t5N3o`z9jRoh@vB)8`+EFRxZ&I|6>pF^Q7W9DNS>9Y`&}7mv>aE3_9#Kssc?=n(5XFDx5#e zVJVv12(Of1rnzM=uW*!AJ2x97RUBtroZMGBM4G8G#X@?F*e9>saruv-)eR}s@$tby z(efhDLChAyuiXw?O3B@jY><~Z(y+Oz;VPqCbXhV9a}8BbuBTL3$(l&P>6$*cJVvzy zmo~SLr!mw=)PIM4c73=oLc=ECSF#U0M*Xrk&A;NV`?7yEPN&Z?fYW$lN;5PnA5-0N zNu(yInQy?c#Y-^Yz2hN-T=RL$RVGUgg}Wh0%%>invq zyNpL_{N4~_aMt<6O)mVvf*qNyPlJ9LgJb9JEX+H#Y196wjo5A8lKDrN&}qMz**bg0 zw@pC|p{1Bi*ff0ZTv^rmj^PDNNlYTVe5gH+Px`@QR;~7yIot6tA~vw4yn>68dD96m z{JqA$B-M+3*KaycfVJpC?>C6FtC8ixiw@&Jc|SBKxg%EL)VPc5?%HQ1DT~%q)u69e z?R&Vf3ruj0qZK$!7FB<((}s~&ENk(Rp`mh2QJte{@1ElILpsh;!4 zm$zjGaP0APxmLm|<_O`c*ugjCm~$WtlQ(s)y1^q0Z}?FU;ZPDsygPDI!kLRhac$Zm zLldJqZ(e+3fw*UjS*K@9L+Qc^{~xFB;)x2{(Ku}{n6udYI*1FH$psL4rq9+keAN|E zw1J^9lL$*!-!Wfnm+*NDl3IaQ6*|L_p?REk+GL{xW?ZUSo9v#pQ8DzXm+A_0@4YHkU7cq4d+!0l&D;B!_w`}TW zI(AXHJGM@!KF?mionl}Ngoifqi%f^yyj4XV7wAs$_s&j^+s#Cc>gt2q?+h|E$;{&3DB-d0eUA)02Jcs=vuo3q6 zwc+%H&40AUed%-n<(w}L6Ln$|VdS`DI8jOlKy&vsCw}NGxO)-&5#f&BMN7;4v1P{5 zIVzN20#FCjLob_%i;Jvq8Ya+S?;IW{)w~(!LO8;sd|A0mK`Sc#2=rH#&mJ94?w6&& z>2(mUe_%{jMLT0?oi5ZX^_)XPWv4`O?u5P--yfni?Y2uiP30~4E~EhdfN<)y^@zOD zpnPGDLEawx9TTd)Pkp$@%4K1)u#i&_c8o0djI!*mbK;8aZjZez5Dww!i>Ov{PCz)X z)T$_11Z}@_kHA7SJ-eulBdXQ?ug6!c5t4sO2f(VbNmS)%V9j7GBU5EBmBnkYsvb;B z&%IMh-*l{q>HLmio`bu}`7p}2bBWBJG_>alBw^dNF9yk8AUi{6TXTy|FX2?EPS^X_ z-I_@olO1Ot#LXlOuKuty55!T~banQ!;l_DhXhKKk5i!$H&1#&U@cNk8BT~sd??Qjn zPO@3!#~wJz2<~nBzoYm%*9mpyh=L=v)~!})$V)!H`gzVdhJQ043zdOaQWQ0v*E z%Tw%@yaWeF4F>pTW#&@mW{c^l>2R(+;S+x`NRITa#y~>1Fp03h0o+PIwqbr)C%KrTp^EpzbF;Lr_ zKY|=gk6Bo5Q04K~v?|F`=(I3n?PGAzRr<7*eP2s{(y39`sG+eD(swJ*l_YF3sUvSp zjSPV-s;c1DKPgJ%nj0Pk%3ht=#%T$!Kc09>Ht<>(%!5@qzLzy`jhs9TsflT3Q%*$~ zdv#HewA9{4T%F*{B*KaZ+aD0g-7wG8wv%ZGd@GGd)++DA4&jK57EZIj3b|4%RP_0C zbSCWzUGc+U(hXt>@7IZ-F4(AsmB~E9p+2Td>iGELmDK{-lu{MZS7W(Sgrm|gJyvYI zYZKV`*Gwm@eEc_G+8)+S7jl|f_#c>}2$aw@{zH>%-w7dl*)betZd_{Y+2iRrto1;+^|^QVMu2fV9A495+BXYpz4 zGq}e(i0OphlUw42nA4U%V)IFmR0rX!^-;W#dlaPHTYhnye}9(dD%)KOrnr>)p>^bI;g=`~5vnSz7DP7w)}ue=1e6gRXWZe^1}2XH!9AN6w#c_k|%s zd!JF`;+0c)9%U$#39sFLfI)U%Ht!;jfj*Augo)eB;g}Qk-HYSsyZ%ff?DTjRwmptS z>(K2s!u5VgZW|v-7blNewiJKvK$ohHP?g)Ozbb|G*n!ZrO3&~ubigb~j>@~js-Jx3 zqGt;lo3&yc#m_UiF0DRSi|~HOt65}pm_Bk3rrfI4_4GM!EnO~+Bb&B?*A2E~t$R9W zLfB%%XB!c8!m^Qzc_zA)$%H>9m9-#pYu)k2!7JA6(GrQYomk`jgA))AbV?6XDrI{C z*JYn#I$@K55y=XD#&OWYnNGNI+*(&f#D89dhzByA@a2i?u2OtSQAP9x^p!fQ?yqfx zpLyD{rEUfD=%=a=rS^df`sc*+#dWJHGn{c6S7EE_6zda&r)VkqjDB|%z0dygBHDqH zHh4KKTckXKqvFE@axNQC*IOnHSfnU!;oz9)=xm=!we>Z|y$e!$?A+g&InCh46OQ%V zxLBc|IfjR3RJ!w4&u-NCI->VcOZiYHxr;@7eG4ne+MGu+b;b}p<5Dhpli8~)7VbJ1 z>hX-?1LPGpAQg}%xdPXSa9{t?cmsAhj3?;!!s`&0BI21&SbzRJ7zVn(>-$v;JMr;c zNM0KjKM{4+q6sX$MQ-C5PC@wdN=G^ZSd|jEX}ch3J=p(q>9_Lwq{>(Dn$K+`2DC1m zity`-gkxrUA>Fv%H?7@bGbxW4Zu(`d?B{Hp<<)Lx(z4$CE4}XDEyEPLYu;bd2W$;m zqR@S=;zC5#uNYh6cXx$8?eZ`5LIL|0%K=v_|8-ulP>m+d?egfelHTvv@<+S6UsUKB zmww6rMV);qIdp6{jqNAjS5qswPlPX%{pfYbDz_`5#<9}F3t=V`T0EX|Q5@Q9k?`#e1ymjro~Qxa;s$>6fC?4kGn9JldLEDZ&oL{t2VxK5ntt zip~q@?>If7`_dDY*w;CPi{0iQg|E|#>4c>|;Y1KBSyQ+jw31V~MC9vzWwpkKnqp*m zgu#b!k%Tb=mz9xxOgmuZqKPl5L7H!^`l9F&Fyi1DJf?p0Ag(M^-)7w3#dZSG+nMTf z@q`8JUriyVdW)2kRs~Gcm_)cVU##)l?Z^A6A@>|WaU@z9DLm;xb_TsC2=_`?oTAiR!;8jXcH72zL``^pfd&u-jct>v728rMnq z9k#MDec<8=(*w3*GC@LBrH#~z_B(}F(bZB7-kSnt(g9~fc`Lj6X6N`>H~J|>C+|klYF}O%JfpTu4}RH* zQD-2lYWcTnU;SG?OsbWib`-s4&GjQ(9sUH5b<;(bpcl|ROXd6ZU4*` zPn`sUaMawTagt%0@b%hfWp7foDAc`U4W+-)GgwkOjW?RrO#B;q{Vs3x)e5G)&2++sfnUbw6yg>Y6O#S1dQ1L_u=Js4R-^|F#iu>!+ZZMh z+Wa*h?|qOmpaTk+8Zn8m!CK30)WBAzYWy#u&7U{Za!M4AXRP$wn~%+T_L+L5waJ20 z5pM21aGxyZ`(f}|Fo|%;G^)=vAX4MkUdYB zwl3<6nU2@~4&e65+9x3X<+)XaNBY^-GaDs)7c7;^x%qdlIbqPna(;Xl>1n)_J)G-6 zn9|GTlbQ7nPJ9>NDo#u|v*THVY_?`Krlp|*K3oC9$>;4JNwx+ag=$}765)-)5e0MV zCcJjxdeA5?oY2X2>rttiQ;u8MxirDCDJ|007wcLi{)C(26Sm8HQt6ul8oj-nq!V6u zsZH~7-0pZe#7Q@w`a1ZOA4yGBG4;5G95Kq}!c_B%v$tp;hR2zfbcNfgnwq0E>PCw< zmT-}Ly21q>-WzV~6=ntD;x1<&h$?1!Vl-UrL~bu(@w90N#Kj)S+H)qZuF9AhYG zbiyLjdxHLwREsc78Xv~#a{@;V^?upJmI8=?as^UWyWBVJfJ5$ zc(rE`xP2i9R#DBQB1I6Dn`q)z*9{~k41Ed7Qq(YUCwB6TLVsvEgNgry!8 zGl+}bExp}>B5{;Wj+I_qEMaZgdvhwntOg&p$YMMN?)%unB*OEzI*KZ%vPJD_3}Ovx`;L3(#htTe7SUb? zsaebeiZfroJiIcAQ)}Ig72UG7PFCs^7-E^vsOFry98Z+ILww9L#?n(KXpS3No!7ct zw2nY^RB4D=GSDsbjz3#U|JHNG<$MWJdep(D<=oqi zWQI{u$S{LBL-?)BfI7n0n5|`ByCPgsgXx5y8qS-R!x}L|z@PYoizfV1ZfigGCj#(% zR@;T4HoE(0U)t8#FSRhE52l0a)~`-;k^*yN+9fK2_hYDX{dDTxv|qI+IR+B0T8c0K z)WthL+1)1&QXQ9a8wfZ17l$XRS`r)K{Q0AU*whyhp+NqUux3kKbd${uE8!f?&oYuX zes*S`Fv-OIGvKLy;ADg+OZCc6jjSiU1HeBuIC3t+yNVRb^|K-Se{(9r{#hl?nhUe@ z=!d&ZL*vYkH8f==6V9yM7|*Pcc1O*HQ@6PrjFPJ2x5ZWTKhb?=!LqdGq=a=hMo&{1 z*f16^5qUG6u)v*aFLEj&!lz^Yqz(d$+vO=oS?g~ZzFv0w4=MJk-C(;9gur&wk{Agj z;m~HS-DIhtJBZRL$n_x82`60s)I##IWmgDfSFR9Y#-lJVWmFlx5Obx^oRn}(%E7;L zI@={Oo?oB&#NQB3acZ(O=NsWR2LhqelO8U_)i!#8sPlIKzcW9Ob0Q4*{K!!@1cQuy zN-%~%mGL&?2Pl;hy@O$vRl)F24oH-O5fKT&Xu>%Y9#3(5Y_20Fm9dt&bdl^z_a^4h z?On_(1*4f)gm#r*rAjsi&I{!@vO3+1^S-%&>}Wl#`|_g_C%6iPAM*A&q8hJxFsP52 zPFU?>+EJ;y4w2B^8eB4ALhMZ3C}$q~Ay(F6Y9C8m-JoQ(z3oUvwqTX5L~jAzQEmO$ z?S92%8|sHc6dH2*gq3GrdLn%jh`s)9lcN8Ru=kFO>geLepG9`rrR~z;UUpeP0a?n5 zSSh<;Z?N`)3dV{JVu>XxL}N^>u&W%f02)nvC^dTE6z}gOY14wl>w`8X(36STMa{s5VUsuZd-v zPjLw_##N$}rB3hdanH-uwCA&NKDr1QH%mwFsf3kazk?#efAaY_PWzTz&eCr)f1uKD zSXjObJ}iGR6AOY}vS-WE?5H6-C8tURzt`Q>TRZ}u0=It1uk)mjN3){PE(O!3jhDYW zJX>ynrG;tOloNjhp)kYs#f^r9nZ5s#LVqIiFRZRXBJwq8_yE_1-am;m7LBjE7$n*g zGhL<6;IOdb{#V|5EPcgXgblO0dWm22PPDpa5IBfm!1{EYQn$@VViil*@z>@`%McNy z_UJhO7k)21w(_?d&4%H09auS4?g>l1KRASA5keCy#YWP*V{vs*9&eV8@3bC~Qnm_5 zBO1EVRi>F8l33-&<3?o>KDmT4o$hnBL>o)T7q>Yetqeulj2T$lI_0)m8XolHNOrIU zU+OML-zsYmRBs;F4f;y)z8GjOt45sbz1;{4v!E!`>MWh~)#pRxFxGldl~;-AQi@#8 zQpcRx9hgc(9J>;+fn>QuEZuf)MU+%z-hiUzG89YWJG7n8w#+1=o}W*wk*lyYC#Lg! zDF6<-^)J}h!S6g1zZxiaslEo+c$)_dO#%Pi@|J(T9D}r3D6+#^ zgN+S`+$>AgWu^ocvQGj#j4#Ammz{NNlJUIN$W~bEWfq z%{N(2zI{+Uk^_ab0TDC9W~?wvWkf6;kkf$gBy<6*F+lE=0@`1Q&{PjNX=NLmGBZ6G zGgr#+EH!1iKW#QtAVYMMcgR&(YRp(7|5Vz)oH@J)oM}D>?k4SjQ{I+hbktNqkb-4t zVd=yDZ{kdcEJ*I;U5Ox-r(Dj`kE3UnOYmYppX|g}1j=M0SQ`6EC+<1JJm||^=!Z^* zXX*Q|EEyuLqCq5ng{{ifOB9N|%K!YQjdK25&m|Qfjb4wo_sO_f`sN^0PgagEo}E?5 zzfo+29%GY)rRSn%M@s=dlxryI9DeetdEZ;EIUg(O2b61r+2wMPi9RxYEFIs7VLX9h zU{&bKS^S2>GP#(gQ@*oCNZMK~-)X^`Y>P}HOXvNJ4-`qt@+|gQj><(W{psjd|9@K# zd49lRn~a{Nf5-i^R&wc`Wv-f#u?6xClm0RumKOiAZQ%1d?zDOxxYSK9XQ|=a?{Tvy z5K0O-+=FBvZJ=C(rSHAG)$qKAhT;hrnwKxJ#^Qpbj6oATW}FnrX>Js{-o3Hw-zrqZ zPz;fqV5y^wciUWR4*y-+*aWA&+y7M>Om1-&vMi@~Xq~-(;o4ETg zNk=m_QN>dn3Z5*t&eHlEezq)xXRu|J{Wr8rd%2vYg<3?SOW9A}n9o2^`khc{L?ImR ziQUc8%9Zk}3S}YBeF9$>Nzhn2^k#bv`Fx3=4~ajma3kH695dCnv3 zd1lKbu=KBrePbnC*>Fa|zW|#4+HVz%`hG7Q&lqd^kGw}EBK-9sc-EXCuZfquDC3mE zLfVt~skbR|TP!VEl~%=y`n+%mvF(PMk^lCTMt!At5n6z`8i$B!1ec`C2V{`}H@Q!N2#VLi@t4f~8@74>eBtB zjNZ`utUD|{d8W#T#>`gw(a9bPE~sy>F5R*Qc6%L@lGR}8qkUU(V<1_o;ZMo{B{s%Z zxrpT~eJ$_V0V*{syXsOQm<)=gw^jw8WxkoAY$qQ`eAjY6UAr);n5Auc&+hndaa|i_ zkm!hBYNJe}+8w-~ZlXr2%+lG36F+9EN5XYzC-0;CDnKe`sn&Bp4jl)&NX3(P^4>a^ zVyT#=#YNxrpf-srKWco6$iFdAsU>R%yH+B!-ox$eo@R8qiiFB)w^T;vG|d|{3UF-MJhSUE93E% z;EjBUP9ZNsSXy)7(^SxrVuB>g094nz~h2D?Eg$dt2mcDI|m*%C)au`<4#(|sbBv((p8 zy_E^ESZ<`zmAt3!W7%r5^x)ZlvLw`b1|`1fn@}F4`$r~`rRk-Yv)ES#W&B`4n0AZo zH?XwO`3W_AuLzSkR3B{DP}XMNOIIl4VCkFbKdq8DWQ(+i>Q=}_Ed6xXUV#~QnY`N- zyoYYKOg>A0+|EU@RgzqOFVgPy!Zpv8->Uv(r_*He(0(Y{^h)XHif*8RJ)h&uS2Gr` z=L2<{H}Z#yJ$-Q2F+pxr7LvGgw? ziAsOM+OIGffl0_6PX$$ckS<;(ilxI(TE3wE9OR*{UAda9>-k{a92o~o+eby#opjsZ#5H`r|WsnO)J6D8KW{soWF75$_xq%vj^$Em1Tvccs zVL^;NSmz@TCQH}+b^goeyf(r&;&s~Q*5KXGI#C;ce8)wcgr*>jJTw z!qYK#@5U%&MLPJ_%E2P#Ux32O#3jM(FtLHGA<8J~Z0EJQ6Eb-${pN#pwem#tvujBi zqLe<``z>G}Fh7=Q`_3i zL0puHi5md#nIdNUV)&AGE;ubAadOR& zluvYDN9K;MV*m7HDlWqSQ#jKfu01{1=cHZrUbHe5?FZE#pHBf~35^euB z?(hS~jrLSyEe|4FygVs54Ad9L1OF>(TC#29L#S{EW}O{IhK&SE&y8~8#$FC4ef4{M zG!-v0c~Zl!iLU+$P)r%}h_f_(%aQDWw(c zH(Vk}5j3;*S=y)l*^`o15X;d4tcGIcsn-w4Pj4Gg%{td#>~0n) z*}uYikImEGVonT@n3f(De`HrCpeD{9s9P@6&eE_w=k`9QJ(y}U%7b+?iA>_D&J3FpEW@)jd`rSL(KJ41fRawdL!QpdJ!R>j zPmki_7t?>}DMwF|>^{1I@=Ryx&o_K`HbY|D4x1SyH^NencFWDr;e*K|9rk&EY&lq} ze|dABBsahxLKoiQ19bc3_F39J?6?0)Bhl1J56Vs{SL+7LJ!R>;Th@I^Usqvbz8a|v zq^tm?^n14nC^Os)j;GR#C|i-N45B+pO6g#o1zu3tEY%wrC0Oh=?UnK3!2AvkbR{VU zrv=+7<0&{Hg5dPNw|{%k<+7?$p%Z8Ms&un=CxN^M0^$K z!rDym{;;=vhJOgQL|Lpt4!RO@}nsol*uC4H6U8|z3&u>7-u`Bx0vk; z8rKwE94hhb`}Qyt&bCS^NO%(6I`pH`g}JAGWNfQU5JA2NriGh-tofJCl-fb53t+t6 zgvK{++fcm~9A$s_EPJvtoSuEU-c84J8LPw6H-7NM#~fsChR}p0rF231NBB#B+j5+2 zO3A{Y@2HGv%isw3ybca}y9u`k-f_ku5q-yxJ5ApfETL!Vk9*D!bqsS&)9shrWa)pd zzjebA?3yeRdOHsv{&k5dZ9*31xZWbfaR7I<-jR(7OBb9^JnFd6qLt$-IR-gH3%!@p zV)<%>dl6T9stJy+f5Drm_^llpk1=hN+jTN0wH=e<#NH0;Bp*1KMe#T z1gfM_nN(*^>4c7LubEqAy3Q;}Axl0}JJc_7^#2&DM|<)I9HG)?5oy=mnD~C6q4}ZZkrI7}HFjQl8s%XRq8)wE znr3)~5B=2wPopw94@Y)(E3!V|jOs(LGNuZU!0tCM})W-c&jLhtgn)AtLM|FRnLzq2oGB zsI))gH^O&oxwcgMHzVNFCa`#x*GGqb@A-##YS1+m0H3E_?@iS@t`z}XOTE3hmgM;l zTFqwzCpJ^#4amm!d^>7v$9qz7JH88jf07Im-w(Cpy{KDzNI^qQsgg#%Um7SC?ATk{ zk`}cG7F1b4wmum2!fu?(QQbd?UhT`7Xk#CYpe{BJhWQ(STKaOaWaw-6WO*72>%%Ri z+)TSKRR#cw2;akEPh$0=L`-Dv3jtZcz-qd33&`4?bEU5`?S9Q5oPCg&o{c=z6T!Mu zbzi*Z{UIUM(376!@N&MAUUl?d7j8b?>I>Ph_TwfK5TvkwI!2Wb9T&hLk(QF)z+BuN zA~n31T}Q)vf{d{4c5ms))(xJSn0K`oH=AmEVyt)d;*wYu4b^q$I?~hLb}v?C0#)^Z zz@Z9$v??3I%D^1e_4PQ%YkbFY5daYV7+Of|&IrwE&W{p~Vs-({iz1HzbK!78 zWWNsebVoQVT^&Oq^ym;?Ejj2ZCS?rejwHSG1Tr+#P>X@v)2`G=JFcRaV!PTQZGv^Dyz!vaG6DZY-6`TjL^qtk2Ws7E#W3O=#&h0OcO0WDHUWls(!^uv-yURn!TRPDfgr~L%?s8cA|&-O8rS)&YEz|Tvl--{AWd?z~nd#Rd=<3Mh)s+^}{6F-d-VSmj+YK$V)z z`_Rf{^bJoI33J-rQnz*2$~~b)Wa=7{cokjqf>9UALHE)~%vV4<_1vlNysL5 zlKYk#PM3C+^t=e6`;|20{FP+gFXq+!jOlf!*uj(aBvcY!m9*-&7peeEM{DZ2Jj!)K z*)^d`q=qwS^4>{q2s(x><*NWiufu5JAP$CV5Vwg+)No#Mzb1~n++mPLU20;7(Sy@C zCI@nq?T*QsFO=d7N3N)`;V@;+~B4X;+xY0%_FHP->3 z`czV`8gIAVxm3JqY4us?Azdbz1Ws$@S7zTsA8;u!3j;!G02-MAB30!FEjK*s=tSr*0bT`;qpr z@1vuj?MAocyy$olT+R|-me&%P@Gp?6y0r|T#Fj9I#Y-`9#M0G4Fsr$Rb~P2W=Q@=w z0o1e@<|$O!y&Tra0J;?b`tRV4x(09=$nv4$z2P2Y2?U;H{@f^9Rt<%DI{>1KY9VFp z!E1B59uHlqW((AtXim(@oM+i$v{M}e1AnijmdxWqJ(;~oq{~*2-6setyi*bUXx0@+ zo-vSg$?#(uCSkf?&4a=;=0aOnhjQU`C78>1l*9$mo(L|85-+-80(ODjHgH^u!x^Ke zqEPM-6^6paHpY9t*dE3Ypcb)A%G%^CE z8^@QorKcR8u8uQW0GrJkEdV;GJ|44iS0OZ}Q_oGJx|iU)jWz|J-X1E(hGoiUKlsPQ4$+YdX7s)hvI2UE+;~14YSxs<9_HKZlvzB2r;M_JZxVy2u)&J&2#bagiFKkSi{r{)}d+={OfekX&Q?HD9O+HQAU3Ko;D6;Sa8ZlnQA3N>5FN?js>m9I zr)!JLjS>>gKzmEc$u5lMJSnfx?n*o6fBPQmEUUV^m~yMmteq)l@% zIi_}mZ0gd~bkBj&5erLJVK{15LvWvB<~VHWO1fNvFuQjeq(7a?xzr=}q;}XcU^m#PFl1?ML8#5l?WVjn-MExrUy0hV?Q}kCgx$Qm}q0PUD7CwgvxCUq@l7Tvvy-k1y$d zY8@h?H(FpTobTCjPAvuUo&INQdG-J!Jf#$79^PvbG;~y+J;jUdehy=IS8*T+Z;@1! zfd14F#Ir6M3hiD?jy42yCP;i&+T9WoD)O{pldRjtnNS=Jt!4fL(>804Lq{ingu^mz zT15~o{2osyTJf1>zhhYTK7*5T7p_L_`3ir^y~{0hI3FQYcozn={!#_p|3{8MvNeK$ zlFJprtcHnpe_s*8^33FX>@Y~BtuIvYQfa>@fGGGKOX2E<3O|f;FCVfr0F?+UA}wwN z<jeb(U$-#LTtEDfvqb>0q}*3d5-GGddhA@)I)nwuI5O5 z0>_~dGylwa;J8}kaAPivkxmKBvAhD)cyDZlmQLPB_ly5TmC#mvN6P&b#;2$V!5Py9 z6kNH*EvC>nDvXr#6J8s>hhpn@t|9_UQM^u%hKrkh0qS_V>sl`=VW{GZDgwyx3!aYr zf_0BrTKNq|zQAp*h8|vn#y`Hv5kQ9++jn1tuTav8*GfAFRb#=GGu=U7$v045fWQ!p zYkIxBs6t2CKLc#AYHc8CzQL3CSs(z-K2$O|+mCizktf2w7Y)bvV964 zBaAIgTT7Y<6&0U{9vl4)JcfqLum_qy;WPq07L*s5iJa*Orf1ih`cagmh+xsOR;*jCq#jw+ zYjqTQ9#zi#hOxYNA4sRYjy6uSVWdm&D;n>E`kGr$#4wi{R6JV?rZA&jt?smq=EzC{17VM0rYvn zd~dkWcr|+SN}B!v>xbM;711KnvPaxdiR3BU9WmteLr+UM9)7qt=sx)u*N+MV!IA2% z6&l**$M+>e7(a@=iVTXOH76bIsNoTqaphwfCp~-*RDeMy^3(yg_!_t=QhV!r2Np1_ z%iil z^}g?2hgs_6nm9#_RM+N%F@;CbkCyKTGyWxD{dMra#*N3}(09QbAc&z`SCJ<^8UDgJ zVX$qIP=xIT6(UQ;-apxb;Sf18*BgDVe4`>>0vn|T-NSW^4{tlvRJ0rgV(+aX3Vai8 z3lyqIY4$0wPi*Mk6K)V$Hdequu-P=}8}LhPDEI-^Iik3&QD7v{kN%W?!y(Ru7$#|v zk{+@8Lc-@A0mH?HoCY+GIWdCf?W=%86Tr`*#;?HFJWsF$YM?cHg)Fc!vH2?^rM$oW zfZq8V>P@-@B_UEEPKS-_DxkU^aq}ow2{Lx5Q15~sLxj0AfDMtFEbmkp7(N)xWvGm9 zwWjZRelScP$Q37Z$wAB*5oy+eiZ)Wuz5fA=D_2Of4fFF()3pBU6O4jbxp6h-Q}uh8 zz2dkv{^*clciab&pbC-bOHdPHXVP~|!)T&q8W5RytVw?qJE2ohr8U(=U_xFd5GkSu z^+TlbeG&|a&ZpRHVSHH~3MPt^`R;LG5vSW7j_*#Pe?XgWih?%xTwLKzmP^o<8`bzF z(BGKZu-(8^pRf`pLM(s|*O7C6g)du;Ah>^>3!uW)4*zDQJ7+bSKUUe%aL?6|cptwA z#0;?rp7c@s1oPGqIzD3p|h?-FJMEG>EauB zTHe6&P}zPL+ZWflb|M9*O%s@uV{iAcx_ldv8K-z+A_%N_1rz-rz&TJBsnq&(Y(sfED{EQeHb7x-p7by51Fz z2x;>HR$N1Oq9KFgQ^_xI-=??3|!>s!b^_<@#GI9AVye9EAZ6xsJ zorTpcILGo{c4%nAcQAZ_2$ftv5!Nyqd=gDGUcD&qJ8&`NWprFL%>SYt)6i3ci9YHkx zGB|a4K3pN=RXpV`bZE=2Ac#}&rb8(a1tc0OxeDLfb{T?qX#t#vLoyVW@Z%w`eXnqP zn2(jjsK9pt&G?z(*b9)gp08DKbTtxk9sfOs6HY;xqxiB~+I|r|r1)>ZM>r5()OeA@ zu3;|Z4g&?!X28S7BPGE^y^ z#zy`w_7r!%kJqqrI6YqDz^PRT7fP6s*G(!|Jr>ULzXelYXFas{U<|s5% zaa;5PD=H(^3`V5HqdiD26NDf{vjenc_x5UI446x;VI(x*2XNIyD5t zjmkV_Z$cOA5}|>#gW;|0Oo#A`jW@OCB~=bhhO$M_rxlg7huKOP!o21jh{T4u35Xk* zAuwWJoWr?XS~HBBN_m|fu8!(_SM0N*F;EdqC21IH5lP)h?7CE%ps1=@|InB#rQ~1* zQk(>@Xv284b7TppDtjFY1P`g?jDeTtjE1Q8*$VMp9tS${^fHBpu|>`}0H8`Vt=@vt zVUeg;vK5oX`VQyrDB0sjtF~ZD+}(x{+0-Z$I-@|aSa*R5$~f$8Kvf%{!|~MCQU87j z&EEz^;oM^qAsyBa)TG;nbvi0x$+rd4niT^Mzq$>|#kt3mLLZvE=^6)B$FQP4cF(q8 zvvST7xRcg-kf`c|2(YZ0gFb#KAb2r)9-7o1K*RvN#LhFSILwQ^sD3{JU%(+{k!3$N zMBL^u@&NCsUmQvcUqQEXKg8bnwb@d>FPRS7J?Jh&X%xy^5sxQF{p&``txdwMnNRG9 z_|9)a2}EJ!`BGD(^{>ZJ{1A{TQVEKDu*sC9rs4CrHV(_{db&FYtUK}%Ce-q|Xn>y! zU32n7?5BhOuqZzvk|j#f^4%~i#nTZPs-6Pv)Ne|gR#bf-!HmKMs8?M80oe1l8b5Kpp&n$rybCPjqgK27BI%+br6CouyUGRO!I6<+iP~g9vE4btj(y>umeGl z;+@dCwjI#UK|63PVE%TzqB1suSf0l&uv450O=`9at$G)frujjEimF`iTH(WD2d&8X z8X#&sF%_o;JFwaG8s=)lDpyKff-akvaGv&+COTZiB_P+2HtYneSS~%95A#tQ3O^ug zmKtYKUjvmQn*2rFO7Y2&yApfkuZfVrr-Db!Er2`#h?A&jYCA*{2=?l*u7b%~%=Ies zh6;hn3!~y9M5j*iFqgU_fFD~3uW;jHZWtMKu!`a!iHH)5;Wpe^03+9XF~k}Fd}-7= zwL8`N!(%9!Aa@omKrOOLgff+Y`r^FBARVQAGfGz z#jJpA#V%#QWYmtv>$9KB{i$FI*Q(4DdeyX_1*SfPP@nn``wC&TAvFCXOr+}lAg;y@ zg!Fu1g64h(snCAFC9Ep~=U0Bf^~3{C{C))Ja~~k^i>e0k6)2Rnzy(9Ys?(;AFwcuy zpiqnyi`KnF2|q9X2?B*D_o0f{N6?cE`!TFV0-UDCeK5M9s22_2kAi>pVG^9sz=(^2 zu*m}sfN1O=zl#Ca)naz8u0=#q)M|M3q)kWcUbJ%zx{BAaStz08i~`^*_*@ z-Ur~u7JQD+v>xCJ=-wyT=_$Al4N#K@O6nWzQ4)zL=q;6cT?N!vpMV3o4IoS$tHK(n zftp|KO2?W*O2@NLqR8VVjJ%lLX)k2x-X8ewjfX=h?S06zbr09WVL2Q@xAwxFTHk;z z5Rq`yA46F;%iZYOZanGU>f}N1yw4Rip>Ev_Em{kv+YCPYX1U7o?4U30cpq(6A47;% zw-NLG&T*)v-P6zw3w?wcTdxu4oi;*+C(MksGbIkJQ&rCV-P$Lr#SNG(aJG^O00lZ^cnUQw=fM~dJ{f;v;%Tl z^%i)Tjmi4+O0Kh`9uE^&VRk*uLL@eUAlC*fq<%^%p3-~5b-axyN6AJN#gwpl)f;N% z=Qoj+y&ew?vf)jJaDyBDvKnvKmP1?AuT|2772K;-Jp|RKtwTd4aD$>*^{91FAbYw1 zb3z%~h%5zlMux(MHhx*dNa+Cr_LKoA8_H$Eo5=dv4j^-TIINRP0CaOL>g!N{JF9;$ z9rdR(WY^F)TAhQQ#IFU3T6FGR^pdK9pKdtN(vKzhm$w|RZmHLWhfYx z228ux;k9}>Smo>v1iMh`DA|Div$ksbGXRFXz8sum$m4qf=nex4Th3)VveEaO%aCte z35-9Np_Q$ykCO+&dOR9O9J3SA5V)LnwMyz_0jJ2gy(vn`@M^^M)g&~~I- z<6xO=7ob5|D^z?D9!BR0P!p%d!?~%O0JFYk9Lzs|340=FOCn_DWX!etNt_KWM^JS> z>WAfHSLW12Z06^l$E?{i4y(~6Stu~}LL{;NywZaz`|`c0XfZJoyBKy6UMm& zRSGN!#}{_w!L?^tX^XGs2Bjex6w{5LNABJEDO49K6%3)r zf5JBtD;IR(3mB>hYU~c!yuY#36rWav0H64DnH3nn1v~flK+hXSV+RFM4zOteZ=$T$ zYrRSTwlsLymdRP`L$_CfTnq)QyH*uM`LFXmsAA+=adSro%Pj&JVoLI>vBi2d*;ay0 zz^9?r*%(3FQw(x(+Il6?5XjK#hmf^V1z=s@>HLVY>q-q3{sb;{7{c$TYdHvv*WFaA zXn78(-J@OahDbkNLx$lM_1xI7^&uO#UQ4zNa88s3^uP>EB9fuh&v(5CtsKY?qUpo1 z7jVW0Nd6fD_*@Q8i8(093taC_?+(Y)E(?&1n85cDDM3E;OCUONdH@OwLh;&n5I>wz zqNRpm63($?8p4lZrGC_L2=YcBr&e8t?9Y*? zx2V?(^%nMoU~5MMY(sza^6?;miM)ER0A%FP0BI$0>vi;M9>0UMg8-`<3nHJzVM4tc zg^6O#1OJ8>0`u-aARViwV2B#@5U&$218E5x=*nsQFuFXfY1qI62znu#OZPGEhDpHZ z-5sJdXC7u+-3aKSO>DI4CPK1+6bt5jR0+z%xJ_&g%;yKA-sm^LKkX=hS+enZH5(1B zS_Lu4aRs@Efy#6E_DXa?Hx~jibT$~~?2p+rc{Cs}k(G3ECi>BF0l$@O+3SPIyE9Zo z@m%P(iLZbH-5kuOT$KvH#q=sDShWZgpq?+4yo%09b9EMPmhuu8KzXOk1el@wdJWxM zgs1JZ!FE8XNjr!2*A=II4D*2M#C(W-zZQ7q=i=2i3$I~aAo0R%fY}yfRFBU?_jLn7 z?&VjJx4Z9pPdbn)(Wj&GB6Oxs4XxhbsZ!E=uK^2Qed*^wrm`7T#)V)`ej&Qr_!_S& zdy1KLn$58%vmi&)7-+|Zc>Q=5L^oIl!Db>?3@ZbI!~1c6?>|@D5QH+SJD;8^LhmeyXJNNBWhU2`_il9FoicPLSBQP z%7=`pkPKZ45Lo@8-E+rc=pHWPhn024V2Bf;`YoI@U9*fIORN3B_>pg7G<7K`h1|(V zuDrz`qQpQn_H;Q!sm>SmPQHO%q|r+zV-d9iYQ8W)rJ=>+Kr*Osqq;Ge62n$7wyr>) zQ3-sWuY>0Y+hH^dmx7*#zPyS$^hO@cl?UDH1-AeuJCu5@<~Ne{7r3T-JEM&%-C9us zdr|1G2u+CQN-SOZYlYZTbd6PZ{#GIO6cJ$^I{9G=C>@@H&KP|#bl$1(d%`@R@@m|{ z`rO5gBMj`}uK+vHSt|9QL+O04vUEVz{DMsfAr1L>awV-N6at1shT5%_#-$gfYJqO( z*KA%fC+qK?JU04v^5Jx*BbKD8y`f9RS6q~bp_gChva9ez2^Zc66Rx%QVb|7mY{ErQ z9`U%+sV^7pG>*9h;tY^DrD{s~)|42Gh?3|i**5Z}bfyZ*375#jsAvn1Gn+9=#JtMk z*B#lw=h3Qoc0#BOe8{cDM8Zw(U@9)dpyrjq)o8kzJ(%huu+B19^P>s3tp}1Z%8t$S zNUZcXR--cN;dmiKFWv{QUXOZ!z!9l3jJquorlevc|2E-DGY%Rt^c~ts4fSOAlyg~Y z8X6r7ZiuD0dyK0Vl^_x~jqBK*Vwo!39u|>SQgjd&y0sUTpHqlmBt-jZ*~w_guqgfmCpA;7jR`mu6$L8SDcuZUyJ+^2^hIqdW~Qn z?LdlsdosSIs0BBUY;UU9V;u&nCICxXRM|+iTj1L!ltKsP#X?cyA}X#%ZRfjD!48N@ zLxSC%N)q9w8(lzs-n(!SLoMYY?7Vq5cHUH_C{&%Xmv z0jzkNQ=>?!3h%2`L{!;EL@L~Bcb&>oyzfHGR{UzHy-=T}_@PDB{e@YIc+wpj8BGQI z$0@50F3M8qtIRjz6gacj^H=xUnvGeCBCo2BJF*l*YNwWDDRNX*k0?vwURCgVmI9H@ zJs)al;Flla*R((WNLN++MwVhOwOx|uS9`83OA)T9?XV0jXz13~sqVEIt+EskJBW=I z)Gk?&r6^QXbxiA|@UE)gnWeZ+PwnG8tM={6Qnabvhm4EH+V-=u6#djy^EQC2+TYG) zDeft1%`>wUo(ho)4>Gjek9$xv|%Sb%oQg!=6mI9Yr zcJ5bKd6#D?c2w;_RsSj*O2aS(a&`1LZNF!g6EOS5%DSpPqp}ozYtMiiiIad`l73`tM?%%oB>R-xITvkx(9~$qfcBps0Hg*~a zRFLxzjk@;6%UOypirS~h@^Ptpi1N2<+va8|Ho1_?T(=O)Kdd&1Pr|W@ZX4XiM@1)^ zKG7{im^s7kj~2qDmFk5$mfur?nD>_YH2wD#w_xGOa&?YE7&K13(}UhERCl1K1?ufM zw5awG?iH%TU1;OqCIh9tto9}I6gRc->P$5@fTm4!8!m)wQFq{l-gDjj)WVKpw{LwE zZG>XGTbxGtXM>wfrAQKbZ*l9w35|!`D)DL3mFfV(qlPMNF+PI&sN0Sng3(>Ab``$! zR`>HFSFIwJ%n#j03nsm~bq}dSt(U12U4)6RxNT4fH#VxBuJm=PKABc%y1P?ie7Kt4 z@*5E+B$>h|d*aw=xG#+qlKsh~nS>u!+n$nK6`kp?@D=8^3SR)tw=+JGioe<9Lwhf5 zQVE4`#J}l+ZQ6J(JtO>qA@9{SL^-i(8r&nx}#L436fRiBB+`H5|xz&!jAj{VE| z@m|78d;B?9D(P9Jq^egxaHAui#^Gl^QbT=&_BHYEw0K@!OV`%EgoC?3;M}I|>sS?z z01iLUF8X1u48 z5$`5^aVFmEBHa2Zej!c=%#YUz?@)ZYi!lAu_#~W_EokY6udwSuXUf;fnSSfNNGfWDAA<&2{7!p%QSHPW*m zBlYyt-^L&s9+es-^!dj)-bE_5{D@}%Wr%ITM_$4+*YJ;AgxjT|hh2n8BSR}NpVGQ0 zDe)V`g=!WWVsX}0t)%abMlbqoN$5Mx8hH!qqN5R4Ogg5$ zbd;YO>P^Ml5;a0hUTCLC-&|Wy+d$lB&;9?EF`UCr4b@OuVVHkeml5HVmiVDgIIu2s zODkG*G{=q39}LBX?GvHFbmm}a0nM__(UEaVq${;HhIt4zhe8pWhm2zz;%d$u+LRR2 zmJXlK@uoG00SqDKs|;s)Dm*BR2WuLVdxulwaZIz6PjYfvNJ5-^IcKX29Xg+bGZ>Fr z-Jyo*mIw+PVDS|$AIrIi4PqHnTOnP@*$CzLMGntqhe$a#T~8RW40*XfFCi|xkW<=% zO8iEIk@09ecB{Wh3=WOwwqM!j^JIl%AYx2dOCR6-b=< zgV1QI88FmOD4A&Liamrg-C)a?gu=mO%q?y-;m3=e?{^GGj3=ujSvMx(wAp==lB~Y% zaiH(NCQnDjyZ+>H-xNxwsp?<>Pi_kG+!xwWX!yf)%$=r>*ySnw^UPGQB=?owBWc?0 z);PP7o)`)B^Py50r;5|N3g_M9`e9SX9j5CuZQM2ut=MI9r(N%vjtjxJOdXW$y;154 zdKxcGo*n;M3j}OUxXHsPu3FhXoT~ngYxQou(lmyQ$2vq|Rn`$#16PMbMdevq2}h2_ zokJA)ek?9?%OE(r+^J(SDq^};bfRfH~TsM;q2N7ZZ*9`sOYvI~OBG)YnRtw}8$dl>i1ESee;*Sp#L zg9gMcVM~rDPS*`-K82izlibN>>W(W7f5f&V>;2e!G*@lH$pt>nk80LV#>V@o;bGG2 zr9WcDdPd_TxuD26(>`MErAm49j6isQsUABg#iQN+Us$FH%VFcPnoNbHX{zF zArW~;Egy+0Q7ts{ljE8`|9==`d!L)ilN)H=8wyPm$fV z!s^SA6z7OrE9EzsI!4o#S#fHCTN~HIh05G5p;SGgXDF6VLv^HG6X7PDD2sbFMwUcZ z)A6#;O=e-|Zd00qbem%l3{33Yj!KT0{Df0CO~1R4`6Pba*H)4PyLrsCuZ8gK8PiCG zP=3MGQca7Fm|69LiHYk zIaJ>P($q$eH68QsECG5P4ny%P!Uv~9PX-Covh*k11m~ZjeQ}-n&(M~_qMt(NsXw&q z7vk6BWh^+&u8+f66@6!+p^g3x4|4v}*GPNQ^jX5rA^KaMg#Xe900i}&&=YFGI95N; zQ+Sf5?~Cc(3`wBWaz%mu8y)pJsz=Q2gZ3O0SB{Zvv75bwnq&GtaNjQDSP*n-4ArF! zOs2-WZC6osW|XPy`=Kh*4ebd3q0kae?=9|-fFDfnD)3+F&$S?@SAQcF zuT8~Q^*-Hx!VpOf7xcsMJy;-o0V06j`%#ZcVKFQxo0plRg6$KP zLPn(Fcbq50$O@B+_4Nv&_nUf+8*S_me&D&e^Pu%7rh1b9m-xJt`6;ih(yxri5%W4n zvg`lN0C!S{wQi<^rl`Y=|F>%2f6af}tlG!l@aAT(x<`j_N44Vujr()UK9WlL&jN!} z+-J`mZ~VU){@W%Xbg^Ul`%f|MJ~EgpbegRW4+C%BMGL=z53G;+ws`7W73J zO`UyM+dS|6BgxHPKb?Izy3FTu+@m_naqgi+~K3J%J#($-1R_`_!$_uMip`U96 z>(||`D~0XfXHIHC#nG=cHA$Yrg-MqA8U!qRYH8sN%U*J3r1qxVnSz;~42*!f*nlg*by4jDsbOXq4(RFz z29UYyh(ucSy#Y?`%)v0#r;R#Ft%(m5F3qxpDJb;D1_SN+HZhMH7Fhy>ggKTkl=$sj zJx`YxTC_BMi(8AbFfPI|izSgY-RvriB+GWp-*K7Hrbjz@ z($;DV4uCr>YAX4|g0s&@tQ>i4w#3slMSENYT#~I?*Q0}uuFkW%3Hl9|Ay|^$%rf#;}^%M&BShnFj+RI(sa5=!@N=GWgIZ|)UG?B4>yBpPSv*11gGm5$| zCL$KQHPe-*ZOzQ3n(|g|WZ9BAKq@tU8QGbfv&>kEb&XaDh7T<_=b!u<5*I zLJPs;drQj@_m=t7yBEwDKW6MC>i;KnB}h}zv!iIs@`t6T`}5L)6h1!FM)9Ra92fj9 z!-pRKVF}VaFQ%_Uthi|yU=63bZJl8N8?PSGX{Sr%ni_t=*4=jOX ze`GPc#~EABoHcD$Yh!0A^X+XGe3`k?8uuMmFxTMl%k>I|!nURpFbNHAqs|A4DA0p;!ktwu8L?u5h1{jGCp zR#+w`;s9%as^!=*vsj;pbPjUQpE+pKjDk61UYbf{qOHMX9^DexQO;ta-eQo|huU?+ z!tX}UwsDlE%79N~iBnUfDkiKoK0G|DU~0jf@iSst7Q8eWzuekoDt=HhYs|Fqt&M4E zX~yVT5?*SUwj+?L-MhiU%2WlB`PM+SN~8io)&bUN>N(K5oT@*;XSAbUvW_a-ZBi zKg*bAq}n`ds3M)(y!3h))efCT?{yqi2AR9cXX!|-A@n@fy0o{Xcmg8b>TX6B5d(wD4}a<4z# zp~p$GcUs|t8pkc(^ubt&;&acHRt~o&QB_*BN{LY(KZx2Kx9F+ihcqvtWTbVRf~wP^ zm9DIa9*?r7QK3pQ&M~RgvWSeQF(a+Gu+qYSy<0YU`;M{ZHzU&aFbhGgfmScS zmh$MMy(Xfmf5>LU*BF%$1b5-uSnIkhGOxD;3Cs6cJ3vOhi^U;<)FEo>Q}z)yy(%;O zDf@1#q#Rmpg9= znbDs5KANVcBR6@RBPq@BqqkRPY$MywFlfj!xJLt5WkgHM1rcA-s*F^sVWr035>@o+ zstnxJW3S?HnfIov>Hew=T;yg8jOm+`;bg6bs_wHo1N-Z&Ud^jDKM92418XIs2^*;WJp(Rf0Sl$^j9f3 zWqdyd-+uWt8P^Uv_jjddmFYMyFaxvLYR`xvZ)G>XvYMf|G`bVfEZy}!u4S+HaHT4H z2Cj`+4xSXV1s0eZM0-~amYG`8tA~bqJ2LDNC(x=dE{SHWkzU2pN9)jm znm@CH=-}E6gx?q!FRsnNfo1jtTc)Bu%gW%E#&p36^K}{N609-3n>Q_7*VOOoa(J@` z*I~THp=rW=Si)ld#ehEkV&KcF(!J=nvL@^pWZ2ms2Wn`kzm2DUl+jj#cW#VPuG`Vq zhln!PidiCLr}B)qo@2!4L9=@x#B9${(hubs;Z*oV7chWn12m7zB9&MOR503 z>c))lChPmHpu=S@jU3qftK4qSn=~A+U1~UZ%(`)zyCBaf>idw;Zz$tOv?ru zSDAYBzyUfo$s3&35wt8RGl(irL!G;9K&aUKIjr=*Q(T;iAAW6p@V|4ka93Ig<(-Fm zZv4jj^#5I2vT>kF=y=W=r@)uUy5XYO^kE?s`g0#IN?y?l%sJClMXSEWLj2edseuxe z)wM9HpsgRR{LWhS|3Zy$h!ZB&^BPQO&4e19QE$>qEnt!;e8*s1daFRpzU-QHz-YMS_w|VBywS~HnEtcXinZyURLI+L3#{P6jMk*JX5f4_i*Xco$nc~!QLuUq z-7}3;G%{lvS$s3pw5DAePkgtGmcs4dt$D9f?w=NKVcN6|e3jK)7^9?)?}JO`r7#@D z27I!k@gX#zme0UPhf=K>I0SFSSri`gH7^4*V$J3ZU*XZhj6ZP0A;qAkkT0zs!kP^k zpG~8Nu5b(U-1_??PGnRHg_=yWiE}lWczzB7B^gFps=f5W=+Do zE5~Ij=wXX)h_zj{cnEvPXI3f5Zw4GKznPgn!s3aU!7bQ(NZG7RH{q+vnQeV>I3@Ed zDjAugqWbmNr|Hr9fETq$7qDJ>ZtTV3KC?;CD01lim;)GzMVavHi!%MGZ|ehUy3_iA zuQbUD3fDKhET+W)IwD>%M4sQ~6OC^yj4|6`4N?$ChTMVDWRZOR#WoLuM;Io%t!>oAL(d zQsqcUX1|Hs>V$2EDq@8d7_hJb)5kOW8|VTR!VS;`)PkT62x0Jl~Vac^wvZWXKM zZmk2Wt+RzXIBHwP4z)wY*4C=E(%NCCXqR33z0MOx@ZG+@pWpZMdj0&vS4f_5p7We@ zpZmV<>%Pv6ndTUX3*alN>*}iKNo6(oOiK?$0jIq-VK6m_p?bCX80<*>iZGdJQIwV% zRmm=_-^`3$q`6$uyrD%D1JRB?z`|9r$ynHiBMi_isDPW-nC!&DcV`{}l-wDt_NQ7c zuuIijO5hZC^H9MV9E+0eS7M;SF)Y-TBF7<`Jl8zLowm#S#Hke--V0KK9rRXA+t83#Lcx}-Xmk75{uOLbjw~z5><(nGtWL*3v*dLLn#r;%I=#i`5WloB zh%aeAz|-AfS=r_vr0>J{;OXEFe2P!&JhOn#4bF0w|=r3p)0E{K+Z<)4M zg|u|PqQ7Zip+~ZG;X>({X|rl(DrCa>=*iM~wd0~vv0+qJ&8(>z)icJ;P$} z@GS6dKR}a5eVJ*;qr}cuQT4zqaNonE0B*aVLrbDYg+G6e)Q6tKqB;NlLCgmVPZDQ- zlEUsTuzZm23-&w-4(xdl^!85*8QpjeFHxh*a-iJ%Eg+1?;&m2vARboLC~R%{MfiiH zP{&k&h%cVVf`HK499Z2N2yuBzQxNXn8;D8LQP7X-UqV*|uZFUa^b)Szcs~dx`a~Ag z0$O8`Nh!#2*wl_;BW}X`7j3PvXQw~RJY>b;N+AS??B}SgJ|x;GN37C&^r@yQ>@3!#fL49zm<#%!=!I z!!Dg~xT|M`-+`=soC(rha0HwxFZj{YwkRadw<5=;IS}u}8ct{825SpbMZcRljeO5#CjHx4A%X=UU0xQFc?zAa z9S`Ic^jS<6q$&?(K^*B~CcMkglptDnJ#!GXZc29TZI8SudRMYHd;Wap@LE#&0IRBc z8IEhSdI7UPx)~!qJq^YnzZqtxNt}vg!1kaZaDTJ9vJb5tT?|iYF3^URKjKzV zbIaVpv>7=UHxs^qHT2lzaR?;_dbuP2ew+_P$*b$;71xfdtDZS&T1`}{U;%^XqPRRr z_Rl|hRxA8_UB!zf%*%2^WwfarxiVF<2UEQ@Y_2Z{IgvL7-b$*yy8}pcXSWmCdZ&Gc z1aLAnL??QXzoP=eT6cq0rkjA5{C~~xrVGWGL>GP1M$vMc7yGfr{%L#Rb+`Z^YE>gx zZMd8889V8f9OB3tzt2E+v;8=nrS0kvCnmiytS*!-dwtk`I6jNe^Fq!>Ixz;B*JowO z`u^mPFf3vci2EZ`MeNJ78TT+*zRy6t@%!Kj-_J@*BYi)_K@Hhy;neqsj1+48AtR7d z%QD>QolLQROHNuNRQ!I-D1}sXS}RSMpXos#=B4eWj+?_kh`c`^Vu&C4+q0ATY4KLH zy3ZaLTAUBq>W`blL^M>LR%h<`lj^h@dM_WoqjdCOXcGOBXGfw!K&x%v?2RxL1I28= zDG#HxUk}-_{Y7b78`59&cVpYN88L3wQ^(T!$IE;+Rb_-R_o|Eyph8^4YT4$eSw;MEDqv6w(3=X@M~|y)y!t3>`lLOZnhjF?m!B zMliXy7-_NTWpL7t=MLv?7^D<_C_-3Opy?wZR?X4V0`cZyT);#Bl$ZZ zTP*9de|XpbogCJ)DfF7)@xGO5Y2SZo0j3P)(R2L&?2Gsz2WC}vl3F14Ksu&49q zVO(mrC)?8SoylW?!zTl1-GN5ymz4Rqa9`SN(3G^}spP)2;<@Am^O5NvshsHij^qGp z7b7}acMwKLy))T^nkBKw=tTlzQJpA9_$$hUKYO|ytI|`+5Hk7#KuG--^gu;pGU_q^ zqah%qcb_Yr|FVd$6}Gf!7uuCCP4RXW{CmqbF|_IVOrk!BcISVjgUE7P7(@qC;VoA! zMaEtDq2JX(P$a#j2qM){Xfak@s<34pUnei}w9T%YHkGD-q?4J?+n$r-YPyFzw*H=M zZ^wTuCC{saprh66WWvdER{BRW>e_2xQus4p_ml~^HP44m4o~@>RBHn4P05)4BbStU zIGg)%%(R-ZG(93^dC#v-uIasgEsjo+Q{yOQJk^d@h)KJo%>SX2`#LJI=+B%uX$D!j zruVh{6(^(GD>4Nsuz$Pzt5GR)dw%_gyF;mKAVeEGdzrUb$(>o+_R@rYWaFCd^G`Q) zVWOCnzhM9;PJ<(U8o85oS5qC>NlnUMTj@dvq(Q&$NHK0wqC&*UoX{sP*F{3C*~J7wLUg4OjGL$6ck&~@J1H^$dAp46>(HsoNnCPl`kfSSl7Cv*mwx=K7>WMk zHIQ@uIc0gzfe$swV`N?cMV~4I8FO~3D@oGw5o)|^^k8rQl2V{#b-}4)rR>JARFf6q z|6!~(Gxbm;iF~6WWivn3l@-rU{dgTkPuCBCYndrF)u_Vg#^(lJ`JCy*ej1$-iX!#y zMIR(e=u)f&PNexP6#1zE!JbU>WX2GMDKr`TYabfek5nITjix0*%#L-~Wn8f*)i?RJ zOzoD@4{=Z(7T3jhGb{;qZ8w{vEi%08&xn2LK~^?a-Hm!E*yKx)4~+nl+QpemV49yY z{#wW`)MW+h+X#`?&6&1r4;dzcUCX;t7?$;~hl0rV zVQerJtu}fykEe~5w$$i#+?^(-fhyQE2{_}zCk$?MXqPdNoqxg*jl6g&)}E@hhUe+^ z*%G)er;mY+a9}q;yw5@X`^Gcei*_##_oU_P3}X7ELgLN7TW1&ru2QtIh+1bG<5)qx zG1As_xzLVHU16MOO`^9OWB4=qp)7E(Gc_(VMDrWMAbwzQWIoFc%AUL0(e4$7XUJ~# zvw*iJ2V?c(w{A_|=0q8lfnqwj(hxvVJLe)J{;AxJzF%ipM>g;7$)l=eAj4047NEuN zZ45~HE1=kRSj+9$z}1FqE1`7^tt&;xtp!zZvIq*8>k)pU5P@C$0_D=tRvm5HO!)~B;{D+Jdm1GyU1=Nx+-#=7nbplS#C5(q{&e*1W|bSwzcK)BdRId&9^tX) z4C&y&&R;H-8FmwwFM0K{ddbioSIgOtdkDW;9ox(=2%n1ufagDp9;km zK4tLr+A`5?jqB2M)H>yaJAHaW35oW&U{Ct9S_yHTjX+iZ{95VDI({>phEwGbE@F%S zGW>2$TiuPo2n7bPnKe#Hw}+u`a45(&ZETV6bOjw-|PTA{=Z4k7kKs zsksuO=h|J-2&6LJ9?;jcIb7T_*8s}=r+hjf90tzh2_HDaK487DjXA=CIYHLW!y zkVCd{<-@kBt>GkCIm^>3skK?=Op!n8f$(O9LsH$*Xirb)7<0@M1E#Bi{tkc-AnhAt z#~$PwzsDmkL%Iy~AQ78YU<75p`HdtnRcZ$U;(RS45h3m1L}>cQAf08)L)K=d;XNu&jT?}gKm9&L*z;il3% znV{@wjZt)P=m|*Z>C>@$jXuDOs-&x6E{}noq4^A?kG9Kr@cOHd!0qouZ(Qi3Qe%*F zPeVwmHip1Z4}=Pv2^{AS_Yd=U|$ZSb~?IIsZ+MwFGHXiikUGHzhoN3CrNw7G6U|s(_ z0!!xdDMNe&tlFeSru1AO+WhVa@Gp=H^0PR$=fVQyxM-AdFoldC(vLnGg?V4Q7Lb=J zGs2U021duxuuN1|H6G5ix944gi%rimf&e@gi@=qMMiD)EY#&k^Yv5MaW=Q&wW(w$a zS0)+z`V!W1VT4re3H)(LByyM6|(uf)z5?Z0Ae z`f{@IJ?ox+a~Oj*j2l~wmlBf)L43~fe7C#jQVPNUnr2KwloaLUA~Ro&qk~XyGZs+F zydfK@?MbW&DIHQLdbP$lmQr>zu+#0sy-D(&9A0GXM0;9vQR*PdFt-fsAamPjeG>zv z=J`@s!d9H4xL=ImH9iO#=wliuVHkOK4kL>Jls?nwO@IFFKfqLP#16hw44G8F+yE{d zX9L#<8;6ohKP)B!Av!6<=w-GC3=7~uE57dCW;Yea$<}mXxe>dq?K}iXpaxw1Jrd(4 z(|lt*JsoBIidrwiBy}yg(4aYo$<0?-h81?VHFpVwrOA~|?qhV~N(N?^rE?|kT8rVu zzN1BlUon7X-RqKr|LqhEu;!JAk_!4lL-wt*n)f77lmAovgPYI`mvP z$Q7fKe3@o!c9wO|?^L@4#DH@%vMuY4I%Z@KvN%LFGux6=eCoxQEvwHEKwG7pf&iw~lj4yu+=44x*$1AT0l~?}TRkM^@WK;6uxXn#t2VGi%0Z2{^fJ~eJokZ(orw>C%>85mbBv~HTdpqganXIY?d1IxN83(=m2f+E^e`I-E93p(z@JE(k@9!+*F*Gj3 z;#bk1S)mqxY9g9^Y3nCQBrZ8WFpN4*#X{_R>npxgys*WcUHLQX8`uBaLp*c?eno~W z&ah^yM`u3`PHXQDZ5WZA%&v~le$>W1WYR_9p1U7>m1WKU3}ZiC&5E?LXdniUA8pO- z)!(g4nk@s+jwQWfecq{-ZT8H0Ih4{u9>BSHJiu}&yuJTmkmZ4Q-a6<_Tknc3Uo8g? z7=VM7eJ$FAM+l^;H7{FUtn5bC>ph1sX?s?S{X>t=aNZx7SU0jj@4A%*w|g8itpX-K zcXD=!6Gh9weedX-T?Gv#d?b8?(S22kkS#15gR5`$X_D^B?!!@bxQ#`@INJ%IM13=y zS=+ws`vCJ*NPpl!pf%gFFPe$!SNCU!3E#0tc4dPkAh6d(cBRO`9o5UJ>R6fEhLK-E zJJG1?gN;*?5kdr&OIc}C_BA+QeC{`H!vmwPOUb_7o{a)5Oq3MMp8Kb<{aIZ>L{Ep1 z0D{!pfQr>q9>{B(7;2k_zyOX77{-YO0jz&?_II}AHYXsPZI91x6S4bV+3(n3JA~*y zO!9NoP;Zvx6#b};O56Og1&bT~Oa7v>a@E5 zhvA$si}XRx9yj{;x}{U0Ci1;@|Bk|E_qns(pz(!5{=Z9XMr?1o!xZ~@l<-Gh?)A#L*FUMNkrNdVmVR>Hc zseRCG>MOOhg!;Zx%O!e!U#TU)Dok$y331oQnd(7kNRwsM{4{s z?6;4!QCK;$@BO9YN6>{m7|iX9#O~Ba_^)NB)N03dB##AyD1eLwVXRcv%lQr&YS2BY_>zG^wQx-0A~4#9Um)GzThPs?fh->dFU$zF}1 zGw(|z7MFSGef{UV8Dy@V= zAL}f;8^h2Tto{G(0&%RlRs4cI#Y_+mVJ zBXDO-+cKet^;NhFYdkA{9>n%VC}TzELKlfYES^)(woeu>0N9Rp2oJU!>JZpLj5iC< ziDm6So7I;l%n~D)W%1%PUAK#&qJ}tE8qt#N%!V`ZZmbcG5|PCl>lzmB^h6!tc3}uW z!oq{SStF^i3@87$4#YpnUp#DupoYQj)k!Wup6e+Iw)5N|aizH%;BFk)AX!8mH=+Om zu8@dHw^8E7M4Ke1k^6+Q1hz*F{l^sJ|JI*^aC4_G(y!a8Le2lr5X;#<%K^;d^N~n2 zER;TG(V^UR=+2u(3-+F1?`7mQs4Cx7>>hDEL=*C?!VE8B=>S<&m8WkDpZrYe2ApdYH zZ-V64-6Do|d<2u$d>C%zHwVK_>R_;@ryjO9)rX>B;aq7LHA*7&U5NuANDV=0O#FG! zeK~8G9<&gJL9PfkyOa^4S<025dXy&P3RLwK5blmU!Jr*KaB^gyTndudGS{_1uM9@H z7$$O+GEc-J9fQG`K+j@!=#HX1aSnK4ZIja=KiKTxMX%J#`?Hs7_F4^#wl!`!>i|V7JK_Y&4$;od#(@nJsHuChymE8pCN@th-LZA5$s+eY`5q z)$)k0Z@VtEn3`YD0J8pkpdD*pEq^7B>OG3R$g~w4&<>9RVB$G(*p=ZZD#n}Zi)GYm z3zB?S$(j>o4#dF%Yeyiu-%qH(*5n_TqEw?@5wxkcIFSmkAa_@FH5|Jp%~mF06y~~9 z&5;u1E*1<%2CzCGlp484milTiFO2CWkQKefvtO6=D|E(1^Ad^t~z+zv4 zQ)Jqa;3Irf(xiyxcX!~F6<+fw&B}qE$A7e3cKKQiuIoZ?3g$}c@}KZ&O5rfbYDe*Jstg({&aGGmR(PCySebpAW=So z4D3q*nANM4zSQwnt}Xo-r}U(_BOu;u7RzBiPn1KqZIx0OEiTq5ol0M=^s_j0)pZDA z)mnqTD=I6rCE-sDENAkKRU%pSwFGL9}j68#!E^1|5sr@f8ay{J* z-~Vh@yt!Vk>s)MC6R#Az%rqyndhXZwIY{UYH&cRXn%5BE=_yL#NL0_b4(?~_KTK}^ z{@qmNKy#%;)0?P`t-X$t(6l6&u(k<VO*WIx(3v+#V&b%UJJ`=z$NAVDwXlXV|5L^yap*Z z)q6#5?Aam8Gl0yd4n|5|aUPvR}Qr!tK1bHX2XF&54I>U z*cwWS+c4HD;}nkziw??zplTy+0#!ae20W2x9toO)?7)s-^zQv5Zgk^o4Kh%-qOlAw zJ_O-8U5E>dDhwVDtvb+f?S}u)xVhNrXfss#rhR%C<+`0L-La%e3>iu7;Q>mT76?Yk zwZjg6&rgN31LD5-7GW?1qn206QU&PtO_eFG(*gv(l15%u(e*Yw~zpGJ75`y^aef| zB>T2R2=p7)AP)gQ)Z@qm6l1mxM14YM9h%5O*XEsYh|it;V1Yf$3lF&tEAZebFq^x< z@M!~O5_YCEnhgU*FQ2KXEgFZeh4r6UCA#XuYEkO1=w&;eR(6RgYFxHqDGQhs)4h(lV zVZ%G?eNfBOLPD`h%kB}5a_3_SG8GSwdb2I0+^?E9M`7XlfY`4W7# z0GR^=-Ty;7h9>@=K%(jZC)W7)(MJLFl^lZ@>(j_-0#Abd{3+NK^qb&OG2BOS5S+S} z&EZxkBA7kUhhqMegBRu&8p;CQLZOA+>&r;?mUAf79--)F-}1YBi6;{sQN9BTL~}W` zz@L#}i{XmFE^PY;%2l8@?NrJcT+~ld^AlBxF?Aw5f{9;KdSOWa5@w+0-{KUeB#exv z8=+w&YKPN+OGpX$BNE;7qug1;F69!uH!+A!n9WXo|2{}pWOCXdL`GtbP z)?fe+#RDAf2R~|^H+Z0+*mtV@8$oCe?w^9vqYNIj<-=GPmV8-$0%|)8We93^hYzBL z-CIfmBX?nn@8urW z6da?tV}3p6%#9?t&`dd%ZdUfQH9ZZFuVZm&3ca)>6u#BFhn%n%XIKhN{Q#9^1-GHM zQ)LQ8%oPTrqUe?$hV515X!HB6IuaJd=By9h>1~>l2Kh>iH=)}*T5>#?!^W`Bt<7oi z`k$3)B#nkEUVlWLM9mqYn6zN5Za@5Kk(G$W?+%@APwSjfq0@9XFBVMYeC%fY1Zp9L z0t7^RuB;(M@f+HCEi{sWfUw4i$}h(U97$6Y0FLKh!X`~daW-TS8DtP2gSeVNRbt-c-> zf>`NVC@Lb?Vo8v!4T9D~8{iJkh+xo1Yr}S_&L9}|I{hc4$1e6VIbZY%kcD5)37nfX>BA)ZYo20lnY&jpYkN;Zov!# zm&HCWoZ7!108*?ZxGzh1Cae+Z{>9)V;-=3q*7{A@<1YWusuU}>OwQHGAL=2e0L5i{ zQZ}IixM!q4iJ^&7U5w9zIwiyOe%zTZh!84mbx_#ZQ2mqPa2!LpBXl@lN$GZ_=6IAT zKMtD?N^={U-4&)MGZz;H$QCe@8ew8`0ww0#3`{aupg=TR9&N`{xzY4x-~JNT79A`X z;$GW_vY|X9D2To~v5`;7-nSA)ID-L#0zp@xD9kzs7O_S-!AiI$Q(Top)a`~pDjmC~ zi8K4HQMn3J*IVmI`wkU&2(Mzz3_uSaW$-=)8|!V9g@UZ>t;LQ-Mnt7o!pr+{<~11S z1CphDsTyfIu1%*7fAACq+lRS<0AqNN4@(*v1e#mz8hGbs%h9Vpxw*{62G4QW?q(>w zvt@}v>+D&hHb@PDutX1c;(JG1jXWAmYk4V#& zo}moovS>boF|osV?RpZ1ZbDrdzI}-uj}K46M=?x`!00diQ9j;@9{FC5{JR`f*=@%V zkVHjcQa`Rcp6ABknMMT-t zyF=iM7u|zTS^rlkpo0_)udO?Pm*Kldgw=?!8Ua<|t3$*jc>*ROUxGS1l7`U8Ik8ZI z8F>Wzh`s|dW;doo((9pFNLwHEqaUxgI8*Bf{s77#tj%f@f{T!Vj6=28kl;{EA55=Q z^B~6@>O&ijYy4PVg{%VUV_;vHK9JL>jmHp*9SF+$XIMPogjAT{_n)I=$S|um%61|y znIVUJDAw7r$2QAuz=ypb*@unXA(J_o?#LY&_E530q6hw{x~P5j5RCgKz;H|6k)^T~ z2V~2w>8c8GaqZImc!-K*uxXv)1QflP1czx^S~3mxllzj(^0a7hZOftY@)JB2&`*=B z>1a55vv$~VCsuVxHUnHHyMa)~s0RH|v!KYGPNeY&(m4*bt2e+e7S%wm;y^L9PCh;* z3t{h^ltG}n>lB#X))>oEVn%8D(zJu&PIP57T6RO&QVTO{9NMf;3V*voKq zCFJ^Cx7o96TDim*dTsd-4j%$f#G|ot94&Iu$(iVs)(L`lEAxF>-^}6(02w!75;aqS zlW9cp0M_(p{+F(7%CnV_RFNLg!lE1oE#S=-Eu+RHZJgPgs#n47s@jlSW4cq0AZ}bi zAp2&C77#$d{MZ3he-LObP6L$Dp@Xv=lL#rOLIp%LPl8(9*j$dOGD9B5OrhGhI*BIr z8*;I4^~Wl#bxp9oUnXiV3Z58AZ|S4Bv_u46tM;0esYV`cmTc{quXUmUS92ii8KQ-} zbfsEB9ZiMsZe0=jwbcR)P-PTA^KKZ>wZ_qv7+y292f8mB3>Y(vTV*$PDoP9OS_H}1 z`I`H)xH1$2UeMYxRfx6)QKMzsJ~kf+08%*6iKVz}Pow%$iApF@F+!R8!5kRaeuNYwkd-dJ)(|PCcA^T_-FK{79vJ z8(UlTKD+*a_9VRTuCp1=J_pUUUXRG|h+z;;wJk&G?&Tc3w+*=|+{FqPfLH<$ixSZz z73S__)+yS<@l@}&)RBcx*CPHFZrS}PEeo}%0T3M5_QAQK-F@N2%4ceqVr}Z`8;1At zF>Hu96hOp$?IB>qh$fnw@^Q0uv2mu?%Z8xH0TQly7hNFRPI=fJ0B}brtEK$D*lH>Q z+}^WCwdWZH>YQ-LIe92BWH|;i;r*Gpl|MQ1gIwvhYq32&o>9Dv;koAxpw_Q*6fAmZ z-g=mY<@wmZxjN6er8+Mb>hE8oU=B6PSZ;od^<>gpnwN$m_$&#>j#oK}G|C6;mXpeo zS}2LYC1SBq^YM!;386lb_;fAusF%GU<1>?DF9%@z@$eG4Suf^#WC?k| z{4-4d?U@;-P7JbcUVg*YX zTyz{IDKjN7jHg=qv*eVb7sfiu#+em9XvZjctK6zO3lAoIP19`(KtbzMV$X`7E7~iE zP|;h+ehe#qf&KkX(RL6p(di7Gj>@O$8*>h`_okGT!y~+#H-i4IDZwtnx&3I#3zbra zzYd`^h2OmGJ%}Q;PcK0ee*1i>*;UV+4%|H9(L5j~plaY2(Mw7&ntV|ICS{jtD~^Y6>-!u*G$iE5VN4lMg_z z?M@!jPJxlZRKFO3Tl;|twj>FR1k(R$J`!*-Nh+#J$_1!5Cl3V_yo3$+ZNh_b5n0Xb zfPG;bAb<$puNz?2ih%eGUwa1IFYU*%3@9XImN+LLz~q{O6`vj3IGyPU8I)5||3;5a$R~GYK{wpvRU+C{qbVq&>Zz{4luPOsr z)H~VfR`k-z;=xS4KL;TOdJ9Dc{jr{4YCzbathf)=EPnu{vMD85EH%qLa0_L#F>-n)(tnozg1n{xXYN1JV})W@ig-5+-WE>Eq0*` zP6ci({f%OlZTrZ$dF3Pxtn?QRah7)elcCghs`*=K&$pAtOBF#fh`UeXdI06sb(5-V z#*Cwti_}4M+fMK5#H)=3NgFyfRgbcLE+s2X(gSC8(SRYVNdkbDnPc0h>r|ev!0kC2 zOexjsNUF-14ES?xnIpaRdvPGdr=eV>8uFqoy*nFKSi%LG^P23uEib^E+I0o2TOD`> zwNvu?&}ITza{o;@+_%rx(x!1ubnAIJcl3bghyo;oi%^L=@S9e$J{eP z4^8t3g8};js=jkD9%|ps-u%#*LLNK+7D=V~i^-)%4G}NS!Qbp>_}sR8oYk@I7xP`= zt4j=Ph4(}yQo|qIFaj{wLIGDZqac(-Q%mA#T|ne?(j3ZPO;zbZ+D;(AG73fs&oMcW z!>G#s^v!8)fjRE%@X_w%?V4&H>&X0-w!E!94Bdrfbt*;mGdi$y?`S?!y6UMUtt1?;#&Hi$G<0~}fUkJ?{AmdC;aDdJ;K8@%Pl-D$iC)=^s z>H?(|OK{S?V#S_VS}8|MxJw5`l;K@|-6$3iTyPtUdK(~Op@&sTD4Am{1VA zoQRAn-{K;0YOw*pBR2xVVzAbx5CjLym$#}naMAh78c!DMcuuyIYhG7TvwdD1Eop!& zBRZFj03k8gj=icVs4~AZ79CzN2-)SX*X7B}W_Swm|L6DRNRe-bap(PCUKy)TEwBzY zzl6q!Vt3lFDFCPd4}hgt7tDvh4iCZ<2o?Ub^C!Sa{fjZ@c2C7zS5{U5&Ffr%!AR^Z zg@pt}(N;&6vNZ22U>SnJe?}I--28N_fuRKCBN+cFyudUc;+l<-2C!y*ik48*PkAbM z-%$MdGaq*KJ7{jCpK9@8Y)jrYYbOLdWv^z6F4!Bl%O`w@0vLmt##%x|B!q%E-s26kWOU=l?o$|&ZGYLFS_bb-YBez!fUg1FsjVH#iY4;>mAu&tBN;cI9=8+HhC8#c6KU&t12vd zfzkpv%vdRNy4+iAHGtbQ+`i6+MfBB}05@OA05bQTeiV~RG>%U6*fWruYiCXFbp5C? z7n(?i;X>Ac+0kB86hXz~G*hVkRZSK}eU8eZHWmCFO*}+}+Af6wK2mBtSy{N|&oCxB zQ`sMGm@yJK!-gStEK#TVdLX4gnu49NH)xzp%b`FaeM)0z%O%-Bp+H<5`lLog?>1;; zZ0l+blzaY%2Uk9&`2s;k8On}o?R5|lG*yV0q)}rZNVoSw+DY}h%!y(*M1tCMBi)5+ z#D`E^xB}WHwTlWKqlSD9%7^a+IWxBtno-CFSr=nm9@Hqgw+w-xH#NReK@oA()Nyqa z#wlboW{sX%S3PFtxUqayol!Vx#!M<1n*&Yd^NDseIJyR zYu~|tZI93MVq4$TER}MvsffM%rN#lS%cuFvA97vH(H8g2_$s=Z{V2(w4;~Oa8TvCO z{|;L}qH-G)3ne-i_Vvp;D_5qvTXqxpw<&KVRc+Lt;vr)Ijrz58C=Gc50ENI2n)ycA zIxG{H%2W^_*CE56Q>NvpS{VCrbj2>z+Gka)p!oIAppq;@zu$(=sel<_L9jQyrbqbx zIi|mAP66=uuX3S@&G)uI1ynYV$Y)dIvj9IDzb~DRO093gx{&qPLv7iurgH30WQG#v zR1~)CEd9~WRH$DLHBj9mYJ4{#)I8hMck3d$7M(GyHK*(gNN|Z&eVEn2@(l|9F^5D; zbpwUW3WxvUd4xocF+T;0OyW6Q02cQQc?4UnD4he~tEOTGb<|XhpoTN0*meFPhRf;5cdTB@>v`id7h)9SSVXj`ToJR zvIDS2OLb#W(5W9o=v4?atu0M7sR6*_;K9^(P?t>|Cv}JxpG7vRedA~hoL-yb(N|WE z00lDiXV~vob=Z`v>NA})-M@+Yoqjj@d0bfd`j?0mxb86<{e>wHxomJMX8Z_8jdyLRVuVYPpkufx*9A3)Pu?8f$uD0>UJ zIo^0xrQVnQ{&txQas!*u>p19Z(wxjrU@&4X;>^sC9DLBlxyTXA*Kfn3@_s^1u#$It;aSZR$$cO&!o1NHQ=;GSp$| z->jQ%9!osvWA&@_Q=R!3WX&(=khiV6QuZXleykDN%+Tf-AkUqz3$QHbGY;KKBizVsRG7nZ1r27Ssf{>8!3eioPQXRw8?Po`!o6A<3N1#wY*Fnhr z_t>;{oz8=pgRMfq%V>;#gWjF zys=*AYFY)rbnBWZ7kV!usLi21mRYsL#2bMY|^hbX<;$TxVZVpXf zhITYZ!P`#3~Un~0PlM1XTz7-x6=c>nccgOXvH2GluWKcMuvMe%ITxShd?D1 zX(i;7K%IOUT71B@po6nT??egbpAn4cDb}%A-`|;GdEJci%%!?9oyNqjbT~JG*zbPF z1|V`7`cv%7m&#C8EzHQCl|z^m7-zfqq6_}S3SBB>10fqE*v9=w%GY}0O_jdLCk{%s zdG;K6JPEblQ)90xzNVD8=uw&fuM3{EPG{if0UqEBC1*FZ+$%#7dhHNhR`+Z%FlkuD zIK;j@nik!`>=kCXFxMKZgx3UCM5BF$qqQ}d8C8|o2c_My!WXhR3rcgT>b$O+urw5# zZGx~)&)=xq0+);15ow(s=_Z(=a&u>*5nk-YXLYxFY!PS)Jn3H>92wMIM~dA%d5XLB zXRy)u)ZYZW=>m6E03tLSHiF`-7`wr;X1zch&xtrMvE`XE2nyju@G>*v0jVcd-x z%G348#P=DDnNUJFiBUGhqLhs`o6+ccjp>Ua6|tt zuVhtwORoj6zn?50fb8sM9sE!(J=$){6Lqg0w&%y*1D7}VN!YwfYChp~KKP{eA;dznl^up3H@II?6Ml;;cB+P`d*j=D79^vqJwqr1`*w2SIjye`r?B-)U z^&iQ6M#|~s>oG3&?gk-hBNQFhPAhxQ(Fvduwx3ar zP}0Rp1?1mumSNaUDVMMp=ax;hz>CT6md63P?cK!MoU*6Pi8)P*F3lVU^q3B_3A9C~^}+TQNOQm#G8n@m zMBUu(_4v*h0t2aGFB~2$?=E!lj?UX&fEA=qCZSP-z4lVO^c6 z4eXD*CXjaP)#VV4kI@0=IMs@M*?+-0ui2$Qa_1XJe6_v+29Bm4`08_K!EDa@71m0C zK08+E_tN#*6|f+Dapga9j53T-De_etbfwhc4YdhAHUuYLFz{9HB|vofQ3OH4Zr1rL$`AE8 zdcsW5cjpNqa&l5P0Hnl3upEQS!Ok7613+R{p401L^-n`sM##)^Q_P(k@UJ>^jzI8E z6|?R)hipe@KGE#knMTDGQ-@PThRG|q4?S6rnoa3eBu>^ilR48-uJ{mgX530Nx>tOMiz7l5oCd*bN)c1OpwqShOC`7D0JnSAD+)qW#)~r&1j$Wm1to3|( zDzXEDWm;(TL=vxJ4mcisC;%c~lb7tRN~yi01WB`d5dW#4jW`s` z7b1Kfsdw9c(^uFkwa5Mo%S^)Cy30bKBSag53mt?FCPFc}y2frh=kRbkEP)Q|`s^oj zQBHmAOsUrH$o8_SkQzRXy+Q?ht~opqf=5@&&?)hy!d0rw+dP<8VywSiBQJy=+&CQ2 zQ;7`Dr=T)26yihep&|B!xXFo<&TarPVt7RpweM76=ibtUT58^>c4rT~^}7QYECRd+ zgcp6;i$}|%ke=>}$4&Q8ykm2`46LcDOF#qiPrz^;tO$@m&`xj5mY*z}4+Mw148Sv9 zGy6sDzgJ-Iy@R@Pb}pfG4uX!(0L(IO=rM(SU7_S-dc-L$A#%3uT*YiajXxkQP<1mL zdSlHB;4Tj!)Rk6>q*2w#Fb`TXaUOQm`KSV9-24P6`P@W_S9&BY)Y!|AN8Gq6&XZ33 zGR4s}3p#__E?4v=&B_vI)RyT19q%fKh$H5w# zu1)*6!q;v#SG=R@qcwv1#Ly8z@Wl)Ca@}!&FhiiaG6&^jA-FC z11<1od0$m*M&_`6H+Iatr*m{+n!M7-%}^5D$`BMOmJcu;0mH1(OJ8Jme99ly&FFzm z1T1ABA%36yuh0iOzqou9P_OP#vS)1*NWZ`D&^>C)I_~M5unRB`*RT~yG)dxhW~)uj zic)))GOhFtTkd|I29n)7kZ#S#Ued5OGA@D=YsS;C;^y$^F@QBcR%(m)#FZGk&V$q2 z8$wFoQFaB-#EsztIk@|Wva!IStRNV(EX0l#oh#i9nfd9uS-ffaopYTVL;*zjVv_!W zgOJ~c|5Apu@k7g?umZxf^=G%YmuGhVERgrm3@~>%&er1xOFQDBR_s)mO;?X0;Al$; zkoC-N_Oo}z)J|Xo9TdcV-B|h(Bo#R>G})kQ24|(y7yfn-;3R zZqG)&r?$3XH4W+snCV~Tda*)JwG6PNW5H6SSJ7+`TEaQBfYsup4%^yz=Xj8lsvLU= zcf%X-yCbQ+f4q2mcvz8@^X{UH>M+wK?EY5Ok{@ZlWl^0PvR_?!J*4V-wTLF300my{ zT8J&)OsMmjCsvQMwuwreN84l6Q1v^Y-o;kLs>Mj@@uW`IP?Zbb1Z%&ic1JZHXWMH? zCZ@DJ1<+3J%|FOfWK!*oqE!q*;tj-RFXA@lx5~G!#@5!}Y;TnMQ?x8l4YUlYe}*(i zGfF`-z!dFi{+bunQy~r!R|F6ly$ZEd&JsW(|5XkFRpLdcCt=}eh1hk~`UudbdU$Tu z5D*AURgVOZ9@&M~)FMA>`j`{Ke=|f^HhynMBss#d^`r^ySW*=?;l2Lh>1FJcpxFEWsSDGvhSwx9M9I4^p& zn9e5~qM52f{gosA*fhbFA_9>YKU}5Ok*hN{F&a>fu5=1igAJ)s_rVXtP(*qF%*Mt3 zgJ6M>_&13wH&KHQ?N|9@ADG{d6&KSt6VNS*Z(u9;S`!wJ3vYv~RC}rj-p-gDym;%$ z`0p)L_PzRik`vv&U+7A&jZxpHCTR{*+Yd@H3@+u2p{ilfDU6u`n%cy1YP}8p&|d0j z8aB_9oF=J}AFI!|rM%Zt;3wRyM5)-L`Cx*^tL^EjNoX=Ig_Ko)41xM{!?2U*BsCJ6 z-QNkx%UVf>6BTLpAk6!1q7!{IS^XX@d7=c6)=oJx>7pV%)C$#esd#0+1DzBZhVXIa zN0^kURC~Mtv`0QdQ6S;WWd7=7;Ck`kHp*S?1_CQjtMr~h?1e`4MqnHTis*-a*>LX% zR4mLZaALQE)%AdNII&Tf*2kZI^niHAzJ3(})>RMkC#-_Ui6XEc<&=e$$bX>`B*} z(Rs~-p_|h%GY{{p4>E0Kq?TH-_QmRO1oey6z&spLle52GJ&RNqA4BN=27I)bZZ=>)h|V-#I44Q9(my)q!UN) z!6sgX!|mvgRq8tS=xTMn6@7mz7`hV&0*3+Z5Zkfu*Qy`GPDb5tP2ds=r0|{n)Q+9M z2y0mHz9MDaGkw@tlX?n>}B9l0N}tksgK3$?zFD6@~=lYMoPnm51&~#i-I(BK>XP8gfqXkGu^C& z9O{3)cDMo8{%=Q^uU#{13W}#*x4iZThX2d8S%0IU3I=Z-*3)i&o4_w%*cWa?6hrP^ z27vl-SVVW(i7SD1IMC#)o!P@c=81A@)8`r~{ngy%e4TV9E)Q|D);@0H_z@-f% zV5Z2J?#q;$F(tvdtydJFtfx;gXqx}ZxNDUa=K(n6+&Xnk@f|9jjm4;K0o;Vv^4vH1 zcmM~n;p^PD`0~#;##DQ-F|Xx*AvgOhS8wKyq1F?{TcD||9RNjjgU0N)@#Jl<$B&|b z@ASx)z(--QDNmz}HzgRk$ojk>QcW*V(Wb9+?(*L5EQol}lJgzPcDcFZjv&08$EeXa zDW{uE_jz~QKBOteA}_Y4e{PJ2@T9CmnVSM881J#xfw`FHNR6s_V5cU{yf|>bh14=C zml$AO(B>X$%6vuMWuYe+dZHXqL$8*y57y^igacYBiy+)cNsZ%kp;w{HeZw>#ue#U4 zfO)?F!@b_akVR;TGi4piy#alTFcKwe7jVxM(!!lP3U<=2d$ld!nw|eXXB*ycuO<*$ z=t>jZ0zK%)hlSvH`{a%WjNa8xLcrYJSq#*sO7jp9ItFl{Bo8&t6_vSAQpv??e<44Y zK)M7m?Rs`THSW=ZDm*J67{vQITGGh0*d?U0622J!vufW66d$EjYRu=ht^-@6@y}eS znYrhtQ^Rw)L8kYiIvceHS76$H}M#xf8&CG$7BMh%_swz_Ik>T9nh) zM^-K)NmxZ3NlZD2-Fk6rJ9&`rXcPH-1=YQaU`p)?`7ZRvc}V3xURDy}+-(f{}fJi_loY(aq1R)=~a6ZDGQLy0) zto@vh-4O(t=Rgm@8)}3GsC8+%WBgZZvi=LUr4XsKlY>s0TnQwsM&B zN<3$rVCo{%N}A87KxF+=ft-DPsUQHAdPBg0Q(Z0?Xyr0`+O#QB*(A==p&cu>`O)>i z3V=n65V2}*7eE>2+k*ZSy#r+?O&tZUB)$Sq9YYI()F*~PbRi(vmi>LD0NKGOWuWPn zu8H+!;nxa2fV=%!L7aKlsJ5>V{WL%G2xjl!aDo?pU*KXDM6tuLUp;n}g3iPhEcQi7KZ8J=sj9nJm%Rbs=f3%Aqu5ry_N(UCK`%X8sC*A-Z5`2MGODmZ^>MpyGD zInaH=4x>*`3Zxq&D$DqwDTNQL4X4X?P$B0fHQW(N;_GT?&l)GqQ*7jbr%ZT{LTQhA z#o=`s48);tK(8r3Zb#K?3+8am4b;`VlBc59qmWx~dOgIEWi}K{4WSEl1(vb{f+`V| zAD#K)icRnRG2B~C*gEgM5fhE9*|tzCko~b2X|pzrw}!Rb7j6YWBGQ3eo1TF3dL>S2 zbHOg(kF-=MsqK})B8qk`oJZg4(p=deu7%^QOaMmQyT{U7GuJg&;(iywc1vagEBCaVgrcY(WbK?U~> z6}NIrWpzmb#RL=-v#iYJqW9jTV2W*;mSUEZno4D9rG_n*R*I$Nl8UYFe&5erF3fYG z`t<#M|M>l*+<9g>GjrygGv}N+CuKIJ7Uuf1fqp6boSAEIN+fc+K8NW_G2*FkP|6-l zRH6%YACAVQeN#Y*PvIVZ){x@PdJj!GNFH4!~bCTtc5XUM@xF@GPG8;r-s06I$=~N z7HUrU$W7{Z1}%1j9y4Sk=#8ov{+^ZD??#YMwPeI>KNuEh54dsG^ak7$m*e4O6O9`tSs~x$~xH&Fw9v zfu{Q#K)CRV(1&e1oHEYI@>U9bXR*NS+$Sl09ckxrPz1llDFKk_kxyJw7)Sb~wy~VR zn%}qyEKgp#A3D+#nDUf9Go2{=>o=hs8&uSqzB!Td9!-tzSAQetk|rJ%z!?5j$`ZPA zwH;okNR+E`?@(V#IJ<>AJ;yMwuTvgJPUyWLj{E|Er~zISP&&$=7EfF6MSsj0dWNbd z;I50CYJce_A87e%C`>6?xKpX#8rmM=9^fczRST+8$FygvkA{wRppDZ&#FMhX4Xe*Y zB1FKEp>N=ZHfN|ox&>I@HnF5@gV(`oEj@GMp6xlINNwXAh?g6shIqX8X_?X=FUzK> zrDtI}X8d{F)366h-qhDV#wJQhM<{g!1mP*u65T9b!vopbPUCSfVfJg!o;^P9F*o+& z?IC+1bV;wyYJMN`Io$Hv;l0BYm%fOxAU*L3T|J_#L7EsYysEfze87(&i;{cj)E@@? z#o+S$3)GBXOUYGjHw;K&;@ySe?o!=?f%*Rk7vVSs{0hq8{d@ltnBy9A1f@RQ;z8xp zV>`3Z9U45*p8AopfZ^)@g)ba@H9;*Y&nwA`tzw!deJE>@s~_DifDcUSahPDM<|qbJ z&0?ho?U}0xXA$3PK0qGYwVHC);}zu}Ao-ta`%B3+VbT6r3rj%b?_Ni=w;U*BIWm&w zuhE#0Rw5DFk56I|mqdY76Z}~{&q4$>Zwy3$p^wteA3M9UgH?%c2qZ+B7Af>m7XBWpRA{|K4O6ksyhbgXLQzSE5<<@=) zk|zmnja%cAsCHWd95?qX;l%M{QJxp zW_F^PX}ka>7&ienILsl2I}o=X_K^(`Lwv&pl;L8PjQ6jQ;2?c zMYqI@ZNSxehnmk3wxePpjZ1UFxNLjC@~GxznPSYV3)WKCG8c z(S}X&S7bObzzU0c%_v1Yp{J)A=9_`275f$IkTfMYE|0FOtPMQr%eS|{eMGmmC7Y;H zEP>*+VXhK_GR*Lm7VKD+Vk2Im*KdEAWcG=X{8iz&SdZhwsIJ@<(R}W9#iQB^B_1Fk zKonJ8GK_9S3<~vwPqC`h)te^k6y>WMqF9s% z6KJjTRzC{WD8ShZaMbI5?}Dp_ zA1Lcj{g9E;YiT8HsmeGNurDcwQg^9!G;`VWt*C4ATEuDcS0PYep*oqizp2hZN_b04 zmNdZ70y58b7rf#ct=ZXz|B08*U;pGF92-?e*i86S;Uk9j7&Crdu7pNjC_7?kHz&VP)i94 z+4DAdoIat)`>3dHsnWYN;8a6|lT8;N@nXKt@dx2#k07J0a*6&I_zhlC#4%HvJ`r)2 zZtLMeGeEDg42_1jt?3!aI6D0NSu9pkF?8cMNz3f~$_F(qBQ=Wh(=hABn(M z>5PGK!uaUY%#c|RH z)2?(BLjKZ+)3>`+Q6O!I1S^#>lsyIqh^7->K3RVp*_|@=!flS>Hiyj35g+NJS*>4u z8aPrQB1B4q?im>Giq+ei2#w3#j{F$oHLPSU$I(D)q$CZLS4oE0C_CwdK{{c$?o=rQ z*8%VA*;UyJSPW{J@RvJtCe{b1#&Pul9j z!252)6K!xTd>gK-q1Tg8=AY-Z=&jf!2ptZw#VmPoEd0Btey)YjgcJ%26BxugC&VHf zDJP~FEll2Jsw96z5>~MtYn>mv7q9)t#113XS$#{kWku{(M^;l9`;!x!Q4y>3qL5ry zHx{LfZ3o)DR^!5)3l04duD7=u-l)-#~vm;j;Mg@#KJ->YDzAx4 zq}09)dbZAcJ4?X@K^l8Nj}>t=4Cp827qMdKH@ZGjl=mrgFH;>ztBkR5DGKNYcbus@ zenLR{p4pvF#(VJDOa3LI6Uz(NMIbrRp!iv2yxy)Q`|hxMr3V|nUX7)~ZsIkUBT!eN zySEy)tyPd`r6i~fNl;T=SepUri7-8JDR9Who{iL-)$URM49o0P^;*8IFpc4%=l2Cj z8(6a)G( z6;V1P+=mi4{wU?0itWjEw1{2f!)TZq#&T&}7`Ej(FKWjUy;$9S^%g+i1Vn@*kYW

S`A{*fCb1I#MXG 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 ``` +### Using Closure values +The package can use Closure values: + +```php +$users = [ + [ + 'name' => 'one', + 'age' => 10, + ], + [ + 'name' => 'two', + 'age' => 12, + ], +]; + +$array = [ + 'users' => function () use ($users) { + $new_users = []; + foreach ($users as $user) { + $new_users[] = array_merge( + $user, + [ + 'double_age' => $user['age'] * 2, + ] + ); + } + + return $new_users; + }, +]; + +ArrayToXml::convert($array) +``` + +This will result in: + +```xml + + + + one + 10 + 20 + + + two + 12 + 24 + + +``` + ### Handling numeric keys The package can also can handle numeric keys: diff --git a/vendor/spatie/array-to-xml/src/ArrayToXml.php b/vendor/spatie/array-to-xml/src/ArrayToXml.php index b84bdc86..eac1ec24 100644 --- a/vendor/spatie/array-to-xml/src/ArrayToXml.php +++ b/vendor/spatie/array-to-xml/src/ArrayToXml.php @@ -2,6 +2,7 @@ namespace Spatie\ArrayToXml; +use Closure; use DOMDocument; use DOMElement; use DOMException; @@ -143,6 +144,10 @@ class ArrayToXml protected function convertElement(DOMElement $element, mixed $value): void { + if ($value instanceof Closure) { + $value = $value(); + } + $sequential = $this->isArrayAllKeySequential($value); if (! is_array($value)) { diff --git a/vendor/symfony/console/Application.php b/vendor/symfony/console/Application.php index 41548a3e..b7aaa6a2 100644 --- a/vendor/symfony/console/Application.php +++ b/vendor/symfony/console/Application.php @@ -105,11 +105,14 @@ class Application implements ResetInterface /** * @final */ - public function setDispatcher(EventDispatcherInterface $dispatcher) + public function setDispatcher(EventDispatcherInterface $dispatcher): void { $this->dispatcher = $dispatcher; } + /** + * @return void + */ public function setCommandLoader(CommandLoaderInterface $commandLoader) { $this->commandLoader = $commandLoader; @@ -118,12 +121,15 @@ class Application implements ResetInterface public function getSignalRegistry(): SignalRegistry { if (!$this->signalRegistry) { - throw new RuntimeException('Signals are not supported. Make sure that the `pcntl` extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.'); + throw new RuntimeException('Signals are not supported. Make sure that the "pcntl" extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.'); } return $this->signalRegistry; } + /** + * @return void + */ public function setSignalsToDispatchEvent(int ...$signalsToDispatchEvent) { $this->signalsToDispatchEvent = $signalsToDispatchEvent; @@ -317,10 +323,16 @@ class Application implements ResetInterface return $exitCode; } + /** + * @return void + */ public function reset() { } + /** + * @return void + */ public function setHelperSet(HelperSet $helperSet) { $this->helperSet = $helperSet; @@ -334,6 +346,9 @@ class Application implements ResetInterface return $this->helperSet ??= $this->getDefaultHelperSet(); } + /** + * @return void + */ public function setDefinition(InputDefinition $definition) { $this->definition = $definition; @@ -404,6 +419,8 @@ class Application implements ResetInterface /** * Sets whether to catch exceptions or not during commands execution. + * + * @return void */ public function setCatchExceptions(bool $boolean) { @@ -420,6 +437,8 @@ class Application implements ResetInterface /** * Sets whether to automatically exit after a command execution or not. + * + * @return void */ public function setAutoExit(bool $boolean) { @@ -436,7 +455,9 @@ class Application implements ResetInterface /** * Sets the application name. - **/ + * + * @return void + */ public function setName(string $name) { $this->name = $name; @@ -452,6 +473,8 @@ class Application implements ResetInterface /** * Sets the application version. + * + * @return void */ public function setVersion(string $version) { @@ -490,6 +513,8 @@ class Application implements ResetInterface * If a Command is not enabled it will not be added. * * @param Command[] $commands An array of commands + * + * @return void */ public function addCommands(array $commands) { @@ -687,9 +712,7 @@ class Application implements ResetInterface if ($alternatives = $this->findAlternatives($name, $allCommands)) { // remove hidden commands - $alternatives = array_filter($alternatives, function ($name) { - return !$this->get($name)->isHidden(); - }); + $alternatives = array_filter($alternatives, fn ($name) => !$this->get($name)->isHidden()); if (1 == \count($alternatives)) { $message .= "\n\nDid you mean this?\n "; @@ -840,9 +863,7 @@ class Application implements ResetInterface } if (str_contains($message, "@anonymous\0")) { - $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) { - return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0]; - }, $message); + $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0], $message); } $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : \PHP_INT_MAX; @@ -903,6 +924,8 @@ class Application implements ResetInterface /** * Configures the input and output instances based on the user arguments and options. + * + * @return void */ protected function configureIO(InputInterface $input, OutputInterface $output) { @@ -977,44 +1000,62 @@ class Application implements ResetInterface } } - if ($this->signalsToDispatchEvent) { - $commandSignals = $command instanceof SignalableCommandInterface ? $command->getSubscribedSignals() : []; + $commandSignals = $command instanceof SignalableCommandInterface ? $command->getSubscribedSignals() : []; + if ($commandSignals || $this->dispatcher && $this->signalsToDispatchEvent) { + if (!$this->signalRegistry) { + throw new RuntimeException('Unable to subscribe to signal events. Make sure that the "pcntl" extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.'); + } - if ($commandSignals || null !== $this->dispatcher) { - if (!$this->signalRegistry) { - throw new RuntimeException('Unable to subscribe to signal events. Make sure that the `pcntl` extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.'); - } + if (Terminal::hasSttyAvailable()) { + $sttyMode = shell_exec('stty -g'); - if (Terminal::hasSttyAvailable()) { - $sttyMode = shell_exec('stty -g'); - - foreach ([\SIGINT, \SIGTERM] as $signal) { - $this->signalRegistry->register($signal, static function () use ($sttyMode) { - shell_exec('stty '.$sttyMode); - }); - } + foreach ([\SIGINT, \SIGTERM] as $signal) { + $this->signalRegistry->register($signal, static fn () => shell_exec('stty '.$sttyMode)); } } - if (null !== $this->dispatcher) { + if ($this->dispatcher) { + // We register application signals, so that we can dispatch the event foreach ($this->signalsToDispatchEvent as $signal) { $event = new ConsoleSignalEvent($command, $input, $output, $signal); - $this->signalRegistry->register($signal, function ($signal, $hasNext) use ($event) { + $this->signalRegistry->register($signal, function ($signal) use ($event, $command, $commandSignals) { $this->dispatcher->dispatch($event, ConsoleEvents::SIGNAL); + $exitCode = $event->getExitCode(); - // No more handlers, we try to simulate PHP default behavior - if (!$hasNext) { - if (!\in_array($signal, [\SIGUSR1, \SIGUSR2], true)) { - exit(0); + // If the command is signalable, we call the handleSignal() method + if (\in_array($signal, $commandSignals, true)) { + $exitCode = $command->handleSignal($signal, $exitCode); + // BC layer for Symfony <= 5 + if (null === $exitCode) { + trigger_deprecation('symfony/console', '6.3', 'Not returning an exit code from "%s::handleSignal()" is deprecated, return "false" to keep the command running or "0" to exit successfully.', get_debug_type($command)); + $exitCode = 0; } } + + if (false !== $exitCode) { + exit($exitCode); + } }); } + + // then we register command signals, but not if already handled after the dispatcher + $commandSignals = array_diff($commandSignals, $this->signalsToDispatchEvent); } foreach ($commandSignals as $signal) { - $this->signalRegistry->register($signal, [$command, 'handleSignal']); + $this->signalRegistry->register($signal, function (int $signal) use ($command): void { + $exitCode = $command->handleSignal($signal); + // BC layer for Symfony <= 5 + if (null === $exitCode) { + trigger_deprecation('symfony/console', '6.3', 'Not returning an exit code from "%s::handleSignal()" is deprecated, return "false" to keep the command running or "0" to exit successfully.', get_debug_type($command)); + $exitCode = 0; + } + + if (false !== $exitCode) { + exit($exitCode); + } + }); } } @@ -1170,7 +1211,7 @@ class Application implements ResetInterface } } - $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; }); + $alternatives = array_filter($alternatives, fn ($lev) => $lev < 2 * $threshold); ksort($alternatives, \SORT_NATURAL | \SORT_FLAG_CASE); return array_keys($alternatives); @@ -1261,7 +1302,7 @@ class Application implements ResetInterface return $namespaces; } - private function init() + private function init(): void { if ($this->initialized) { return; diff --git a/vendor/symfony/console/CHANGELOG.md b/vendor/symfony/console/CHANGELOG.md index 61c36b0e..3428a57d 100644 --- a/vendor/symfony/console/CHANGELOG.md +++ b/vendor/symfony/console/CHANGELOG.md @@ -1,6 +1,13 @@ CHANGELOG ========= +6.3 +--- + + * Add support for choosing exit code while handling signal, or to not exit at all + * Add `ProgressBar::setPlaceholderFormatter` to set a placeholder attached to a instance, instead of being global. + * Add `ReStructuredTextDescriptor` + 6.2 --- diff --git a/vendor/symfony/console/Command/Command.php b/vendor/symfony/console/Command/Command.php index 1e3c1a5a..704b112d 100644 --- a/vendor/symfony/console/Command/Command.php +++ b/vendor/symfony/console/Command/Command.php @@ -141,12 +141,17 @@ class Command * Ignores validation errors. * * This is mainly useful for the help command. + * + * @return void */ public function ignoreValidationErrors() { $this->ignoreValidationErrors = true; } + /** + * @return void + */ public function setApplication(Application $application = null) { if (1 > \func_num_args()) { @@ -162,6 +167,9 @@ class Command $this->fullDefinition = null; } + /** + * @return void + */ public function setHelperSet(HelperSet $helperSet) { $this->helperSet = $helperSet; @@ -198,6 +206,8 @@ class Command /** * Configures the current command. + * + * @return void */ protected function configure() { @@ -228,6 +238,8 @@ class Command * 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. + * + * @return void */ protected function interact(InputInterface $input, OutputInterface $output) { @@ -242,6 +254,8 @@ class Command * * @see InputInterface::bind() * @see InputInterface::validate() + * + * @return void */ protected function initialize(InputInterface $input, OutputInterface $output) { @@ -378,7 +392,7 @@ class Command * * @internal */ - public function mergeApplicationDefinition(bool $mergeArgs = true) + public function mergeApplicationDefinition(bool $mergeArgs = true): void { if (null === $this->application) { return; @@ -702,7 +716,7 @@ class Command * * @throws InvalidArgumentException When the name is invalid */ - private function validateName(string $name) + private function validateName(string $name): void { if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) { throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name)); diff --git a/vendor/symfony/console/Command/CompleteCommand.php b/vendor/symfony/console/Command/CompleteCommand.php index dbf5d7dd..058578d8 100644 --- a/vendor/symfony/console/Command/CompleteCommand.php +++ b/vendor/symfony/console/Command/CompleteCommand.php @@ -74,7 +74,7 @@ final class CompleteCommand extends Command ; } - protected function initialize(InputInterface $input, OutputInterface $output) + protected function initialize(InputInterface $input, OutputInterface $output): void { $this->isDebug = filter_var(getenv('SYMFONY_COMPLETION_DEBUG'), \FILTER_VALIDATE_BOOL); } @@ -134,12 +134,12 @@ final class CompleteCommand extends Command $completionInput->bind($command->getDefinition()); if (CompletionInput::TYPE_OPTION_NAME === $completionInput->getCompletionType()) { - $this->log(' Completing option names for the '.\get_class($command instanceof LazyCommand ? $command->getCommand() : $command).' command.'); + $this->log(' Completing option names for the '.($command instanceof LazyCommand ? $command->getCommand() : $command)::class.' command.'); $suggestions->suggestOptions($command->getDefinition()->getOptions()); } else { $this->log([ - ' Completing using the '.\get_class($command instanceof LazyCommand ? $command->getCommand() : $command).' class.', + ' Completing using the '.($command instanceof LazyCommand ? $command->getCommand() : $command)::class.' class.', ' Completing '.$completionInput->getCompletionType().' for '.$completionInput->getCompletionName().'', ]); if (null !== $compval = $completionInput->getCompletionValue()) { @@ -155,7 +155,7 @@ final class CompleteCommand extends Command $this->log('Suggestions:'); if ($options = $suggestions->getOptionSuggestions()) { - $this->log(' --'.implode(' --', array_map(function ($o) { return $o->getName(); }, $options))); + $this->log(' --'.implode(' --', array_map(fn ($o) => $o->getName(), $options))); } elseif ($values = $suggestions->getValueSuggestions()) { $this->log(' '.implode(' ', $values)); } else { diff --git a/vendor/symfony/console/Command/DumpCompletionCommand.php b/vendor/symfony/console/Command/DumpCompletionCommand.php index cac944ec..51b613a1 100644 --- a/vendor/symfony/console/Command/DumpCompletionCommand.php +++ b/vendor/symfony/console/Command/DumpCompletionCommand.php @@ -39,7 +39,7 @@ final class DumpCompletionCommand extends Command private array $supportedShells; - protected function configure() + protected function configure(): void { $fullCommand = $_SERVER['PHP_SELF']; $commandName = basename($fullCommand); diff --git a/vendor/symfony/console/Command/HelpCommand.php b/vendor/symfony/console/Command/HelpCommand.php index d4134e17..e6447b05 100644 --- a/vendor/symfony/console/Command/HelpCommand.php +++ b/vendor/symfony/console/Command/HelpCommand.php @@ -27,6 +27,9 @@ class HelpCommand extends Command { private Command $command; + /** + * @return void + */ protected function configure() { $this->ignoreValidationErrors(); @@ -34,12 +37,8 @@ class HelpCommand extends Command $this ->setName('help') ->setDefinition([ - new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help', function () { - return array_keys((new ApplicationDescription($this->getApplication()))->getCommands()); - }), - new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt', function () { - return (new DescriptorHelper())->getFormats(); - }), + new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help', fn () => array_keys((new ApplicationDescription($this->getApplication()))->getCommands())), + new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt', fn () => (new DescriptorHelper())->getFormats()), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'), ]) ->setDescription('Display help for a command') @@ -58,6 +57,9 @@ EOF ; } + /** + * @return void + */ public function setCommand(Command $command) { $this->command = $command; diff --git a/vendor/symfony/console/Command/ListCommand.php b/vendor/symfony/console/Command/ListCommand.php index cab88b43..5850c3d7 100644 --- a/vendor/symfony/console/Command/ListCommand.php +++ b/vendor/symfony/console/Command/ListCommand.php @@ -25,18 +25,17 @@ use Symfony\Component\Console\Output\OutputInterface; */ class ListCommand extends Command { + /** + * @return void + */ protected function configure() { $this ->setName('list') ->setDefinition([ - new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name', null, function () { - return array_keys((new ApplicationDescription($this->getApplication()))->getNamespaces()); - }), + new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name', null, fn () => array_keys((new ApplicationDescription($this->getApplication()))->getNamespaces())), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt', function () { - return (new DescriptorHelper())->getFormats(); - }), + new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt', fn () => (new DescriptorHelper())->getFormats()), new InputOption('short', null, InputOption::VALUE_NONE, 'To skip describing commands\' arguments'), ]) ->setDescription('List commands') diff --git a/vendor/symfony/console/Command/LockableTrait.php b/vendor/symfony/console/Command/LockableTrait.php index 67923a9e..c1006a65 100644 --- a/vendor/symfony/console/Command/LockableTrait.php +++ b/vendor/symfony/console/Command/LockableTrait.php @@ -32,7 +32,7 @@ trait LockableTrait private function lock(string $name = null, bool $blocking = false): bool { if (!class_exists(SemaphoreStore::class)) { - throw new LogicException('To enable the locking feature you must install the symfony/lock component.'); + throw new LogicException('To enable the locking feature you must install the symfony/lock component. Try running "composer require symfony/lock".'); } if (null !== $this->lock) { @@ -58,7 +58,7 @@ trait LockableTrait /** * Releases the command lock if there is one. */ - private function release() + private function release(): void { if ($this->lock) { $this->lock->release(); diff --git a/vendor/symfony/console/Command/SignalableCommandInterface.php b/vendor/symfony/console/Command/SignalableCommandInterface.php index d439728b..4d087600 100644 --- a/vendor/symfony/console/Command/SignalableCommandInterface.php +++ b/vendor/symfony/console/Command/SignalableCommandInterface.php @@ -25,6 +25,10 @@ interface SignalableCommandInterface /** * The method will be called when the application is signaled. + * + * @param int|false $previousExitCode + + * @return int|false The exit code to return or false to continue the normal execution */ - public function handleSignal(int $signal): void; + public function handleSignal(int $signal, /* int|false $previousExitCode = 0 */); } diff --git a/vendor/symfony/console/Completion/CompletionInput.php b/vendor/symfony/console/Completion/CompletionInput.php index 3ef8db5d..800b7235 100644 --- a/vendor/symfony/console/Completion/CompletionInput.php +++ b/vendor/symfony/console/Completion/CompletionInput.php @@ -34,7 +34,7 @@ final class CompletionInput extends ArgvInput private $tokens; private $currentIndex; private $completionType; - private $completionName = null; + private $completionName; private $completionValue = ''; /** diff --git a/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php b/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php index 62c80c3b..27705ddb 100644 --- a/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php +++ b/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php @@ -29,6 +29,9 @@ use Symfony\Component\DependencyInjection\TypedReference; */ class AddConsoleCommandPass implements CompilerPassInterface { + /** + * @return void + */ public function process(ContainerBuilder $container) { $commandServices = $container->findTaggedServiceIds('console.command', true); diff --git a/vendor/symfony/console/Descriptor/ApplicationDescription.php b/vendor/symfony/console/Descriptor/ApplicationDescription.php index 2158339e..f8ed1804 100644 --- a/vendor/symfony/console/Descriptor/ApplicationDescription.php +++ b/vendor/symfony/console/Descriptor/ApplicationDescription.php @@ -79,7 +79,7 @@ class ApplicationDescription return $this->commands[$name] ?? $this->aliases[$name]; } - private function inspectApplication() + private function inspectApplication(): void { $this->commands = []; $this->namespaces = []; diff --git a/vendor/symfony/console/Descriptor/Descriptor.php b/vendor/symfony/console/Descriptor/Descriptor.php index 1476f575..7b2509c6 100644 --- a/vendor/symfony/console/Descriptor/Descriptor.php +++ b/vendor/symfony/console/Descriptor/Descriptor.php @@ -26,12 +26,9 @@ use Symfony\Component\Console\Output\OutputInterface; */ abstract class Descriptor implements DescriptorInterface { - /** - * @var OutputInterface - */ - protected $output; + protected OutputInterface $output; - public function describe(OutputInterface $output, object $object, array $options = []) + public function describe(OutputInterface $output, object $object, array $options = []): void { $this->output = $output; @@ -45,10 +42,7 @@ abstract class Descriptor implements DescriptorInterface }; } - /** - * Writes content to output. - */ - protected function write(string $content, bool $decorated = false) + protected function write(string $content, bool $decorated = false): void { $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW); } @@ -56,25 +50,25 @@ abstract class Descriptor implements DescriptorInterface /** * Describes an InputArgument instance. */ - abstract protected function describeInputArgument(InputArgument $argument, array $options = []); + abstract protected function describeInputArgument(InputArgument $argument, array $options = []): void; /** * Describes an InputOption instance. */ - abstract protected function describeInputOption(InputOption $option, array $options = []); + abstract protected function describeInputOption(InputOption $option, array $options = []): void; /** * Describes an InputDefinition instance. */ - abstract protected function describeInputDefinition(InputDefinition $definition, array $options = []); + abstract protected function describeInputDefinition(InputDefinition $definition, array $options = []): void; /** * Describes a Command instance. */ - abstract protected function describeCommand(Command $command, array $options = []); + abstract protected function describeCommand(Command $command, array $options = []): void; /** * Describes an Application instance. */ - abstract protected function describeApplication(Application $application, array $options = []); + abstract protected function describeApplication(Application $application, array $options = []): void; } diff --git a/vendor/symfony/console/Descriptor/DescriptorInterface.php b/vendor/symfony/console/Descriptor/DescriptorInterface.php index ebea3036..ab468a25 100644 --- a/vendor/symfony/console/Descriptor/DescriptorInterface.php +++ b/vendor/symfony/console/Descriptor/DescriptorInterface.php @@ -20,5 +20,8 @@ use Symfony\Component\Console\Output\OutputInterface; */ interface DescriptorInterface { + /** + * @return void + */ public function describe(OutputInterface $output, object $object, array $options = []); } diff --git a/vendor/symfony/console/Descriptor/JsonDescriptor.php b/vendor/symfony/console/Descriptor/JsonDescriptor.php index 6f79a17a..95630370 100644 --- a/vendor/symfony/console/Descriptor/JsonDescriptor.php +++ b/vendor/symfony/console/Descriptor/JsonDescriptor.php @@ -26,12 +26,12 @@ use Symfony\Component\Console\Input\InputOption; */ class JsonDescriptor extends Descriptor { - protected function describeInputArgument(InputArgument $argument, array $options = []) + protected function describeInputArgument(InputArgument $argument, array $options = []): void { $this->writeData($this->getInputArgumentData($argument), $options); } - protected function describeInputOption(InputOption $option, array $options = []) + protected function describeInputOption(InputOption $option, array $options = []): void { $this->writeData($this->getInputOptionData($option), $options); if ($option->isNegatable()) { @@ -39,17 +39,17 @@ class JsonDescriptor extends Descriptor } } - protected function describeInputDefinition(InputDefinition $definition, array $options = []) + protected function describeInputDefinition(InputDefinition $definition, array $options = []): void { $this->writeData($this->getInputDefinitionData($definition), $options); } - protected function describeCommand(Command $command, array $options = []) + protected function describeCommand(Command $command, array $options = []): void { $this->writeData($this->getCommandData($command, $options['short'] ?? false), $options); } - protected function describeApplication(Application $application, array $options = []) + protected function describeApplication(Application $application, array $options = []): void { $describedNamespace = $options['namespace'] ?? null; $description = new ApplicationDescription($application, $describedNamespace, true); @@ -81,7 +81,7 @@ class JsonDescriptor extends Descriptor /** * Writes data as json. */ - private function writeData(array $data, array $options) + private function writeData(array $data, array $options): void { $flags = $options['json_encoding'] ?? 0; diff --git a/vendor/symfony/console/Descriptor/MarkdownDescriptor.php b/vendor/symfony/console/Descriptor/MarkdownDescriptor.php index fbd9c534..b3f16ee9 100644 --- a/vendor/symfony/console/Descriptor/MarkdownDescriptor.php +++ b/vendor/symfony/console/Descriptor/MarkdownDescriptor.php @@ -28,7 +28,7 @@ use Symfony\Component\Console\Output\OutputInterface; */ class MarkdownDescriptor extends Descriptor { - public function describe(OutputInterface $output, object $object, array $options = []) + public function describe(OutputInterface $output, object $object, array $options = []): void { $decorated = $output->isDecorated(); $output->setDecorated(false); @@ -38,12 +38,12 @@ class MarkdownDescriptor extends Descriptor $output->setDecorated($decorated); } - protected function write(string $content, bool $decorated = true) + protected function write(string $content, bool $decorated = true): void { parent::write($content, $decorated); } - protected function describeInputArgument(InputArgument $argument, array $options = []) + protected function describeInputArgument(InputArgument $argument, array $options = []): void { $this->write( '#### `'.($argument->getName() ?: '')."`\n\n" @@ -54,7 +54,7 @@ class MarkdownDescriptor extends Descriptor ); } - protected function describeInputOption(InputOption $option, array $options = []) + protected function describeInputOption(InputOption $option, array $options = []): void { $name = '--'.$option->getName(); if ($option->isNegatable()) { @@ -75,15 +75,13 @@ class MarkdownDescriptor extends Descriptor ); } - protected function describeInputDefinition(InputDefinition $definition, array $options = []) + protected function describeInputDefinition(InputDefinition $definition, array $options = []): void { if ($showArguments = \count($definition->getArguments()) > 0) { $this->write('### Arguments'); foreach ($definition->getArguments() as $argument) { $this->write("\n\n"); - if (null !== $describeInputArgument = $this->describeInputArgument($argument)) { - $this->write($describeInputArgument); - } + $this->describeInputArgument($argument); } } @@ -95,14 +93,12 @@ class MarkdownDescriptor extends Descriptor $this->write('### Options'); foreach ($definition->getOptions() as $option) { $this->write("\n\n"); - if (null !== $describeInputOption = $this->describeInputOption($option)) { - $this->write($describeInputOption); - } + $this->describeInputOption($option); } } } - protected function describeCommand(Command $command, array $options = []) + protected function describeCommand(Command $command, array $options = []): void { if ($options['short'] ?? false) { $this->write( @@ -110,9 +106,7 @@ class MarkdownDescriptor extends Descriptor .str_repeat('-', Helper::width($command->getName()) + 2)."\n\n" .($command->getDescription() ? $command->getDescription()."\n\n" : '') .'### Usage'."\n\n" - .array_reduce($command->getAliases(), function ($carry, $usage) { - return $carry.'* `'.$usage.'`'."\n"; - }) + .array_reduce($command->getAliases(), fn ($carry, $usage) => $carry.'* `'.$usage.'`'."\n") ); return; @@ -125,9 +119,7 @@ class MarkdownDescriptor extends Descriptor .str_repeat('-', Helper::width($command->getName()) + 2)."\n\n" .($command->getDescription() ? $command->getDescription()."\n\n" : '') .'### Usage'."\n\n" - .array_reduce(array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), function ($carry, $usage) { - return $carry.'* `'.$usage.'`'."\n"; - }) + .array_reduce(array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), fn ($carry, $usage) => $carry.'* `'.$usage.'`'."\n") ); if ($help = $command->getProcessedHelp()) { @@ -142,7 +134,7 @@ class MarkdownDescriptor extends Descriptor } } - protected function describeApplication(Application $application, array $options = []) + protected function describeApplication(Application $application, array $options = []): void { $describedNamespace = $options['namespace'] ?? null; $description = new ApplicationDescription($application, $describedNamespace); @@ -157,16 +149,12 @@ class MarkdownDescriptor extends Descriptor } $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']))); + $this->write(implode("\n", array_map(fn ($commandName) => sprintf('* [`%s`](#%s)', $commandName, str_replace(':', '', $description->getCommand($commandName)->getName())), $namespace['commands']))); } foreach ($description->getCommands() as $command) { $this->write("\n\n"); - if (null !== $describeCommand = $this->describeCommand($command, $options)) { - $this->write($describeCommand); - } + $this->describeCommand($command, $options); } } diff --git a/vendor/symfony/console/Descriptor/ReStructuredTextDescriptor.php b/vendor/symfony/console/Descriptor/ReStructuredTextDescriptor.php new file mode 100644 index 00000000..d4423fd3 --- /dev/null +++ b/vendor/symfony/console/Descriptor/ReStructuredTextDescriptor.php @@ -0,0 +1,272 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\String\UnicodeString; + +class ReStructuredTextDescriptor extends Descriptor +{ + //

+ private string $partChar = '='; + //

+ private string $chapterChar = '-'; + //

+ private string $sectionChar = '~'; + //

+ private string $subsectionChar = '.'; + //

+ private string $subsubsectionChar = '^'; + //
+ private string $paragraphsChar = '"'; + + private array $visibleNamespaces = []; + + public function describe(OutputInterface $output, object $object, array $options = []): void + { + $decorated = $output->isDecorated(); + $output->setDecorated(false); + + parent::describe($output, $object, $options); + + $output->setDecorated($decorated); + } + + /** + * Override parent method to set $decorated = true. + */ + protected function write(string $content, bool $decorated = true): void + { + parent::write($content, $decorated); + } + + protected function describeInputArgument(InputArgument $argument, array $options = []): void + { + $this->write( + $argument->getName() ?: ''."\n".str_repeat($this->paragraphsChar, Helper::width($argument->getName()))."\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)).'``' + ); + } + + protected function describeInputOption(InputOption $option, array $options = []): void + { + $name = '\-\-'.$option->getName(); + if ($option->isNegatable()) { + $name .= '|\-\-no-'.$option->getName(); + } + if ($option->getShortcut()) { + $name .= '|-'.str_replace('|', '|-', $option->getShortcut()); + } + + $optionDescription = $option->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n\n", $option->getDescription())."\n\n" : ''; + $optionDescription = (new UnicodeString($optionDescription))->ascii(); + $this->write( + $name."\n".str_repeat($this->paragraphsChar, Helper::width($name))."\n\n" + .$optionDescription + .'- **Accept value**: '.($option->acceptValue() ? 'yes' : 'no')."\n" + .'- **Is value required**: '.($option->isValueRequired() ? 'yes' : 'no')."\n" + .'- **Is multiple**: '.($option->isArray() ? 'yes' : 'no')."\n" + .'- **Is negatable**: '.($option->isNegatable() ? 'yes' : 'no')."\n" + .'- **Default**: ``'.str_replace("\n", '', var_export($option->getDefault(), true)).'``'."\n" + ); + } + + protected function describeInputDefinition(InputDefinition $definition, array $options = []): void + { + if ($showArguments = ((bool) $definition->getArguments())) { + $this->write("Arguments\n".str_repeat($this->subsubsectionChar, 9))."\n\n"; + foreach ($definition->getArguments() as $argument) { + $this->write("\n\n"); + $this->describeInputArgument($argument); + } + } + + if ($nonDefaultOptions = $this->getNonDefaultOptions($definition)) { + if ($showArguments) { + $this->write("\n\n"); + } + + $this->write("Options\n".str_repeat($this->subsubsectionChar, 7)."\n\n"); + foreach ($nonDefaultOptions as $option) { + $this->describeInputOption($option); + $this->write("\n"); + } + } + } + + protected function describeCommand(Command $command, array $options = []): void + { + if ($options['short'] ?? false) { + $this->write( + '``'.$command->getName()."``\n" + .str_repeat($this->subsectionChar, Helper::width($command->getName()))."\n\n" + .($command->getDescription() ? $command->getDescription()."\n\n" : '') + ."Usage\n".str_repeat($this->paragraphsChar, 5)."\n\n" + .array_reduce($command->getAliases(), static fn ($carry, $usage) => $carry.'- ``'.$usage.'``'."\n") + ); + + return; + } + + $command->mergeApplicationDefinition(false); + + foreach ($command->getAliases() as $alias) { + $this->write('.. _'.$alias.":\n\n"); + } + $this->write( + $command->getName()."\n" + .str_repeat($this->subsectionChar, Helper::width($command->getName()))."\n\n" + .($command->getDescription() ? $command->getDescription()."\n\n" : '') + ."Usage\n".str_repeat($this->subsubsectionChar, 5)."\n\n" + .array_reduce(array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), static fn ($carry, $usage) => $carry.'- ``'.$usage.'``'."\n") + ); + + if ($help = $command->getProcessedHelp()) { + $this->write("\n"); + $this->write($help); + } + + $definition = $command->getDefinition(); + if ($definition->getOptions() || $definition->getArguments()) { + $this->write("\n\n"); + $this->describeInputDefinition($definition); + } + } + + protected function describeApplication(Application $application, array $options = []): void + { + $description = new ApplicationDescription($application, $options['namespace'] ?? null); + $title = $this->getApplicationTitle($application); + + $this->write($title."\n".str_repeat($this->partChar, Helper::width($title))); + $this->createTableOfContents($description, $application); + $this->describeCommands($application, $options); + } + + private function getApplicationTitle(Application $application): string + { + if ('UNKNOWN' === $application->getName()) { + return 'Console Tool'; + } + if ('UNKNOWN' !== $application->getVersion()) { + return sprintf('%s %s', $application->getName(), $application->getVersion()); + } + + return $application->getName(); + } + + private function describeCommands($application, array $options): void + { + $title = 'Commands'; + $this->write("\n\n$title\n".str_repeat($this->chapterChar, Helper::width($title))."\n\n"); + foreach ($this->visibleNamespaces as $namespace) { + if ('_global' === $namespace) { + $commands = $application->all(''); + $this->write('Global'."\n".str_repeat($this->sectionChar, Helper::width('Global'))."\n\n"); + } else { + $commands = $application->all($namespace); + $this->write($namespace."\n".str_repeat($this->sectionChar, Helper::width($namespace))."\n\n"); + } + + foreach ($this->removeAliasesAndHiddenCommands($commands) as $command) { + $this->describeCommand($command, $options); + $this->write("\n\n"); + } + } + } + + private function createTableOfContents(ApplicationDescription $description, Application $application): void + { + $this->setVisibleNamespaces($description); + $chapterTitle = 'Table of Contents'; + $this->write("\n\n$chapterTitle\n".str_repeat($this->chapterChar, Helper::width($chapterTitle))."\n\n"); + foreach ($this->visibleNamespaces as $namespace) { + if ('_global' === $namespace) { + $commands = $application->all(''); + } else { + $commands = $application->all($namespace); + $this->write("\n\n"); + $this->write($namespace."\n".str_repeat($this->sectionChar, Helper::width($namespace))."\n\n"); + } + $commands = $this->removeAliasesAndHiddenCommands($commands); + + $this->write("\n\n"); + $this->write(implode("\n", array_map(static fn ($commandName) => sprintf('- `%s`_', $commandName), array_keys($commands)))); + } + } + + private function getNonDefaultOptions(InputDefinition $definition): array + { + $globalOptions = [ + 'help', + 'quiet', + 'verbose', + 'version', + 'ansi', + 'no-interaction', + ]; + $nonDefaultOptions = []; + foreach ($definition->getOptions() as $option) { + // Skip global options. + if (!\in_array($option->getName(), $globalOptions)) { + $nonDefaultOptions[] = $option; + } + } + + return $nonDefaultOptions; + } + + private function setVisibleNamespaces(ApplicationDescription $description): void + { + $commands = $description->getCommands(); + foreach ($description->getNamespaces() as $namespace) { + try { + $namespaceCommands = $namespace['commands']; + foreach ($namespaceCommands as $key => $commandName) { + if (!\array_key_exists($commandName, $commands)) { + // If the array key does not exist, then this is an alias. + unset($namespaceCommands[$key]); + } elseif ($commands[$commandName]->isHidden()) { + unset($namespaceCommands[$key]); + } + } + if (!$namespaceCommands) { + // If the namespace contained only aliases or hidden commands, skip the namespace. + continue; + } + } catch (\Exception) { + } + $this->visibleNamespaces[] = $namespace['id']; + } + } + + private function removeAliasesAndHiddenCommands(array $commands): array + { + foreach ($commands as $key => $command) { + if ($command->isHidden() || \in_array($key, $command->getAliases(), true)) { + unset($commands[$key]); + } + } + unset($commands['completion']); + + return $commands; + } +} diff --git a/vendor/symfony/console/Descriptor/TextDescriptor.php b/vendor/symfony/console/Descriptor/TextDescriptor.php index 48a0b42a..d04d1023 100644 --- a/vendor/symfony/console/Descriptor/TextDescriptor.php +++ b/vendor/symfony/console/Descriptor/TextDescriptor.php @@ -28,7 +28,7 @@ use Symfony\Component\Console\Input\InputOption; */ class TextDescriptor extends Descriptor { - protected function describeInputArgument(InputArgument $argument, array $options = []) + protected function describeInputArgument(InputArgument $argument, array $options = []): void { if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) { $default = sprintf(' [default: %s]', $this->formatDefaultValue($argument->getDefault())); @@ -48,7 +48,7 @@ class TextDescriptor extends Descriptor ), $options); } - protected function describeInputOption(InputOption $option, array $options = []) + protected function describeInputOption(InputOption $option, array $options = []): void { if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) { $default = sprintf(' [default: %s]', $this->formatDefaultValue($option->getDefault())); @@ -83,7 +83,7 @@ class TextDescriptor extends Descriptor ), $options); } - protected function describeInputDefinition(InputDefinition $definition, array $options = []) + protected function describeInputDefinition(InputDefinition $definition, array $options = []): void { $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions()); foreach ($definition->getArguments() as $argument) { @@ -122,7 +122,7 @@ class TextDescriptor extends Descriptor } } - protected function describeCommand(Command $command, array $options = []) + protected function describeCommand(Command $command, array $options = []): void { $command->mergeApplicationDefinition(false); @@ -157,7 +157,7 @@ class TextDescriptor extends Descriptor } } - protected function describeApplication(Application $application, array $options = []) + protected function describeApplication(Application $application, array $options = []): void { $describedNamespace = $options['namespace'] ?? null; $description = new ApplicationDescription($application, $describedNamespace); @@ -193,9 +193,7 @@ class TextDescriptor extends Descriptor } // calculate max. width based on available commands per namespace - $width = $this->getColumnWidth(array_merge(...array_values(array_map(function ($namespace) use ($commands) { - return array_intersect($namespace['commands'], array_keys($commands)); - }, array_values($namespaces))))); + $width = $this->getColumnWidth(array_merge(...array_values(array_map(fn ($namespace) => array_intersect($namespace['commands'], array_keys($commands)), array_values($namespaces))))); if ($describedNamespace) { $this->writeText(sprintf('Available commands for the "%s" namespace:', $describedNamespace), $options); @@ -204,9 +202,7 @@ class TextDescriptor extends Descriptor } foreach ($namespaces as $namespace) { - $namespace['commands'] = array_filter($namespace['commands'], function ($name) use ($commands) { - return isset($commands[$name]); - }); + $namespace['commands'] = array_filter($namespace['commands'], fn ($name) => isset($commands[$name])); if (!$namespace['commands']) { continue; @@ -230,7 +226,7 @@ class TextDescriptor extends Descriptor } } - private function writeText(string $content, array $options = []) + private function writeText(string $content, array $options = []): void { $this->write( isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, diff --git a/vendor/symfony/console/Descriptor/XmlDescriptor.php b/vendor/symfony/console/Descriptor/XmlDescriptor.php index f4643a9a..72580fd9 100644 --- a/vendor/symfony/console/Descriptor/XmlDescriptor.php +++ b/vendor/symfony/console/Descriptor/XmlDescriptor.php @@ -120,27 +120,27 @@ class XmlDescriptor extends Descriptor return $dom; } - protected function describeInputArgument(InputArgument $argument, array $options = []) + protected function describeInputArgument(InputArgument $argument, array $options = []): void { $this->writeDocument($this->getInputArgumentDocument($argument)); } - protected function describeInputOption(InputOption $option, array $options = []) + protected function describeInputOption(InputOption $option, array $options = []): void { $this->writeDocument($this->getInputOptionDocument($option)); } - protected function describeInputDefinition(InputDefinition $definition, array $options = []) + protected function describeInputDefinition(InputDefinition $definition, array $options = []): void { $this->writeDocument($this->getInputDefinitionDocument($definition)); } - protected function describeCommand(Command $command, array $options = []) + protected function describeCommand(Command $command, array $options = []): void { $this->writeDocument($this->getCommandDocument($command, $options['short'] ?? false)); } - protected function describeApplication(Application $application, array $options = []) + protected function describeApplication(Application $application, array $options = []): void { $this->writeDocument($this->getApplicationDocument($application, $options['namespace'] ?? null, $options['short'] ?? false)); } @@ -148,7 +148,7 @@ class XmlDescriptor extends Descriptor /** * Appends document children to parent node. */ - private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent) + private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent): void { foreach ($importedParent->childNodes as $childNode) { $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true)); @@ -158,7 +158,7 @@ class XmlDescriptor extends Descriptor /** * Writes DOM document. */ - private function writeDocument(\DOMDocument $dom) + private function writeDocument(\DOMDocument $dom): void { $dom->formatOutput = true; $this->write($dom->saveXML()); diff --git a/vendor/symfony/console/Event/ConsoleSignalEvent.php b/vendor/symfony/console/Event/ConsoleSignalEvent.php index 766af691..95af1f91 100644 --- a/vendor/symfony/console/Event/ConsoleSignalEvent.php +++ b/vendor/symfony/console/Event/ConsoleSignalEvent.php @@ -21,15 +21,36 @@ use Symfony\Component\Console\Output\OutputInterface; final class ConsoleSignalEvent extends ConsoleEvent { private int $handlingSignal; + private int|false $exitCode; - public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $handlingSignal) + public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $handlingSignal, int|false $exitCode = 0) { parent::__construct($command, $input, $output); $this->handlingSignal = $handlingSignal; + $this->exitCode = $exitCode; } public function getHandlingSignal(): int { return $this->handlingSignal; } + + public function setExitCode(int $exitCode): void + { + if ($exitCode < 0 || $exitCode > 255) { + throw new \InvalidArgumentException('Exit code must be between 0 and 255.'); + } + + $this->exitCode = $exitCode; + } + + public function abortExit(): void + { + $this->exitCode = false; + } + + public function getExitCode(): int|false + { + return $this->exitCode; + } } diff --git a/vendor/symfony/console/EventListener/ErrorListener.php b/vendor/symfony/console/EventListener/ErrorListener.php index 773a13a1..9925a5f7 100644 --- a/vendor/symfony/console/EventListener/ErrorListener.php +++ b/vendor/symfony/console/EventListener/ErrorListener.php @@ -31,6 +31,9 @@ class ErrorListener implements EventSubscriberInterface $this->logger = $logger; } + /** + * @return void + */ public function onConsoleError(ConsoleErrorEvent $event) { if (null === $this->logger) { @@ -48,6 +51,9 @@ class ErrorListener implements EventSubscriberInterface $this->logger->critical('Error thrown while running command "{command}". Message: "{message}"', ['exception' => $error, 'command' => $inputString, 'message' => $error->getMessage()]); } + /** + * @return void + */ public function onConsoleTerminate(ConsoleTerminateEvent $event) { if (null === $this->logger) { diff --git a/vendor/symfony/console/Formatter/OutputFormatter.php b/vendor/symfony/console/Formatter/OutputFormatter.php index 38e75c31..9cb63104 100644 --- a/vendor/symfony/console/Formatter/OutputFormatter.php +++ b/vendor/symfony/console/Formatter/OutputFormatter.php @@ -81,6 +81,9 @@ class OutputFormatter implements WrappableOutputFormatterInterface $this->styleStack = new OutputFormatterStyleStack(); } + /** + * @return void + */ public function setDecorated(bool $decorated) { $this->decorated = $decorated; @@ -91,6 +94,9 @@ class OutputFormatter implements WrappableOutputFormatterInterface return $this->decorated; } + /** + * @return void + */ public function setStyle(string $name, OutputFormatterStyleInterface $style) { $this->styles[strtolower($name)] = $style; @@ -115,6 +121,9 @@ class OutputFormatter implements WrappableOutputFormatterInterface return $this->formatAndWrap($message, 0); } + /** + * @return string + */ public function formatAndWrap(?string $message, int $width) { if (null === $message) { diff --git a/vendor/symfony/console/Formatter/OutputFormatterInterface.php b/vendor/symfony/console/Formatter/OutputFormatterInterface.php index b94e51de..433cd419 100644 --- a/vendor/symfony/console/Formatter/OutputFormatterInterface.php +++ b/vendor/symfony/console/Formatter/OutputFormatterInterface.php @@ -20,6 +20,8 @@ interface OutputFormatterInterface { /** * Sets the decorated flag. + * + * @return void */ public function setDecorated(bool $decorated); @@ -30,6 +32,8 @@ interface OutputFormatterInterface /** * Sets a new style. + * + * @return void */ public function setStyle(string $name, OutputFormatterStyleInterface $style); diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyle.php b/vendor/symfony/console/Formatter/OutputFormatterStyle.php index 3394c9ad..346a474c 100644 --- a/vendor/symfony/console/Formatter/OutputFormatterStyle.php +++ b/vendor/symfony/console/Formatter/OutputFormatterStyle.php @@ -38,6 +38,9 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface $this->color = new Color($this->foreground = $foreground ?: '', $this->background = $background ?: '', $this->options = $options); } + /** + * @return void + */ public function setForeground(string $color = null) { if (1 > \func_num_args()) { @@ -46,6 +49,9 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface $this->color = new Color($this->foreground = $color ?: '', $this->background, $this->options); } + /** + * @return void + */ public function setBackground(string $color = null) { if (1 > \func_num_args()) { @@ -59,12 +65,18 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface $this->href = $url; } + /** + * @return void + */ public function setOption(string $option) { $this->options[] = $option; $this->color = new Color($this->foreground, $this->background, $this->options); } + /** + * @return void + */ public function unsetOption(string $option) { $pos = array_search($option, $this->options); @@ -75,6 +87,9 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface $this->color = new Color($this->foreground, $this->background, $this->options); } + /** + * @return void + */ public function setOptions(array $options) { $this->color = new Color($this->foreground, $this->background, $this->options = $options); diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php b/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php index 7ed67d9a..3b15098c 100644 --- a/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php +++ b/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php @@ -20,26 +20,36 @@ interface OutputFormatterStyleInterface { /** * Sets style foreground color. + * + * @return void */ public function setForeground(?string $color); /** * Sets style background color. + * + * @return void */ public function setBackground(?string $color); /** * Sets some specific style option. + * + * @return void */ public function setOption(string $option); /** * Unsets some specific style option. + * + * @return void */ public function unsetOption(string $option); /** * Sets multiple style options at once. + * + * @return void */ public function setOptions(array $options); diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php b/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php index 2c5cdf9b..f98c2eff 100644 --- a/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php +++ b/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php @@ -34,6 +34,8 @@ class OutputFormatterStyleStack implements ResetInterface /** * Resets stack (ie. empty internal arrays). + * + * @return void */ public function reset() { @@ -42,6 +44,8 @@ class OutputFormatterStyleStack implements ResetInterface /** * Pushes a style in the stack. + * + * @return void */ public function push(OutputFormatterStyleInterface $style) { diff --git a/vendor/symfony/console/Helper/DescriptorHelper.php b/vendor/symfony/console/Helper/DescriptorHelper.php index 3015ff08..eb32bce8 100644 --- a/vendor/symfony/console/Helper/DescriptorHelper.php +++ b/vendor/symfony/console/Helper/DescriptorHelper.php @@ -14,6 +14,7 @@ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Descriptor\DescriptorInterface; use Symfony\Component\Console\Descriptor\JsonDescriptor; use Symfony\Component\Console\Descriptor\MarkdownDescriptor; +use Symfony\Component\Console\Descriptor\ReStructuredTextDescriptor; use Symfony\Component\Console\Descriptor\TextDescriptor; use Symfony\Component\Console\Descriptor\XmlDescriptor; use Symfony\Component\Console\Exception\InvalidArgumentException; @@ -38,6 +39,7 @@ class DescriptorHelper extends Helper ->register('xml', new XmlDescriptor()) ->register('json', new JsonDescriptor()) ->register('md', new MarkdownDescriptor()) + ->register('rst', new ReStructuredTextDescriptor()) ; } @@ -48,6 +50,8 @@ class DescriptorHelper extends Helper * * format: string, the output format name * * raw_text: boolean, sets output type as raw * + * @return void + * * @throws InvalidArgumentException when the given format is not supported */ public function describe(OutputInterface $output, ?object $object, array $options = []) diff --git a/vendor/symfony/console/Helper/Dumper.php b/vendor/symfony/console/Helper/Dumper.php index ac7571ce..8c6a94d5 100644 --- a/vendor/symfony/console/Helper/Dumper.php +++ b/vendor/symfony/console/Helper/Dumper.php @@ -40,14 +40,12 @@ final class Dumper return rtrim($dumper->dump(($this->cloner ??= new VarCloner())->cloneVar($var)->withRefHandles(false), true)); }; } else { - $this->handler = function ($var): string { - return match (true) { - null === $var => 'null', - true === $var => 'true', - false === $var => 'false', - \is_string($var) => '"'.$var.'"', - default => rtrim(print_r($var, true)), - }; + $this->handler = fn ($var): string => match (true) { + null === $var => 'null', + true === $var => 'true', + false === $var => 'false', + \is_string($var) => '"'.$var.'"', + default => rtrim(print_r($var, true)), }; } } diff --git a/vendor/symfony/console/Helper/Helper.php b/vendor/symfony/console/Helper/Helper.php index 920196e0..3631b30f 100644 --- a/vendor/symfony/console/Helper/Helper.php +++ b/vendor/symfony/console/Helper/Helper.php @@ -21,8 +21,11 @@ use Symfony\Component\String\UnicodeString; */ abstract class Helper implements HelperInterface { - protected $helperSet = null; + protected $helperSet; + /** + * @return void + */ public function setHelperSet(HelperSet $helperSet = null) { if (1 > \func_num_args()) { @@ -88,6 +91,9 @@ abstract class Helper implements HelperInterface return mb_substr($string, $from, $length, $encoding); } + /** + * @return string + */ public static function formatTime(int|float $secs) { static $timeFormats = [ @@ -117,6 +123,9 @@ abstract class Helper implements HelperInterface } } + /** + * @return string + */ public static function formatMemory(int $memory) { if ($memory >= 1024 * 1024 * 1024) { @@ -134,6 +143,9 @@ abstract class Helper implements HelperInterface return sprintf('%d B', $memory); } + /** + * @return string + */ public static function removeDecoration(OutputFormatterInterface $formatter, ?string $string) { $isDecorated = $formatter->isDecorated(); diff --git a/vendor/symfony/console/Helper/HelperInterface.php b/vendor/symfony/console/Helper/HelperInterface.php index 2762cdf0..ab626c93 100644 --- a/vendor/symfony/console/Helper/HelperInterface.php +++ b/vendor/symfony/console/Helper/HelperInterface.php @@ -20,6 +20,8 @@ interface HelperInterface { /** * Sets the helper set associated with this helper. + * + * @return void */ public function setHelperSet(?HelperSet $helperSet); diff --git a/vendor/symfony/console/Helper/HelperSet.php b/vendor/symfony/console/Helper/HelperSet.php index cefe62be..dc5d499c 100644 --- a/vendor/symfony/console/Helper/HelperSet.php +++ b/vendor/symfony/console/Helper/HelperSet.php @@ -35,6 +35,9 @@ class HelperSet implements \IteratorAggregate } } + /** + * @return void + */ public function set(HelperInterface $helper, string $alias = null) { $this->helpers[$helper->getName()] = $helper; diff --git a/vendor/symfony/console/Helper/InputAwareHelper.php b/vendor/symfony/console/Helper/InputAwareHelper.php index ba81e377..6f822597 100644 --- a/vendor/symfony/console/Helper/InputAwareHelper.php +++ b/vendor/symfony/console/Helper/InputAwareHelper.php @@ -23,6 +23,9 @@ abstract class InputAwareHelper extends Helper implements InputAwareInterface { protected $input; + /** + * @return void + */ public function setInput(InputInterface $input) { $this->input = $input; diff --git a/vendor/symfony/console/Helper/ProgressBar.php b/vendor/symfony/console/Helper/ProgressBar.php index 0d112609..19faea47 100644 --- a/vendor/symfony/console/Helper/ProgressBar.php +++ b/vendor/symfony/console/Helper/ProgressBar.php @@ -59,6 +59,7 @@ final class ProgressBar private Terminal $terminal; private ?string $previousMessage = null; private Cursor $cursor; + private array $placeholders = []; private static array $formatters; private static array $formats; @@ -94,12 +95,12 @@ final class ProgressBar } /** - * Sets a placeholder formatter for a given name. + * Sets a placeholder formatter for a given name, globally for all instances of ProgressBar. * * 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 + * @param string $name The placeholder name (including the delimiter char like %) + * @param callable(ProgressBar):string $callable A PHP callable */ public static function setPlaceholderFormatterDefinition(string $name, callable $callable): void { @@ -120,6 +121,26 @@ final class ProgressBar return self::$formatters[$name] ?? null; } + /** + * Sets a placeholder formatter for a given name, for this instance only. + * + * @param callable(ProgressBar):string $callable A PHP callable + */ + public function setPlaceholderFormatter(string $name, callable $callable): void + { + $this->placeholders[$name] = $callable; + } + + /** + * Gets the placeholder formatter for a given name. + * + * @param string $name The placeholder name (including the delimiter char like %) + */ + public function getPlaceholderFormatter(string $name): ?callable + { + return $this->placeholders[$name] ?? $this::getPlaceholderFormatterDefinition($name); + } + /** * Sets a format for a given name. * @@ -157,12 +178,12 @@ final class ProgressBar * @param string $message The text to associate with the placeholder * @param string $name The name of the placeholder */ - public function setMessage(string $message, string $name = 'message') + public function setMessage(string $message, string $name = 'message'): void { $this->messages[$name] = $message; } - public function getMessage(string $name = 'message') + public function getMessage(string $name = 'message'): string { return $this->messages[$name]; } @@ -215,7 +236,7 @@ final class ProgressBar return round((time() - $this->startTime) / ($this->step - $this->startingStep) * ($this->max - $this->step)); } - public function setBarWidth(int $size) + public function setBarWidth(int $size): void { $this->barWidth = max(1, $size); } @@ -225,7 +246,7 @@ final class ProgressBar return $this->barWidth; } - public function setBarCharacter(string $char) + public function setBarCharacter(string $char): void { $this->barChar = $char; } @@ -235,7 +256,7 @@ final class ProgressBar return $this->barChar ?? ($this->max ? '=' : $this->emptyBarChar); } - public function setEmptyBarCharacter(string $char) + public function setEmptyBarCharacter(string $char): void { $this->emptyBarChar = $char; } @@ -245,7 +266,7 @@ final class ProgressBar return $this->emptyBarChar; } - public function setProgressCharacter(string $char) + public function setProgressCharacter(string $char): void { $this->progressChar = $char; } @@ -255,7 +276,7 @@ final class ProgressBar return $this->progressChar; } - public function setFormat(string $format) + public function setFormat(string $format): void { $this->format = null; $this->internalFormat = $format; @@ -266,7 +287,7 @@ final class ProgressBar * * @param int|null $freq The frequency in steps */ - public function setRedrawFrequency(?int $freq) + public function setRedrawFrequency(?int $freq): void { $this->redrawFreq = null !== $freq ? max(1, $freq) : null; } @@ -325,7 +346,7 @@ final class ProgressBar * * @param int $step Number of steps to advance */ - public function advance(int $step = 1) + public function advance(int $step = 1): void { $this->setProgress($this->step + $step); } @@ -333,12 +354,12 @@ final class ProgressBar /** * Sets whether to overwrite the progressbar, false for new line. */ - public function setOverwrite(bool $overwrite) + public function setOverwrite(bool $overwrite): void { $this->overwrite = $overwrite; } - public function setProgress(int $step) + public function setProgress(int $step): void { if ($this->max && $step > $this->max) { $this->max = $step; @@ -371,7 +392,7 @@ final class ProgressBar } } - public function setMaxSteps(int $max) + public function setMaxSteps(int $max): void { $this->format = null; $this->max = max(0, $max); @@ -431,7 +452,7 @@ final class ProgressBar $this->overwrite(''); } - private function setRealFormat(string $format) + private function setRealFormat(string $format): void { // try to use the _nomax variant if available if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) { @@ -513,9 +534,7 @@ final class ProgressBar return $display; }, - 'elapsed' => function (self $bar) { - return Helper::formatTime(time() - $bar->getStartTime()); - }, + 'elapsed' => fn (self $bar) => Helper::formatTime(time() - $bar->getStartTime()), 'remaining' => function (self $bar) { if (!$bar->getMaxSteps()) { throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.'); @@ -530,18 +549,10 @@ final class ProgressBar return Helper::formatTime($bar->getEstimated()); }, - 'memory' => function (self $bar) { - return Helper::formatMemory(memory_get_usage(true)); - }, - 'current' => function (self $bar) { - return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', \STR_PAD_LEFT); - }, - 'max' => function (self $bar) { - return $bar->getMaxSteps(); - }, - 'percent' => function (self $bar) { - return floor($bar->getProgressPercent() * 100); - }, + 'memory' => fn (self $bar) => Helper::formatMemory(memory_get_usage(true)), + 'current' => fn (self $bar) => str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', \STR_PAD_LEFT), + 'max' => fn (self $bar) => $bar->getMaxSteps(), + 'percent' => fn (self $bar) => floor($bar->getProgressPercent() * 100), ]; } @@ -568,7 +579,7 @@ final class ProgressBar $regex = "{%([a-z\-_]+)(?:\:([^%]+))?%}i"; $callback = function ($matches) { - if ($formatter = $this::getPlaceholderFormatterDefinition($matches[1])) { + if ($formatter = $this->getPlaceholderFormatter($matches[1])) { $text = $formatter($this, $this->output); } elseif (isset($this->messages[$matches[1]])) { $text = $this->messages[$matches[1]]; @@ -585,9 +596,7 @@ final class ProgressBar $line = preg_replace_callback($regex, $callback, $this->format); // gets string length for each sub line with multiline format - $linesLength = array_map(function ($subLine) { - return Helper::width(Helper::removeDecoration($this->output->getFormatter(), rtrim($subLine, "\r"))); - }, explode("\n", $line)); + $linesLength = array_map(fn ($subLine) => Helper::width(Helper::removeDecoration($this->output->getFormatter(), rtrim($subLine, "\r"))), explode("\n", $line)); $linesWidth = max($linesLength); diff --git a/vendor/symfony/console/Helper/ProgressIndicator.php b/vendor/symfony/console/Helper/ProgressIndicator.php index b5fa24c4..84dbef95 100644 --- a/vendor/symfony/console/Helper/ProgressIndicator.php +++ b/vendor/symfony/console/Helper/ProgressIndicator.php @@ -70,6 +70,8 @@ class ProgressIndicator /** * Sets the current indicator message. + * + * @return void */ public function setMessage(?string $message) { @@ -80,6 +82,8 @@ class ProgressIndicator /** * Starts the indicator output. + * + * @return void */ public function start(string $message) { @@ -98,6 +102,8 @@ class ProgressIndicator /** * Advances the indicator. + * + * @return void */ public function advance() { @@ -123,6 +129,8 @@ class ProgressIndicator /** * Finish the indicator with message. + * + * @return void */ public function finish(string $message) { @@ -148,6 +156,8 @@ class ProgressIndicator * Sets a placeholder formatter for a given name. * * This method also allow you to override an existing placeholder. + * + * @return void */ public static function setPlaceholderFormatterDefinition(string $name, callable $callable) { @@ -166,7 +176,7 @@ class ProgressIndicator return self::$formatters[$name] ?? null; } - private function display() + private function display(): void { if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) { return; @@ -195,7 +205,7 @@ class ProgressIndicator /** * Overwrites a previous message to the output. */ - private function overwrite(string $message) + private function overwrite(string $message): void { if ($this->output->isDecorated()) { $this->output->write("\x0D\x1B[2K"); @@ -216,18 +226,10 @@ class ProgressIndicator private static function initPlaceholderFormatters(): array { return [ - 'indicator' => function (self $indicator) { - return $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)]; - }, - 'message' => function (self $indicator) { - return $indicator->message; - }, - 'elapsed' => function (self $indicator) { - return Helper::formatTime(time() - $indicator->startTime); - }, - 'memory' => function () { - return Helper::formatMemory(memory_get_usage(true)); - }, + 'indicator' => fn (self $indicator) => $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)], + 'message' => fn (self $indicator) => $indicator->message, + 'elapsed' => fn (self $indicator) => Helper::formatTime(time() - $indicator->startTime), + 'memory' => fn () => Helper::formatMemory(memory_get_usage(true)), ]; } } diff --git a/vendor/symfony/console/Helper/QuestionHelper.php b/vendor/symfony/console/Helper/QuestionHelper.php index f26ca577..f32813c6 100644 --- a/vendor/symfony/console/Helper/QuestionHelper.php +++ b/vendor/symfony/console/Helper/QuestionHelper.php @@ -68,9 +68,7 @@ class QuestionHelper extends Helper return $this->doAsk($output, $question); } - $interviewer = function () use ($output, $question) { - return $this->doAsk($output, $question); - }; + $interviewer = fn () => $this->doAsk($output, $question); return $this->validateAttempts($interviewer, $output, $question); } catch (MissingInputException $exception) { @@ -91,6 +89,8 @@ class QuestionHelper extends Helper /** * Prevents usage of stty. + * + * @return void */ public static function disableStty() { @@ -170,7 +170,7 @@ class QuestionHelper extends Helper } if ($validator = $question->getValidator()) { - return \call_user_func($question->getValidator(), $default); + return \call_user_func($validator, $default); } elseif ($question instanceof ChoiceQuestion) { $choices = $question->getChoices(); @@ -190,6 +190,8 @@ class QuestionHelper extends Helper /** * Outputs the question prompt. + * + * @return void */ protected function writePrompt(OutputInterface $output, Question $question) { @@ -226,6 +228,8 @@ class QuestionHelper extends Helper /** * Outputs an error message. + * + * @return void */ protected function writeError(OutputInterface $output, \Exception $error) { @@ -325,9 +329,7 @@ class QuestionHelper extends Helper $matches = array_filter( $autocomplete($ret), - function ($match) use ($ret) { - return '' === $ret || str_starts_with($match, $ret); - } + fn ($match) => '' === $ret || str_starts_with($match, $ret) ); $numMatches = \count($matches); $ofs = -1; diff --git a/vendor/symfony/console/Helper/SymfonyQuestionHelper.php b/vendor/symfony/console/Helper/SymfonyQuestionHelper.php index 109045d0..8ebc8437 100644 --- a/vendor/symfony/console/Helper/SymfonyQuestionHelper.php +++ b/vendor/symfony/console/Helper/SymfonyQuestionHelper.php @@ -25,6 +25,9 @@ use Symfony\Component\Console\Style\SymfonyStyle; */ class SymfonyQuestionHelper extends QuestionHelper { + /** + * @return void + */ protected function writePrompt(OutputInterface $output, Question $question) { $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion()); @@ -80,6 +83,9 @@ class SymfonyQuestionHelper extends QuestionHelper $output->write($prompt); } + /** + * @return void + */ protected function writeError(OutputInterface $output, \Exception $error) { if ($output instanceof SymfonyStyle) { diff --git a/vendor/symfony/console/Helper/Table.php b/vendor/symfony/console/Helper/Table.php index 907c9f50..cf714873 100644 --- a/vendor/symfony/console/Helper/Table.php +++ b/vendor/symfony/console/Helper/Table.php @@ -66,6 +66,8 @@ class Table /** * Sets a style definition. + * + * @return void */ public static function setStyleDefinition(string $name, TableStyle $style) { @@ -310,6 +312,8 @@ class Table * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | * +---------------+-----------------------+------------------+ + * + * @return void */ public function render() { @@ -450,7 +454,7 @@ class Table * * +-----+-----------+-------+ */ - private function renderRowSeparator(int $type = self::SEPARATOR_MID, string $title = null, string $titleFormat = null) + private function renderRowSeparator(int $type = self::SEPARATOR_MID, string $title = null, string $titleFormat = null): void { if (!$count = $this->numberOfColumns) { return; @@ -515,7 +519,7 @@ class Table * * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | */ - private function renderRow(array $row, string $cellFormat, string $firstCellFormat = null) + private function renderRow(array $row, string $cellFormat, string $firstCellFormat = null): void { $rowContent = $this->renderColumnSeparator(self::BORDER_OUTSIDE); $columns = $this->getRowColumns($row); @@ -588,7 +592,7 @@ class Table /** * Calculate number of columns for this table. */ - private function calculateNumberOfColumns(array $rows) + private function calculateNumberOfColumns(array $rows): void { $columns = [0]; foreach ($rows as $row) { @@ -727,7 +731,7 @@ class Table /** * fill cells for a row that contains colspan > 1. */ - private function fillCells(iterable $row) + private function fillCells(iterable $row): iterable { $newRow = []; @@ -789,7 +793,7 @@ class Table /** * Calculates columns widths. */ - private function calculateColumnsWidth(iterable $groups) + private function calculateColumnsWidth(iterable $groups): void { for ($column = 0; $column < $this->numberOfColumns; ++$column) { $lengths = []; @@ -843,7 +847,7 @@ class Table /** * Called after rendering to cleanup cache data. */ - private function cleanup() + private function cleanup(): void { $this->effectiveColumnWidths = []; unset($this->numberOfColumns); diff --git a/vendor/symfony/console/Helper/TableCellStyle.php b/vendor/symfony/console/Helper/TableCellStyle.php index 65ae9e72..9419dcb4 100644 --- a/vendor/symfony/console/Helper/TableCellStyle.php +++ b/vendor/symfony/console/Helper/TableCellStyle.php @@ -67,9 +67,7 @@ class TableCellStyle { return array_filter( $this->getOptions(), - function ($key) { - return \in_array($key, self::TAG_OPTIONS) && isset($this->options[$key]); - }, + fn ($key) => \in_array($key, self::TAG_OPTIONS) && isset($this->options[$key]), \ARRAY_FILTER_USE_KEY ); } diff --git a/vendor/symfony/console/Input/ArgvInput.php b/vendor/symfony/console/Input/ArgvInput.php index c0c28bb5..59f9217e 100644 --- a/vendor/symfony/console/Input/ArgvInput.php +++ b/vendor/symfony/console/Input/ArgvInput.php @@ -55,11 +55,17 @@ class ArgvInput extends Input parent::__construct($definition); } + /** + * @return void + */ protected function setTokens(array $tokens) { $this->tokens = $tokens; } + /** + * @return void + */ protected function parse() { $parseOptions = true; @@ -89,7 +95,7 @@ class ArgvInput extends Input /** * Parses a short option. */ - private function parseShortOption(string $token) + private function parseShortOption(string $token): void { $name = substr($token, 1); @@ -110,7 +116,7 @@ class ArgvInput extends Input * * @throws RuntimeException When option given doesn't exist */ - private function parseShortOptionSet(string $name) + private function parseShortOptionSet(string $name): void { $len = \strlen($name); for ($i = 0; $i < $len; ++$i) { @@ -133,7 +139,7 @@ class ArgvInput extends Input /** * Parses a long option. */ - private function parseLongOption(string $token) + private function parseLongOption(string $token): void { $name = substr($token, 2); @@ -152,7 +158,7 @@ class ArgvInput extends Input * * @throws RuntimeException When too many arguments are given */ - private function parseArgument(string $token) + private function parseArgument(string $token): void { $c = \count($this->arguments); @@ -196,7 +202,7 @@ class ArgvInput extends Input * * @throws RuntimeException When option given doesn't exist */ - private function addShortOption(string $shortcut, mixed $value) + private function addShortOption(string $shortcut, mixed $value): void { if (!$this->definition->hasShortcut($shortcut)) { throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut)); @@ -210,7 +216,7 @@ class ArgvInput extends Input * * @throws RuntimeException When option given doesn't exist */ - private function addLongOption(string $name, mixed $value) + private function addLongOption(string $name, mixed $value): void { if (!$this->definition->hasOption($name)) { if (!$this->definition->hasNegation($name)) { diff --git a/vendor/symfony/console/Input/ArrayInput.php b/vendor/symfony/console/Input/ArrayInput.php index 02fb4e8e..355de61d 100644 --- a/vendor/symfony/console/Input/ArrayInput.php +++ b/vendor/symfony/console/Input/ArrayInput.php @@ -113,6 +113,9 @@ class ArrayInput extends Input return implode(' ', $params); } + /** + * @return void + */ protected function parse() { foreach ($this->parameters as $key => $value) { @@ -134,7 +137,7 @@ class ArrayInput extends Input * * @throws InvalidOptionException When option given doesn't exist */ - private function addShortOption(string $shortcut, mixed $value) + private function addShortOption(string $shortcut, mixed $value): void { if (!$this->definition->hasShortcut($shortcut)) { throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut)); @@ -149,7 +152,7 @@ class ArrayInput extends Input * @throws InvalidOptionException When option given doesn't exist * @throws InvalidOptionException When a required value is missing */ - private function addLongOption(string $name, mixed $value) + private function addLongOption(string $name, mixed $value): void { if (!$this->definition->hasOption($name)) { if (!$this->definition->hasNegation($name)) { @@ -182,7 +185,7 @@ class ArrayInput extends Input * * @throws InvalidArgumentException When argument given doesn't exist */ - private function addArgument(string|int $name, mixed $value) + private function addArgument(string|int $name, mixed $value): void { if (!$this->definition->hasArgument($name)) { throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); diff --git a/vendor/symfony/console/Input/Input.php b/vendor/symfony/console/Input/Input.php index 7b90713c..0f5617cd 100644 --- a/vendor/symfony/console/Input/Input.php +++ b/vendor/symfony/console/Input/Input.php @@ -43,6 +43,9 @@ abstract class Input implements InputInterface, StreamableInputInterface } } + /** + * @return void + */ public function bind(InputDefinition $definition) { $this->arguments = []; @@ -54,17 +57,20 @@ abstract class Input implements InputInterface, StreamableInputInterface /** * Processes command line arguments. + * + * @return void */ abstract protected function parse(); + /** + * @return void + */ 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(); - }); + $missingArguments = array_filter(array_keys($definition->getArguments()), fn ($argument) => !\array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired()); if (\count($missingArguments) > 0) { throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments))); @@ -76,6 +82,9 @@ abstract class Input implements InputInterface, StreamableInputInterface return $this->interactive; } + /** + * @return void + */ public function setInteractive(bool $interactive) { $this->interactive = $interactive; @@ -95,6 +104,9 @@ abstract class Input implements InputInterface, StreamableInputInterface return $this->arguments[$name] ?? $this->definition->getArgument($name)->getDefault(); } + /** + * @return void + */ public function setArgument(string $name, mixed $value) { if (!$this->definition->hasArgument($name)) { @@ -131,6 +143,9 @@ abstract class Input implements InputInterface, StreamableInputInterface return \array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); } + /** + * @return void + */ public function setOption(string $name, mixed $value) { if ($this->definition->hasNegation($name)) { @@ -157,11 +172,19 @@ abstract class Input implements InputInterface, StreamableInputInterface return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token); } + /** + * @param resource $stream + * + * @return void + */ public function setStream($stream) { $this->stream = $stream; } + /** + * @return resource + */ public function getStream() { return $this->stream; diff --git a/vendor/symfony/console/Input/InputArgument.php b/vendor/symfony/console/Input/InputArgument.php index 0e86e916..5cb15148 100644 --- a/vendor/symfony/console/Input/InputArgument.php +++ b/vendor/symfony/console/Input/InputArgument.php @@ -91,6 +91,8 @@ class InputArgument /** * Sets the default value. * + * @return void + * * @throws LogicException When incorrect default value is given */ public function setDefault(string|bool|int|float|array $default = null) diff --git a/vendor/symfony/console/Input/InputAwareInterface.php b/vendor/symfony/console/Input/InputAwareInterface.php index 5a288de5..0ad27b45 100644 --- a/vendor/symfony/console/Input/InputAwareInterface.php +++ b/vendor/symfony/console/Input/InputAwareInterface.php @@ -21,6 +21,8 @@ interface InputAwareInterface { /** * Sets the Console Input. + * + * @return void */ public function setInput(InputInterface $input); } diff --git a/vendor/symfony/console/Input/InputDefinition.php b/vendor/symfony/console/Input/InputDefinition.php index f4b14a1c..b7162d77 100644 --- a/vendor/symfony/console/Input/InputDefinition.php +++ b/vendor/symfony/console/Input/InputDefinition.php @@ -46,6 +46,8 @@ class InputDefinition /** * Sets the definition of the input. + * + * @return void */ public function setDefinition(array $definition) { @@ -67,6 +69,8 @@ class InputDefinition * Sets the InputArgument objects. * * @param InputArgument[] $arguments An array of InputArgument objects + * + * @return void */ public function setArguments(array $arguments = []) { @@ -81,6 +85,8 @@ class InputDefinition * Adds an array of InputArgument objects. * * @param InputArgument[] $arguments An array of InputArgument objects + * + * @return void */ public function addArguments(?array $arguments = []) { @@ -92,6 +98,8 @@ class InputDefinition } /** + * @return void + * * @throws LogicException When incorrect argument is given */ public function addArgument(InputArgument $argument) @@ -190,6 +198,8 @@ class InputDefinition * Sets the InputOption objects. * * @param InputOption[] $options An array of InputOption objects + * + * @return void */ public function setOptions(array $options = []) { @@ -203,6 +213,8 @@ class InputDefinition * Adds an array of InputOption objects. * * @param InputOption[] $options An array of InputOption objects + * + * @return void */ public function addOptions(array $options = []) { @@ -212,6 +224,8 @@ class InputDefinition } /** + * @return void + * * @throws LogicException When option given already exist */ public function addOption(InputOption $option) diff --git a/vendor/symfony/console/Input/InputInterface.php b/vendor/symfony/console/Input/InputInterface.php index 3af991a7..aaed5fd0 100644 --- a/vendor/symfony/console/Input/InputInterface.php +++ b/vendor/symfony/console/Input/InputInterface.php @@ -61,6 +61,8 @@ interface InputInterface /** * Binds the current Input instance with the given arguments and options. * + * @return void + * * @throws RuntimeException */ public function bind(InputDefinition $definition); @@ -68,6 +70,8 @@ interface InputInterface /** * Validates the input. * + * @return void + * * @throws RuntimeException When not enough arguments are given */ public function validate(); @@ -91,6 +95,8 @@ interface InputInterface /** * Sets an argument value by name. * + * @return void + * * @throws InvalidArgumentException When argument given doesn't exist */ public function setArgument(string $name, mixed $value); @@ -119,6 +125,8 @@ interface InputInterface /** * Sets an option value by name. * + * @return void + * * @throws InvalidArgumentException When option given doesn't exist */ public function setOption(string $name, mixed $value); @@ -135,6 +143,8 @@ interface InputInterface /** * Sets the input interactivity. + * + * @return void */ public function setInteractive(bool $interactive); } diff --git a/vendor/symfony/console/Input/InputOption.php b/vendor/symfony/console/Input/InputOption.php index 9a7032a0..fdf88dcc 100644 --- a/vendor/symfony/console/Input/InputOption.php +++ b/vendor/symfony/console/Input/InputOption.php @@ -178,6 +178,9 @@ class InputOption return self::VALUE_NEGATABLE === (self::VALUE_NEGATABLE & $this->mode); } + /** + * @return void + */ public function setDefault(string|bool|int|float|array $default = null) { if (1 > \func_num_args()) { diff --git a/vendor/symfony/console/Input/StreamableInputInterface.php b/vendor/symfony/console/Input/StreamableInputInterface.php index d7e462f2..4b95fcb1 100644 --- a/vendor/symfony/console/Input/StreamableInputInterface.php +++ b/vendor/symfony/console/Input/StreamableInputInterface.php @@ -25,6 +25,8 @@ interface StreamableInputInterface extends InputInterface * This is mainly useful for testing purpose. * * @param resource $stream The input stream + * + * @return void */ public function setStream($stream); diff --git a/vendor/symfony/console/Output/AnsiColorMode.php b/vendor/symfony/console/Output/AnsiColorMode.php index c6cc5c12..5f9f744f 100644 --- a/vendor/symfony/console/Output/AnsiColorMode.php +++ b/vendor/symfony/console/Output/AnsiColorMode.php @@ -26,7 +26,7 @@ enum AnsiColorMode case Ansi4; /* - * 8-bit Ansi colors (240 differents colors + 16 duplicate color codes, ensuring backward compatibility). + * 8-bit Ansi colors (240 different colors + 16 duplicate color codes, ensuring backward compatibility). * Output syntax is: "ESC[38;5;${foreGroundColorcode};48;5;${backGroundColorcode}m" * Should be compatible with most terminals. */ @@ -78,25 +78,7 @@ enum AnsiColorMode private function degradeHexColorToAnsi4(int $r, int $g, int $b): int { - if (0 === round($this->getSaturation($r, $g, $b) / 50)) { - return 0; - } - - return (int) ((round($b / 255) << 2) | (round($g / 255) << 1) | round($r / 255)); - } - - private function getSaturation(int $r, int $g, int $b): int - { - $r = $r / 255; - $g = $g / 255; - $b = $b / 255; - $v = max($r, $g, $b); - - if (0 === $diff = $v - min($r, $g, $b)) { - return 0; - } - - return (int) ((int) $diff * 100 / $v); + return round($b / 255) << 2 | (round($g / 255) << 1) | round($r / 255); } /** diff --git a/vendor/symfony/console/Output/BufferedOutput.php b/vendor/symfony/console/Output/BufferedOutput.php index 94d4e414..ef5099bf 100644 --- a/vendor/symfony/console/Output/BufferedOutput.php +++ b/vendor/symfony/console/Output/BufferedOutput.php @@ -29,6 +29,9 @@ class BufferedOutput extends Output return $content; } + /** + * @return void + */ protected function doWrite(string $message, bool $newline) { $this->buffer .= $message; diff --git a/vendor/symfony/console/Output/ConsoleOutput.php b/vendor/symfony/console/Output/ConsoleOutput.php index e3aa92c7..c1eb7cd1 100644 --- a/vendor/symfony/console/Output/ConsoleOutput.php +++ b/vendor/symfony/console/Output/ConsoleOutput.php @@ -64,18 +64,27 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface return new ConsoleSectionOutput($this->getStream(), $this->consoleSectionOutputs, $this->getVerbosity(), $this->isDecorated(), $this->getFormatter()); } + /** + * @return void + */ public function setDecorated(bool $decorated) { parent::setDecorated($decorated); $this->stderr->setDecorated($decorated); } + /** + * @return void + */ public function setFormatter(OutputFormatterInterface $formatter) { parent::setFormatter($formatter); $this->stderr->setFormatter($formatter); } + /** + * @return void + */ public function setVerbosity(int $level) { parent::setVerbosity($level); @@ -87,6 +96,9 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface return $this->stderr; } + /** + * @return void + */ public function setErrorOutput(OutputInterface $error) { $this->stderr = $error; diff --git a/vendor/symfony/console/Output/ConsoleOutputInterface.php b/vendor/symfony/console/Output/ConsoleOutputInterface.php index 6b4babc6..9c0049c8 100644 --- a/vendor/symfony/console/Output/ConsoleOutputInterface.php +++ b/vendor/symfony/console/Output/ConsoleOutputInterface.php @@ -24,6 +24,9 @@ interface ConsoleOutputInterface extends OutputInterface */ public function getErrorOutput(): OutputInterface; + /** + * @return void + */ public function setErrorOutput(OutputInterface $error); public function section(): ConsoleSectionOutput; diff --git a/vendor/symfony/console/Output/ConsoleSectionOutput.php b/vendor/symfony/console/Output/ConsoleSectionOutput.php index c813c811..3f3f1434 100644 --- a/vendor/symfony/console/Output/ConsoleSectionOutput.php +++ b/vendor/symfony/console/Output/ConsoleSectionOutput.php @@ -60,6 +60,8 @@ class ConsoleSectionOutput extends StreamOutput * Clears previous output for this section. * * @param int $lines Number of lines to clear. If null, then the entire output of this section is cleared + * + * @return void */ public function clear(int $lines = null) { @@ -81,6 +83,8 @@ class ConsoleSectionOutput extends StreamOutput /** * Overwrites the previous output with a new message. + * + * @return void */ public function overwrite(string|iterable $message) { @@ -153,12 +157,15 @@ class ConsoleSectionOutput extends StreamOutput /** * @internal */ - public function addNewLineOfInputSubmit() + public function addNewLineOfInputSubmit(): void { $this->content[] = \PHP_EOL; ++$this->lines; } + /** + * @return void + */ protected function doWrite(string $message, bool $newline) { if (!$this->isDecorated()) { diff --git a/vendor/symfony/console/Output/NullOutput.php b/vendor/symfony/console/Output/NullOutput.php index 4884cbad..f3aa15b1 100644 --- a/vendor/symfony/console/Output/NullOutput.php +++ b/vendor/symfony/console/Output/NullOutput.php @@ -26,6 +26,9 @@ class NullOutput implements OutputInterface { private NullOutputFormatter $formatter; + /** + * @return void + */ public function setFormatter(OutputFormatterInterface $formatter) { // do nothing @@ -37,6 +40,9 @@ class NullOutput implements OutputInterface return $this->formatter ??= new NullOutputFormatter(); } + /** + * @return void + */ public function setDecorated(bool $decorated) { // do nothing @@ -47,6 +53,9 @@ class NullOutput implements OutputInterface return false; } + /** + * @return void + */ public function setVerbosity(int $level) { // do nothing @@ -77,11 +86,17 @@ class NullOutput implements OutputInterface return false; } + /** + * @return void + */ public function writeln(string|iterable $messages, int $options = self::OUTPUT_NORMAL) { // do nothing } + /** + * @return void + */ public function write(string|iterable $messages, bool $newline = false, int $options = self::OUTPUT_NORMAL) { // do nothing diff --git a/vendor/symfony/console/Output/Output.php b/vendor/symfony/console/Output/Output.php index 4cb71acb..3a06311a 100644 --- a/vendor/symfony/console/Output/Output.php +++ b/vendor/symfony/console/Output/Output.php @@ -44,6 +44,9 @@ abstract class Output implements OutputInterface $this->formatter->setDecorated($decorated); } + /** + * @return void + */ public function setFormatter(OutputFormatterInterface $formatter) { $this->formatter = $formatter; @@ -54,6 +57,9 @@ abstract class Output implements OutputInterface return $this->formatter; } + /** + * @return void + */ public function setDecorated(bool $decorated) { $this->formatter->setDecorated($decorated); @@ -64,6 +70,9 @@ abstract class Output implements OutputInterface return $this->formatter->isDecorated(); } + /** + * @return void + */ public function setVerbosity(int $level) { $this->verbosity = $level; @@ -94,11 +103,17 @@ abstract class Output implements OutputInterface return self::VERBOSITY_DEBUG <= $this->verbosity; } + /** + * @return void + */ public function writeln(string|iterable $messages, int $options = self::OUTPUT_NORMAL) { $this->write($messages, true, $options); } + /** + * @return void + */ public function write(string|iterable $messages, bool $newline = false, int $options = self::OUTPUT_NORMAL) { if (!is_iterable($messages)) { @@ -133,6 +148,8 @@ abstract class Output implements OutputInterface /** * Writes a message to the output. + * + * @return void */ abstract protected function doWrite(string $message, bool $newline); } diff --git a/vendor/symfony/console/Output/OutputInterface.php b/vendor/symfony/console/Output/OutputInterface.php index bc927c51..fb155772 100644 --- a/vendor/symfony/console/Output/OutputInterface.php +++ b/vendor/symfony/console/Output/OutputInterface.php @@ -36,6 +36,8 @@ interface OutputInterface * @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 + * + * @return void */ public function write(string|iterable $messages, bool $newline = false, int $options = 0); @@ -44,11 +46,15 @@ interface OutputInterface * * @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 + * + * @return void */ public function writeln(string|iterable $messages, int $options = 0); /** * Sets the verbosity of the output. + * + * @return void */ public function setVerbosity(int $level); @@ -79,6 +85,8 @@ interface OutputInterface /** * Sets the decorated flag. + * + * @return void */ public function setDecorated(bool $decorated); @@ -87,6 +95,9 @@ interface OutputInterface */ public function isDecorated(): bool; + /** + * @return void + */ public function setFormatter(OutputFormatterInterface $formatter); /** diff --git a/vendor/symfony/console/Output/StreamOutput.php b/vendor/symfony/console/Output/StreamOutput.php index 9ec524e4..155066ea 100644 --- a/vendor/symfony/console/Output/StreamOutput.php +++ b/vendor/symfony/console/Output/StreamOutput.php @@ -62,6 +62,9 @@ class StreamOutput extends Output return $this->stream; } + /** + * @return void + */ protected function doWrite(string $message, bool $newline) { if ($newline) { diff --git a/vendor/symfony/console/Output/TrimmedBufferOutput.php b/vendor/symfony/console/Output/TrimmedBufferOutput.php index 1ca5a13e..b00445ec 100644 --- a/vendor/symfony/console/Output/TrimmedBufferOutput.php +++ b/vendor/symfony/console/Output/TrimmedBufferOutput.php @@ -45,6 +45,9 @@ class TrimmedBufferOutput extends Output return $content; } + /** + * @return void + */ protected function doWrite(string $message, bool $newline) { $this->buffer .= $message; diff --git a/vendor/symfony/console/Question/Question.php b/vendor/symfony/console/Question/Question.php index b06db945..26896bb5 100644 --- a/vendor/symfony/console/Question/Question.php +++ b/vendor/symfony/console/Question/Question.php @@ -146,12 +146,11 @@ class Question if (\is_array($values)) { $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values); - $callback = static function () use ($values) { - return $values; - }; + $callback = static fn () => $values; } elseif ($values instanceof \Traversable) { - $valueCache = null; - $callback = static function () use ($values, &$valueCache) { + $callback = static function () use ($values) { + static $valueCache; + return $valueCache ??= iterator_to_array($values, false); }; } else { @@ -267,6 +266,9 @@ class Question return $this->normalizer; } + /** + * @return bool + */ protected function isAssoc(array $array) { return (bool) \count(array_filter(array_keys($array), 'is_string')); diff --git a/vendor/symfony/console/README.md b/vendor/symfony/console/README.md index c89b4a1a..bfd48810 100644 --- a/vendor/symfony/console/README.md +++ b/vendor/symfony/console/README.md @@ -4,6 +4,18 @@ Console Component The Console component eases the creation of beautiful and testable command line interfaces. +Sponsor +------- + +The Console component for Symfony 6.3 is [backed][1] by [Les-Tilleuls.coop][2]. + +Les-Tilleuls.coop is a team of 70+ Symfony experts who can help you design, develop and +fix your projects. They provide a wide range of professional services including development, +consulting, coaching, training and audits. They also are highly skilled in JS, Go and DevOps. +They are a worker cooperative! + +Help Symfony by [sponsoring][3] its development! + Resources --------- @@ -18,3 +30,7 @@ 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. + +[1]: https://symfony.com/backers +[2]: https://les-tilleuls.coop +[3]: https://symfony.com/sponsor diff --git a/vendor/symfony/console/Resources/completion.bash b/vendor/symfony/console/Resources/completion.bash index ad69eab0..0d76eacc 100644 --- a/vendor/symfony/console/Resources/completion.bash +++ b/vendor/symfony/console/Resources/completion.bash @@ -6,6 +6,16 @@ # https://symfony.com/doc/current/contributing/code/license.html _sf_{{ COMMAND_NAME }}() { + + # Use the default completion for shell redirect operators. + for w in '>' '>>' '&>' '<'; do + if [[ $w = "${COMP_WORDS[COMP_CWORD-1]}" ]]; then + compopt -o filenames + COMPREPLY=($(compgen -f -- "${COMP_WORDS[COMP_CWORD]}")) + return 0 + fi + done + # Use newline as only separator to allow space in completion values IFS=$'\n' local sf_cmd="${COMP_WORDS[0]}" diff --git a/vendor/symfony/console/Style/OutputStyle.php b/vendor/symfony/console/Style/OutputStyle.php index b694bb53..ddfa8dec 100644 --- a/vendor/symfony/console/Style/OutputStyle.php +++ b/vendor/symfony/console/Style/OutputStyle.php @@ -30,6 +30,9 @@ abstract class OutputStyle implements OutputInterface, StyleInterface $this->output = $output; } + /** + * @return void + */ public function newLine(int $count = 1) { $this->output->write(str_repeat(\PHP_EOL, $count)); @@ -40,16 +43,25 @@ abstract class OutputStyle implements OutputInterface, StyleInterface return new ProgressBar($this->output, $max); } + /** + * @return void + */ public function write(string|iterable $messages, bool $newline = false, int $type = self::OUTPUT_NORMAL) { $this->output->write($messages, $newline, $type); } + /** + * @return void + */ public function writeln(string|iterable $messages, int $type = self::OUTPUT_NORMAL) { $this->output->writeln($messages, $type); } + /** + * @return void + */ public function setVerbosity(int $level) { $this->output->setVerbosity($level); @@ -60,6 +72,9 @@ abstract class OutputStyle implements OutputInterface, StyleInterface return $this->output->getVerbosity(); } + /** + * @return void + */ public function setDecorated(bool $decorated) { $this->output->setDecorated($decorated); @@ -70,6 +85,9 @@ abstract class OutputStyle implements OutputInterface, StyleInterface return $this->output->isDecorated(); } + /** + * @return void + */ public function setFormatter(OutputFormatterInterface $formatter) { $this->output->setFormatter($formatter); @@ -100,6 +118,9 @@ abstract class OutputStyle implements OutputInterface, StyleInterface return $this->output->isDebug(); } + /** + * @return OutputInterface + */ protected function getErrorOutput() { if (!$this->output instanceof ConsoleOutputInterface) { diff --git a/vendor/symfony/console/Style/StyleInterface.php b/vendor/symfony/console/Style/StyleInterface.php index 0bb12339..e25a65bd 100644 --- a/vendor/symfony/console/Style/StyleInterface.php +++ b/vendor/symfony/console/Style/StyleInterface.php @@ -20,51 +20,71 @@ interface StyleInterface { /** * Formats a command title. + * + * @return void */ public function title(string $message); /** * Formats a section title. + * + * @return void */ public function section(string $message); /** * Formats a list. + * + * @return void */ public function listing(array $elements); /** * Formats informational text. + * + * @return void */ public function text(string|array $message); /** * Formats a success result bar. + * + * @return void */ public function success(string|array $message); /** * Formats an error result bar. + * + * @return void */ public function error(string|array $message); /** * Formats an warning result bar. + * + * @return void */ public function warning(string|array $message); /** * Formats a note admonition. + * + * @return void */ public function note(string|array $message); /** * Formats a caution admonition. + * + * @return void */ public function caution(string|array $message); /** * Formats a table. + * + * @return void */ public function table(array $headers, array $rows); @@ -90,21 +110,29 @@ interface StyleInterface /** * Add newline(s). + * + * @return void */ public function newLine(int $count = 1); /** * Starts the progress output. + * + * @return void */ public function progressStart(int $max = 0); /** * Advances the progress output X steps. + * + * @return void */ public function progressAdvance(int $step = 1); /** * Finishes the progress output. + * + * @return void */ public function progressFinish(); } diff --git a/vendor/symfony/console/Style/SymfonyStyle.php b/vendor/symfony/console/Style/SymfonyStyle.php index 8fd6f849..cecce6c0 100644 --- a/vendor/symfony/console/Style/SymfonyStyle.php +++ b/vendor/symfony/console/Style/SymfonyStyle.php @@ -60,6 +60,8 @@ class SymfonyStyle extends OutputStyle /** * Formats a message as a block of text. + * + * @return void */ public function block(string|array $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = true) { @@ -70,6 +72,9 @@ class SymfonyStyle extends OutputStyle $this->newLine(); } + /** + * @return void + */ public function title(string $message) { $this->autoPrependBlock(); @@ -80,6 +85,9 @@ class SymfonyStyle extends OutputStyle $this->newLine(); } + /** + * @return void + */ public function section(string $message) { $this->autoPrependBlock(); @@ -90,17 +98,21 @@ class SymfonyStyle extends OutputStyle $this->newLine(); } + /** + * @return void + */ public function listing(array $elements) { $this->autoPrependText(); - $elements = array_map(function ($element) { - return sprintf(' * %s', $element); - }, $elements); + $elements = array_map(fn ($element) => sprintf(' * %s', $element), $elements); $this->writeln($elements); $this->newLine(); } + /** + * @return void + */ public function text(string|array $message) { $this->autoPrependText(); @@ -113,27 +125,41 @@ class SymfonyStyle extends OutputStyle /** * Formats a command comment. + * + * @return void */ public function comment(string|array $message) { $this->block($message, null, null, ' // ', false, false); } + /** + * @return void + */ public function success(string|array $message) { $this->block($message, 'OK', 'fg=black;bg=green', ' ', true); } + /** + * @return void + */ public function error(string|array $message) { $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true); } + /** + * @return void + */ public function warning(string|array $message) { $this->block($message, 'WARNING', 'fg=black;bg=yellow', ' ', true); } + /** + * @return void + */ public function note(string|array $message) { $this->block($message, 'NOTE', 'fg=yellow', ' ! '); @@ -141,17 +167,25 @@ class SymfonyStyle extends OutputStyle /** * Formats an info message. + * + * @return void */ public function info(string|array $message) { $this->block($message, 'INFO', 'fg=green', ' ', true); } + /** + * @return void + */ public function caution(string|array $message) { $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true); } + /** + * @return void + */ public function table(array $headers, array $rows) { $this->createTable() @@ -165,6 +199,8 @@ class SymfonyStyle extends OutputStyle /** * Formats a horizontal table. + * + * @return void */ public function horizontalTable(array $headers, array $rows) { @@ -185,6 +221,8 @@ class SymfonyStyle extends OutputStyle * * 'A title' * * ['key' => 'value'] * * new TableSeparator() + * + * @return void */ public function definitionList(string|array|TableSeparator ...$list) { @@ -247,17 +285,26 @@ class SymfonyStyle extends OutputStyle return $this->askQuestion($questionChoice); } + /** + * @return void + */ public function progressStart(int $max = 0) { $this->progressBar = $this->createProgressBar($max); $this->progressBar->start(); } + /** + * @return void + */ public function progressAdvance(int $step = 1) { $this->getProgressBar()->advance($step); } + /** + * @return void + */ public function progressFinish() { $this->getProgressBar()->finish(); @@ -311,6 +358,9 @@ class SymfonyStyle extends OutputStyle return $answer; } + /** + * @return void + */ public function writeln(string|iterable $messages, int $type = self::OUTPUT_NORMAL) { if (!is_iterable($messages)) { @@ -323,6 +373,9 @@ class SymfonyStyle extends OutputStyle } } + /** + * @return void + */ public function write(string|iterable $messages, bool $newline = false, int $type = self::OUTPUT_NORMAL) { if (!is_iterable($messages)) { @@ -335,6 +388,9 @@ class SymfonyStyle extends OutputStyle } } + /** + * @return void + */ public function newLine(int $count = 1) { parent::newLine($count); @@ -381,7 +437,7 @@ class SymfonyStyle extends OutputStyle { $fetched = $this->bufferedOutput->fetch(); // Prepend new line if last char isn't EOL: - if (!str_ends_with($fetched, "\n")) { + if ($fetched && !str_ends_with($fetched, "\n")) { $this->newLine(); } } diff --git a/vendor/symfony/console/Terminal.php b/vendor/symfony/console/Terminal.php index 855f4114..3eda0376 100644 --- a/vendor/symfony/console/Terminal.php +++ b/vendor/symfony/console/Terminal.php @@ -131,7 +131,7 @@ class Terminal return self::$stty = (bool) shell_exec('stty 2> '.('\\' === \DIRECTORY_SEPARATOR ? 'NUL' : '/dev/null')); } - private static function initDimensions() + private static function initDimensions(): void { if ('\\' === \DIRECTORY_SEPARATOR) { $ansicon = getenv('ANSICON'); @@ -165,7 +165,7 @@ class Terminal /** * Initializes dimensions using the output of an stty columns line. */ - private static function initDimensionsUsingStty() + private static function initDimensionsUsingStty(): void { if ($sttyString = self::getSttyColumns()) { if (preg_match('/rows.(\d+);.columns.(\d+);/is', $sttyString, $matches)) { diff --git a/vendor/symfony/console/Tester/TesterTrait.php b/vendor/symfony/console/Tester/TesterTrait.php index 9670a496..497b8c8c 100644 --- a/vendor/symfony/console/Tester/TesterTrait.php +++ b/vendor/symfony/console/Tester/TesterTrait.php @@ -128,7 +128,7 @@ trait TesterTrait * * verbosity: Sets the output verbosity flag * * capture_stderr_separately: Make output of stdOut and stdErr separately available */ - private function initOutput(array $options) + private function initOutput(array $options): void { $this->captureStreamsIndependently = \array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately']; if (!$this->captureStreamsIndependently) { diff --git a/vendor/symfony/console/composer.json b/vendor/symfony/console/composer.json index 6cc6166d..c3442129 100644 --- a/vendor/symfony/console/composer.json +++ b/vendor/symfony/console/composer.json @@ -17,9 +17,9 @@ ], "require": { "php": ">=8.1", - "symfony/deprecation-contracts": "^2.1|^3", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2|^3", + "symfony/service-contracts": "^2.5|^3", "symfony/string": "^5.4|^6.0" }, "require-dev": { @@ -34,12 +34,6 @@ "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, - "suggest": { - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "", - "psr/log": "For using the console logger" - }, "conflict": { "symfony/dependency-injection": "<5.4", "symfony/dotenv": "<5.4", diff --git a/vendor/symfony/deprecation-contracts/composer.json b/vendor/symfony/deprecation-contracts/composer.json index 774200fd..c6d02d87 100644 --- a/vendor/symfony/deprecation-contracts/composer.json +++ b/vendor/symfony/deprecation-contracts/composer.json @@ -25,7 +25,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", diff --git a/vendor/symfony/filesystem/Filesystem.php b/vendor/symfony/filesystem/Filesystem.php index 3b3cf7a1..a379ce18 100644 --- a/vendor/symfony/filesystem/Filesystem.php +++ b/vendor/symfony/filesystem/Filesystem.php @@ -31,6 +31,8 @@ class Filesystem * If the target file is newer, it is overwritten only when the * $overwriteNewerFiles option is set to true. * + * @return void + * * @throws FileNotFoundException When originFile doesn't exist * @throws IOException When copy fails */ @@ -82,6 +84,8 @@ class Filesystem /** * Creates a directory recursively. * + * @return void + * * @throws IOException On any directory creation failure */ public function mkdir(string|iterable $dirs, int $mode = 0777) @@ -123,6 +127,8 @@ class Filesystem * @param int|null $time The touch time as a Unix timestamp, if not supplied the current system time is used * @param int|null $atime The access time as a Unix timestamp, if not supplied the current system time is used * + * @return void + * * @throws IOException When touch fails */ public function touch(string|iterable $files, int $time = null, int $atime = null) @@ -137,6 +143,8 @@ class Filesystem /** * Removes files or directories. * + * @return void + * * @throws IOException When removal fails */ public function remove(string|iterable $files) @@ -203,12 +211,14 @@ class Filesystem * @param int $umask The mode mask (octal) * @param bool $recursive Whether change the mod recursively or not * + * @return void + * * @throws IOException When the change fails */ public function chmod(string|iterable $files, int $mode, int $umask = 0000, bool $recursive = false) { foreach ($this->toIterable($files) as $file) { - if (\is_int($mode) && !self::box('chmod', $file, $mode & ~$umask)) { + if (!self::box('chmod', $file, $mode & ~$umask)) { throw new IOException(sprintf('Failed to chmod file "%s": ', $file).self::$lastError, 0, null, $file); } if ($recursive && is_dir($file) && !is_link($file)) { @@ -223,6 +233,8 @@ class Filesystem * @param string|int $user A user name or number * @param bool $recursive Whether change the owner recursively or not * + * @return void + * * @throws IOException When the change fails */ public function chown(string|iterable $files, string|int $user, bool $recursive = false) @@ -249,6 +261,8 @@ class Filesystem * @param string|int $group A group name or number * @param bool $recursive Whether change the group recursively or not * + * @return void + * * @throws IOException When the change fails */ public function chgrp(string|iterable $files, string|int $group, bool $recursive = false) @@ -272,6 +286,8 @@ class Filesystem /** * Renames a file or a directory. * + * @return void + * * @throws IOException When target file or directory already exists * @throws IOException When origin cannot be renamed */ @@ -313,6 +329,8 @@ class Filesystem /** * Creates a symbolic link or copy a directory. * + * @return void + * * @throws IOException When symlink fails */ public function symlink(string $originDir, string $targetDir, bool $copyOnWindows = false) @@ -349,6 +367,8 @@ class Filesystem * * @param string|string[] $targetFiles The target file(s) * + * @return void + * * @throws FileNotFoundException When original file is missing or not a file * @throws IOException When link fails, including if link already exists */ @@ -381,7 +401,7 @@ class Filesystem /** * @param string $linkType Name of the link type, typically 'symbolic' or 'hard' */ - private function linkException(string $origin, string $target, string $linkType) + private function linkException(string $origin, string $target, string $linkType): never { if (self::$lastError) { if ('\\' === \DIRECTORY_SEPARATOR && str_contains(self::$lastError, 'error code(1314)')) { @@ -438,11 +458,9 @@ class Filesystem $startPath = str_replace('\\', '/', $startPath); } - $splitDriveLetter = function ($path) { - return (\strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) - ? [substr($path, 2), strtoupper($path[0])] - : [$path, null]; - }; + $splitDriveLetter = fn ($path) => (\strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) + ? [substr($path, 2), strtoupper($path[0])] + : [$path, null]; $splitPath = function ($path) { $result = []; @@ -508,6 +526,8 @@ class Filesystem * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink(), defaults to false) * - $options['delete'] Whether to delete files that are not in the source directory (defaults to false) * + * @return void + * * @throws IOException When file type is unknown */ public function mirror(string $originDir, string $targetDir, \Traversable $iterator = null, array $options = []) @@ -632,6 +652,8 @@ class Filesystem * * @param string|resource $content The data to write into the file * + * @return void + * * @throws IOException if the file cannot be written to */ public function dumpFile(string $filename, $content) @@ -642,6 +664,12 @@ class Filesystem $dir = \dirname($filename); + if (is_link($filename) && $linkTarget = $this->readlink($filename)) { + $this->dumpFile(Path::makeAbsolute($linkTarget, $dir), $content); + + return; + } + if (!is_dir($dir)) { $this->mkdir($dir); } @@ -671,6 +699,8 @@ class Filesystem * @param string|resource $content The content to append * @param bool $lock Whether the file should be locked when writing to it * + * @return void + * * @throws IOException If the file is not writable */ public function appendToFile(string $filename, $content/* , bool $lock = false */) @@ -730,7 +760,7 @@ class Filesystem /** * @internal */ - public static function handleError(int $type, string $msg) + public static function handleError(int $type, string $msg): void { self::$lastError = $msg; } diff --git a/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php b/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php index 88f6a068..07d12b4a 100644 --- a/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php +++ b/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php @@ -11,82 +11,13 @@ namespace Symfony\Contracts\Service\Test; -use PHPUnit\Framework\TestCase; -use Psr\Container\ContainerInterface; -use Symfony\Contracts\Service\ServiceLocatorTrait; +class_alias(ServiceLocatorTestCase::class, ServiceLocatorTest::class); -abstract class ServiceLocatorTest extends TestCase -{ - protected function getServiceLocator(array $factories): ContainerInterface +if (false) { + /** + * @deprecated since PHPUnit 9.6 + */ + class ServiceLocatorTest { - return new class($factories) implements ContainerInterface { - use ServiceLocatorTrait; - }; - } - - public function testHas() - { - $locator = $this->getServiceLocator([ - 'foo' => function () { return 'bar'; }, - 'bar' => function () { return 'baz'; }, - function () { return 'dummy'; }, - ]); - - $this->assertTrue($locator->has('foo')); - $this->assertTrue($locator->has('bar')); - $this->assertFalse($locator->has('dummy')); - } - - public function testGet() - { - $locator = $this->getServiceLocator([ - 'foo' => function () { return 'bar'; }, - 'bar' => function () { return 'baz'; }, - ]); - - $this->assertSame('bar', $locator->get('foo')); - $this->assertSame('baz', $locator->get('bar')); - } - - public function testGetDoesNotMemoize() - { - $i = 0; - $locator = $this->getServiceLocator([ - 'foo' => function () use (&$i) { - ++$i; - - return 'bar'; - }, - ]); - - $this->assertSame('bar', $locator->get('foo')); - $this->assertSame('bar', $locator->get('foo')); - $this->assertSame(2, $i); - } - - public function testThrowsOnUndefinedInternalService() - { - if (!$this->getExpectedException()) { - $this->expectException(\Psr\Container\NotFoundExceptionInterface::class); - $this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.'); - } - $locator = $this->getServiceLocator([ - 'foo' => function () use (&$locator) { return $locator->get('bar'); }, - ]); - - $locator->get('foo'); - } - - public function testThrowsOnCircularReference() - { - $this->expectException(\Psr\Container\ContainerExceptionInterface::class); - $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".'); - $locator = $this->getServiceLocator([ - 'foo' => function () use (&$locator) { return $locator->get('bar'); }, - 'bar' => function () use (&$locator) { return $locator->get('baz'); }, - 'baz' => function () use (&$locator) { return $locator->get('bar'); }, - ]); - - $locator->get('foo'); } } diff --git a/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php b/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php new file mode 100644 index 00000000..a0f20a6a --- /dev/null +++ b/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service\Test; + +use PHPUnit\Framework\TestCase; +use Psr\Container\ContainerInterface; +use Symfony\Contracts\Service\ServiceLocatorTrait; + +abstract class ServiceLocatorTestCase extends TestCase +{ + protected function getServiceLocator(array $factories): ContainerInterface + { + return new class($factories) implements ContainerInterface { + use ServiceLocatorTrait; + }; + } + + public function testHas() + { + $locator = $this->getServiceLocator([ + 'foo' => function () { return 'bar'; }, + 'bar' => function () { return 'baz'; }, + function () { return 'dummy'; }, + ]); + + $this->assertTrue($locator->has('foo')); + $this->assertTrue($locator->has('bar')); + $this->assertFalse($locator->has('dummy')); + } + + public function testGet() + { + $locator = $this->getServiceLocator([ + 'foo' => function () { return 'bar'; }, + 'bar' => function () { return 'baz'; }, + ]); + + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame('baz', $locator->get('bar')); + } + + public function testGetDoesNotMemoize() + { + $i = 0; + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$i) { + ++$i; + + return 'bar'; + }, + ]); + + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame(2, $i); + } + + public function testThrowsOnUndefinedInternalService() + { + if (!$this->getExpectedException()) { + $this->expectException(\Psr\Container\NotFoundExceptionInterface::class); + $this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.'); + } + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$locator) { return $locator->get('bar'); }, + ]); + + $locator->get('foo'); + } + + public function testThrowsOnCircularReference() + { + $this->expectException(\Psr\Container\ContainerExceptionInterface::class); + $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".'); + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$locator) { return $locator->get('bar'); }, + 'bar' => function () use (&$locator) { return $locator->get('baz'); }, + 'baz' => function () use (&$locator) { return $locator->get('bar'); }, + ]); + + $locator->get('foo'); + } +} diff --git a/vendor/symfony/service-contracts/composer.json b/vendor/symfony/service-contracts/composer.json index 36b0d95e..a64188b5 100644 --- a/vendor/symfony/service-contracts/composer.json +++ b/vendor/symfony/service-contracts/composer.json @@ -22,9 +22,6 @@ "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" }, "exclude-from-classmap": [ @@ -34,7 +31,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", diff --git a/vendor/symfony/string/AbstractUnicodeString.php b/vendor/symfony/string/AbstractUnicodeString.php index 2a2bed71..d19a61a9 100644 --- a/vendor/symfony/string/AbstractUnicodeString.php +++ b/vendor/symfony/string/AbstractUnicodeString.php @@ -40,10 +40,6 @@ abstract class AbstractUnicodeString extends AbstractString private const FOLD_FROM = ['İ', 'µ', 'ſ', "\xCD\x85", 'ς', 'ϐ', 'ϑ', 'ϕ', 'ϖ', 'ϰ', 'ϱ', 'ϵ', 'ẛ', "\xE1\xBE\xBE", 'ß', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'և', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ẞ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'ᾐ', 'ᾑ', 'ᾒ', 'ᾓ', 'ᾔ', 'ᾕ', 'ᾖ', 'ᾗ', 'ᾘ', 'ᾙ', 'ᾚ', 'ᾛ', 'ᾜ', 'ᾝ', 'ᾞ', 'ᾟ', 'ᾠ', 'ᾡ', 'ᾢ', 'ᾣ', 'ᾤ', 'ᾥ', 'ᾦ', 'ᾧ', 'ᾨ', 'ᾩ', 'ᾪ', 'ᾫ', 'ᾬ', 'ᾭ', 'ᾮ', 'ᾯ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'ᾼ', 'ῂ', 'ῃ', 'ῄ', 'ῆ', 'ῇ', 'ῌ', 'ῒ', 'ῖ', 'ῗ', 'ῢ', 'ῤ', 'ῦ', 'ῧ', 'ῲ', 'ῳ', 'ῴ', 'ῶ', 'ῷ', 'ῼ', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ']; private const FOLD_TO = ['i̇', 'μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', 'ṡ', 'ι', 'ss', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'եւ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'aʾ', 'ss', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὰι', 'αι', 'άι', 'ᾶ', 'ᾶι', 'αι', 'ὴι', 'ηι', 'ήι', 'ῆ', 'ῆι', 'ηι', 'ῒ', 'ῖ', 'ῗ', 'ῢ', 'ῤ', 'ῦ', 'ῧ', 'ὼι', 'ωι', 'ώι', 'ῶ', 'ῶι', 'ωι', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'st', 'st', 'մն', 'մե', 'մի', 'վն', 'մխ']; - // the subset of upper case mappings that map one code point to many code points - private const UPPER_FROM = ['ß', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'և', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ', 'ʼn', 'ΐ', 'ΰ', 'ǰ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾶ', 'ῆ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ῶ']; - private const UPPER_TO = ['SS', 'FF', 'FI', 'FL', 'FFI', 'FFL', 'ST', 'ST', 'ԵՒ', 'ՄՆ', 'ՄԵ', 'ՄԻ', 'ՎՆ', 'ՄԽ', 'ʼN', 'Ϊ́', 'Ϋ́', 'J̌', 'H̱', 'T̈', 'W̊', 'Y̊', 'Aʾ', 'Υ̓', 'Υ̓̀', 'Υ̓́', 'Υ̓͂', 'Α͂', 'Η͂', 'Ϊ̀', 'Ϊ́', 'Ι͂', 'Ϊ͂', 'Ϋ̀', 'Ϋ́', 'Ρ̓', 'Υ͂', 'Ϋ͂', 'Ω͂']; - // the subset of https://github.com/unicode-org/cldr/blob/master/common/transforms/Latin-ASCII.xml that is not in NFKD private const TRANSLIT_FROM = ['Æ', 'Ð', 'Ø', 'Þ', 'ß', 'æ', 'ð', 'ø', 'þ', 'Đ', 'đ', 'Ħ', 'ħ', 'ı', 'ĸ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'ʼn', 'Ŋ', 'ŋ', 'Œ', 'œ', 'Ŧ', 'ŧ', 'ƀ', 'Ɓ', 'Ƃ', 'ƃ', 'Ƈ', 'ƈ', 'Ɖ', 'Ɗ', 'Ƌ', 'ƌ', 'Ɛ', 'Ƒ', 'ƒ', 'Ɠ', 'ƕ', 'Ɩ', 'Ɨ', 'Ƙ', 'ƙ', 'ƚ', 'Ɲ', 'ƞ', 'Ƣ', 'ƣ', 'Ƥ', 'ƥ', 'ƫ', 'Ƭ', 'ƭ', 'Ʈ', 'Ʋ', 'Ƴ', 'ƴ', 'Ƶ', 'ƶ', 'DŽ', 'Dž', 'dž', 'Ǥ', 'ǥ', 'ȡ', 'Ȥ', 'ȥ', 'ȴ', 'ȵ', 'ȶ', 'ȷ', 'ȸ', 'ȹ', 'Ⱥ', 'Ȼ', 'ȼ', 'Ƚ', 'Ⱦ', 'ȿ', 'ɀ', 'Ƀ', 'Ʉ', 'Ɇ', 'ɇ', 'Ɉ', 'ɉ', 'Ɍ', 'ɍ', 'Ɏ', 'ɏ', 'ɓ', 'ɕ', 'ɖ', 'ɗ', 'ɛ', 'ɟ', 'ɠ', 'ɡ', 'ɢ', 'ɦ', 'ɧ', 'ɨ', 'ɪ', 'ɫ', 'ɬ', 'ɭ', 'ɱ', 'ɲ', 'ɳ', 'ɴ', 'ɶ', 'ɼ', 'ɽ', 'ɾ', 'ʀ', 'ʂ', 'ʈ', 'ʉ', 'ʋ', 'ʏ', 'ʐ', 'ʑ', 'ʙ', 'ʛ', 'ʜ', 'ʝ', 'ʟ', 'ʠ', 'ʣ', 'ʥ', 'ʦ', 'ʪ', 'ʫ', 'ᴀ', 'ᴁ', 'ᴃ', 'ᴄ', 'ᴅ', 'ᴆ', 'ᴇ', 'ᴊ', 'ᴋ', 'ᴌ', 'ᴍ', 'ᴏ', 'ᴘ', 'ᴛ', 'ᴜ', 'ᴠ', 'ᴡ', 'ᴢ', 'ᵫ', 'ᵬ', 'ᵭ', 'ᵮ', 'ᵯ', 'ᵰ', 'ᵱ', 'ᵲ', 'ᵳ', 'ᵴ', 'ᵵ', 'ᵶ', 'ᵺ', 'ᵻ', 'ᵽ', 'ᵾ', 'ᶀ', 'ᶁ', 'ᶂ', 'ᶃ', 'ᶄ', 'ᶅ', 'ᶆ', 'ᶇ', 'ᶈ', 'ᶉ', 'ᶊ', 'ᶌ', 'ᶍ', 'ᶎ', 'ᶏ', 'ᶑ', 'ᶒ', 'ᶓ', 'ᶖ', 'ᶙ', 'ẚ', 'ẜ', 'ẝ', 'ẞ', 'Ỻ', 'ỻ', 'Ỽ', 'ỽ', 'Ỿ', 'ỿ', '©', '®', '₠', '₢', '₣', '₤', '₧', '₺', '₹', 'ℌ', '℞', '㎧', '㎮', '㏆', '㏗', '㏞', '㏟', '¼', '½', '¾', '⅓', '⅔', '⅕', '⅖', '⅗', '⅘', '⅙', '⅚', '⅛', '⅜', '⅝', '⅞', '⅟', '〇', '‘', '’', '‚', '‛', '“', '”', '„', '‟', '′', '″', '〝', '〞', '«', '»', '‹', '›', '‐', '‑', '‒', '–', '—', '―', '︱', '︲', '﹘', '‖', '⁄', '⁅', '⁆', '⁎', '、', '。', '〈', '〉', '《', '》', '〔', '〕', '〘', '〙', '〚', '〛', '︑', '︒', '︹', '︺', '︽', '︾', '︿', '﹀', '﹑', '﹝', '﹞', '⦅', '⦆', '。', '、', '×', '÷', '−', '∕', '∖', '∣', '∥', '≪', '≫', '⦅', '⦆']; private const TRANSLIT_TO = ['AE', 'D', 'O', 'TH', 'ss', 'ae', 'd', 'o', 'th', 'D', 'd', 'H', 'h', 'i', 'q', 'L', 'l', 'L', 'l', '\'n', 'N', 'n', 'OE', 'oe', 'T', 't', 'b', 'B', 'B', 'b', 'C', 'c', 'D', 'D', 'D', 'd', 'E', 'F', 'f', 'G', 'hv', 'I', 'I', 'K', 'k', 'l', 'N', 'n', 'OI', 'oi', 'P', 'p', 't', 'T', 't', 'T', 'V', 'Y', 'y', 'Z', 'z', 'DZ', 'Dz', 'dz', 'G', 'g', 'd', 'Z', 'z', 'l', 'n', 't', 'j', 'db', 'qp', 'A', 'C', 'c', 'L', 'T', 's', 'z', 'B', 'U', 'E', 'e', 'J', 'j', 'R', 'r', 'Y', 'y', 'b', 'c', 'd', 'd', 'e', 'j', 'g', 'g', 'G', 'h', 'h', 'i', 'I', 'l', 'l', 'l', 'm', 'n', 'n', 'N', 'OE', 'r', 'r', 'r', 'R', 's', 't', 'u', 'v', 'Y', 'z', 'z', 'B', 'G', 'H', 'j', 'L', 'q', 'dz', 'dz', 'ts', 'ls', 'lz', 'A', 'AE', 'B', 'C', 'D', 'D', 'E', 'J', 'K', 'L', 'M', 'O', 'P', 'T', 'U', 'V', 'W', 'Z', 'ue', 'b', 'd', 'f', 'm', 'n', 'p', 'r', 'r', 's', 't', 'z', 'th', 'I', 'p', 'U', 'b', 'd', 'f', 'g', 'k', 'l', 'm', 'n', 'p', 'r', 's', 'v', 'x', 'z', 'a', 'd', 'e', 'e', 'i', 'u', 'a', 's', 's', 'SS', 'LL', 'll', 'V', 'v', 'Y', 'y', '(C)', '(R)', 'CE', 'Cr', 'Fr.', 'L.', 'Pts', 'TL', 'Rs', 'x', 'Rx', 'm/s', 'rad/s', 'C/kg', 'pH', 'V/m', 'A/m', ' 1/4', ' 1/2', ' 3/4', ' 1/3', ' 2/3', ' 1/5', ' 2/5', ' 3/5', ' 4/5', ' 1/6', ' 5/6', ' 1/8', ' 3/8', ' 5/8', ' 7/8', ' 1/', '0', '\'', '\'', ',', '\'', '"', '"', ',,', '"', '\'', '"', '"', '"', '<<', '>>', '<', '>', '-', '-', '-', '-', '-', '-', '-', '-', '-', '||', '/', '[', ']', '*', ',', '.', '<', '>', '<<', '>>', '[', ']', '[', ']', '[', ']', ',', '.', '[', ']', '<<', '>>', '<', '>', ',', '[', ']', '((', '))', '.', ',', '*', '/', '-', '/', '\\', '|', '||', '<<', '>>', '((', '))']; @@ -159,7 +155,9 @@ abstract class AbstractUnicodeString extends AbstractString public function camel(): static { $str = clone $this; - $str->string = str_replace(' ', '', preg_replace_callback('/\b.(?![A-Z]{2,})/u', static function ($m) use (&$i) { + $str->string = str_replace(' ', '', preg_replace_callback('/\b.(?![A-Z]{2,})/u', static function ($m) { + static $i = 0; + return 1 === ++$i ? ('İ' === $m[0] ? 'i̇' : mb_strtolower($m[0], 'UTF-8')) : mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8'); }, preg_replace('/[^\pL0-9]++/u', ' ', $this->string))); @@ -360,9 +358,7 @@ abstract class AbstractUnicodeString extends AbstractString $limit = $allWords ? -1 : 1; - $str->string = preg_replace_callback('/\b./u', static function (array $m): string { - return mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8'); - }, $str->string, $limit); + $str->string = preg_replace_callback('/\b./u', static fn (array $m): string => mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8'), $str->string, $limit); return $str; } diff --git a/vendor/symfony/string/Inflector/EnglishInflector.php b/vendor/symfony/string/Inflector/EnglishInflector.php index 2871e4e5..2cd6bb87 100644 --- a/vendor/symfony/string/Inflector/EnglishInflector.php +++ b/vendor/symfony/string/Inflector/EnglishInflector.php @@ -94,6 +94,9 @@ final class EnglishInflector implements InflectorInterface // accesses (access), addresses (address), kisses (kiss) ['sess', 4, true, false, 'ss'], + // statuses (status) + ['sesutats', 8, true, true, 'status'], + // analyses (analysis), ellipses (ellipsis), fungi (fungus), // neuroses (neurosis), theses (thesis), emphases (emphasis), // oases (oasis), crises (crisis), houses (house), bases (base), @@ -138,6 +141,9 @@ final class EnglishInflector implements InflectorInterface // shoes (shoe) ['se', 2, true, true, ['', 'e']], + // status (status) + ['sutats', 6, true, true, 'status'], + // tags (tag) ['s', 1, true, true, ''], @@ -279,6 +285,9 @@ final class EnglishInflector implements InflectorInterface // circuses (circus) ['suc', 3, true, true, 'cuses'], + // status (status) + ['sutats', 6, true, true, ['status', 'statuses']], + // conspectuses (conspectus), prospectuses (prospectus) ['sutcep', 6, true, true, 'pectuses'], diff --git a/vendor/symfony/string/LazyString.php b/vendor/symfony/string/LazyString.php index 9523b8cd..3128ebb3 100644 --- a/vendor/symfony/string/LazyString.php +++ b/vendor/symfony/string/LazyString.php @@ -30,7 +30,9 @@ class LazyString implements \Stringable, \JsonSerializable } $lazyString = new static(); - $lazyString->value = static function () use (&$callback, &$arguments, &$value): string { + $lazyString->value = static function () use (&$callback, &$arguments): string { + static $value; + if (null !== $arguments) { if (!\is_callable($callback)) { $callback[0] = $callback[0](); diff --git a/vendor/symfony/string/Slugger/AsciiSlugger.php b/vendor/symfony/string/Slugger/AsciiSlugger.php index 826d07ca..6e550c61 100644 --- a/vendor/symfony/string/Slugger/AsciiSlugger.php +++ b/vendor/symfony/string/Slugger/AsciiSlugger.php @@ -74,6 +74,9 @@ class AsciiSlugger implements SluggerInterface, LocaleAwareInterface $this->symbolsMap = $symbolsMap ?? $this->symbolsMap; } + /** + * @return void + */ public function setLocale(string $locale) { $this->defaultLocale = $locale; @@ -121,9 +124,7 @@ class AsciiSlugger implements SluggerInterface, LocaleAwareInterface // If the symbols map is passed as a closure, there is no need to fallback to the parent locale // as the closure can just provide substitutions for all locales of interest. $symbolsMap = $this->symbolsMap; - array_unshift($transliterator, static function ($s) use ($symbolsMap, $locale) { - return $symbolsMap($s, $locale); - }); + array_unshift($transliterator, static fn ($s) => $symbolsMap($s, $locale)); } $unicodeString = (new UnicodeString($string))->ascii($transliterator); diff --git a/vendor/symfony/string/composer.json b/vendor/symfony/string/composer.json index 44a809d5..3545c853 100644 --- a/vendor/symfony/string/composer.json +++ b/vendor/symfony/string/composer.json @@ -26,11 +26,11 @@ "symfony/error-handler": "^5.4|^6.0", "symfony/intl": "^6.2", "symfony/http-client": "^5.4|^6.0", - "symfony/translation-contracts": "^2.0|^3.0", + "symfony/translation-contracts": "^2.5|^3.0", "symfony/var-exporter": "^5.4|^6.0" }, "conflict": { - "symfony/translation-contracts": "<2.0" + "symfony/translation-contracts": "<2.5" }, "autoload": { "psr-4": { "Symfony\\Component\\String\\": "" }, diff --git a/vendor/vimeo/psalm/composer.json b/vendor/vimeo/psalm/composer.json index cfca1191..7df7c97a 100644 --- a/vendor/vimeo/psalm/composer.json +++ b/vendor/vimeo/psalm/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0", + "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", "ext-SimpleXML": "*", "ext-ctype": "*", "ext-dom": "*", @@ -23,9 +23,9 @@ "ext-libxml": "*", "ext-mbstring": "*", "ext-tokenizer": "*", + "composer-runtime-api": "^2", "amphp/amp": "^2.4.2", "amphp/byte-stream": "^1.5", - "composer-runtime-api": "^2", "composer/semver": "^1.4 || ^2.0 || ^3.0", "composer/xdebug-handler": "^2.0 || ^3.0", "dnoegel/php-xdg-base-dir": "^0.1.1", @@ -33,7 +33,7 @@ "felixfbecker/language-server-protocol": "^1.5.2", "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1", "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.14", + "nikic/php-parser": "^4.16", "sebastian/diff": "^4.0 || ^5.0", "spatie/array-to-xml": "^2.17.0 || ^3.0", "symfony/console": "^4.1.6 || ^5.0 || ^6.0", diff --git a/vendor/vimeo/psalm/config.xsd b/vendor/vimeo/psalm/config.xsd index 4d4f377f..4cf075b6 100644 --- a/vendor/vimeo/psalm/config.xsd +++ b/vendor/vimeo/psalm/config.xsd @@ -33,6 +33,7 @@ + diff --git a/vendor/vimeo/psalm/dictionaries/CallMap.php b/vendor/vimeo/psalm/dictionaries/CallMap.php index bb61ce41..7d8c477b 100644 --- a/vendor/vimeo/psalm/dictionaries/CallMap.php +++ b/vendor/vimeo/psalm/dictionaries/CallMap.php @@ -337,7 +337,6 @@ return [ 'AppendIterator::next' => ['void'], 'AppendIterator::rewind' => ['void'], 'AppendIterator::valid' => ['bool'], -'ArgumentCountError::__clone' => ['void'], 'ArgumentCountError::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'ArgumentCountError::__toString' => ['string'], 'ArgumentCountError::__wakeup' => ['void'], @@ -348,7 +347,6 @@ return [ 'ArgumentCountError::getPrevious' => ['?Throwable'], 'ArgumentCountError::getTrace' => ['list\',args?:array}>'], 'ArgumentCountError::getTraceAsString' => ['string'], -'ArithmeticError::__clone' => ['void'], 'ArithmeticError::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'ArithmeticError::__toString' => ['string'], 'ArithmeticError::__wakeup' => ['void'], @@ -425,10 +423,10 @@ return [ 'array_walk\'1' => ['bool', '&rw_array'=>'object', 'callback'=>'callable', 'arg='=>'mixed'], 'array_walk_recursive' => ['bool', '&rw_array'=>'array', 'callback'=>'callable', 'arg='=>'mixed'], 'array_walk_recursive\'1' => ['bool', '&rw_array'=>'object', 'callback'=>'callable', 'arg='=>'mixed'], -'ArrayAccess::offsetExists' => ['bool', 'offset'=>'mixed'], -'ArrayAccess::offsetGet' => ['mixed', 'offset'=>'mixed'], -'ArrayAccess::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], -'ArrayAccess::offsetUnset' => ['void', 'offset'=>'mixed'], +'ArrayAccess::offsetExists' => ['bool', 'offset'=>'int|string'], +'ArrayAccess::offsetGet' => ['mixed', 'offset'=>'int|string'], +'ArrayAccess::offsetSet' => ['void', 'offset'=>'int|string|null', 'value'=>'mixed'], +'ArrayAccess::offsetUnset' => ['void', 'offset'=>'int|string'], 'ArrayIterator::__construct' => ['void', 'array='=>'array|object', 'flags='=>'int'], 'ArrayIterator::append' => ['void', 'value'=>'mixed'], 'ArrayIterator::asort' => ['true', 'flags='=>'int'], @@ -443,7 +441,7 @@ return [ 'ArrayIterator::next' => ['void'], 'ArrayIterator::offsetExists' => ['bool', 'key'=>'string|int'], 'ArrayIterator::offsetGet' => ['mixed', 'key'=>'string|int'], -'ArrayIterator::offsetSet' => ['void', 'key'=>'string|int', 'value'=>'mixed'], +'ArrayIterator::offsetSet' => ['void', 'key'=>'string|int|null', 'value'=>'mixed'], 'ArrayIterator::offsetUnset' => ['void', 'key'=>'string|int'], 'ArrayIterator::rewind' => ['void'], 'ArrayIterator::seek' => ['void', 'offset'=>'int'], @@ -467,7 +465,7 @@ return [ 'ArrayObject::natsort' => ['true'], 'ArrayObject::offsetExists' => ['bool', 'key'=>'int|string'], 'ArrayObject::offsetGet' => ['mixed|null', 'key'=>'int|string'], -'ArrayObject::offsetSet' => ['void', 'key'=>'int|string', 'value'=>'mixed'], +'ArrayObject::offsetSet' => ['void', 'key'=>'int|string|null', 'value'=>'mixed'], 'ArrayObject::offsetUnset' => ['void', 'key'=>'int|string'], 'ArrayObject::serialize' => ['string'], 'ArrayObject::setFlags' => ['void', 'flags'=>'int'], @@ -491,7 +489,6 @@ return [ 'atan' => ['float', 'num'=>'float'], 'atan2' => ['float', 'y'=>'float', 'x'=>'float'], 'atanh' => ['float', 'num'=>'float'], -'BadFunctionCallException::__clone' => ['void'], 'BadFunctionCallException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'BadFunctionCallException::__toString' => ['string'], 'BadFunctionCallException::getCode' => ['int'], @@ -501,7 +498,6 @@ return [ 'BadFunctionCallException::getPrevious' => ['?Throwable'], 'BadFunctionCallException::getTrace' => ['list\',args?:array}>'], 'BadFunctionCallException::getTraceAsString' => ['string'], -'BadMethodCallException::__clone' => ['void'], 'BadMethodCallException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'BadMethodCallException::__toString' => ['string'], 'BadMethodCallException::getCode' => ['int'], @@ -511,7 +507,8 @@ return [ 'BadMethodCallException::getPrevious' => ['?Throwable'], 'BadMethodCallException::getTrace' => ['list\',args?:array}>'], 'BadMethodCallException::getTraceAsString' => ['string'], -'base64_decode' => ['string|false', 'string'=>'string', 'strict='=>'bool'], +'base64_decode' => ['string', 'string'=>'string', 'strict='=>'false'], +'base64_decode\'1' => ['string|false', 'string'=>'string', 'strict='=>'true'], 'base64_encode' => ['string', 'string'=>'string'], 'base_convert' => ['string', 'num'=>'string', 'from_base'=>'int', 'to_base'=>'int'], 'basename' => ['string', 'path'=>'string', 'suffix='=>'string'], @@ -660,7 +657,6 @@ return [ 'clearstatcache' => ['void', 'clear_realpath_cache='=>'bool', 'filename='=>'string'], 'cli_get_process_title' => ['?string'], 'cli_set_process_title' => ['bool', 'title'=>'string'], -'ClosedGeneratorException::__clone' => ['void'], 'ClosedGeneratorException::__toString' => ['string'], 'ClosedGeneratorException::getCode' => ['int'], 'ClosedGeneratorException::getFile' => ['string'], @@ -1351,7 +1347,7 @@ return [ 'datefmt_set_calendar' => ['bool', 'formatter'=>'IntlDateFormatter', 'calendar'=>'IntlCalendar|int|null'], 'datefmt_set_lenient' => ['void', 'formatter'=>'IntlDateFormatter', 'lenient'=>'bool'], 'datefmt_set_pattern' => ['bool', 'formatter'=>'IntlDateFormatter', 'pattern'=>'string'], -'datefmt_set_timezone' => ['false|null', 'formatter'=>'IntlDateFormatter', 'timezone'=>'IntlTimeZone|DateTimeZone|string|null'], +'datefmt_set_timezone' => ['bool', 'formatter'=>'IntlDateFormatter', 'timezone'=>'IntlTimeZone|DateTimeZone|string|null'], 'DateInterval::__construct' => ['void', 'duration'=>'string'], 'DateInterval::__set_state' => ['DateInterval', 'array'=>'array'], 'DateInterval::__wakeup' => ['void'], @@ -1545,7 +1541,7 @@ return [ 'dcgettext' => ['string', 'domain'=>'string', 'message'=>'string', 'category'=>'int'], 'dcngettext' => ['string', 'domain'=>'string', 'singular'=>'string', 'plural'=>'string', 'count'=>'int', 'category'=>'int'], 'deaggregate' => ['', 'object'=>'object', 'class_name='=>'string'], -'debug_backtrace' => ['list', 'options='=>'int', 'limit='=>'int'], +'debug_backtrace' => ['list', 'options='=>'int', 'limit='=>'int'], 'debug_print_backtrace' => ['void', 'options='=>'int', 'limit='=>'int'], 'debug_zval_dump' => ['void', 'value'=>'mixed', '...values='=>'mixed'], 'debugger_connect' => [''], @@ -1612,7 +1608,7 @@ return [ 'DirectoryIterator::setFileClass' => ['void', 'class='=>'class-string'], 'DirectoryIterator::setInfoClass' => ['void', 'class='=>'class-string'], 'DirectoryIterator::valid' => ['bool'], -'dirname' => ['string', 'path'=>'string', 'levels='=>'int'], +'dirname' => ['string', 'path'=>'string', 'levels='=>'int<1, max>'], 'disk_free_space' => ['float|false', 'directory'=>'string'], 'disk_total_space' => ['float|false', 'directory'=>'string'], 'diskfreespace' => ['float|false', 'directory'=>'string'], @@ -1632,7 +1628,6 @@ return [ 'dom_xpath_query' => ['DOMNodeList', 'expr'=>'string', 'context'=>'DOMNode', 'registernodens'=>'bool'], 'dom_xpath_register_ns' => ['bool', 'prefix'=>'string', 'uri'=>'string'], 'dom_xpath_register_php_functions' => [''], -'DomainException::__clone' => ['void'], 'DomainException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'DomainException::__toString' => ['string'], 'DomainException::__wakeup' => ['void'], @@ -2092,7 +2087,6 @@ return [ 'error_get_last' => ['?array{type:int,message:string,file:string,line:int}'], 'error_log' => ['bool', 'message'=>'string', 'message_type='=>'int', 'destination='=>'?string', 'additional_headers='=>'?string'], 'error_reporting' => ['int', 'error_level='=>'?int'], -'ErrorException::__clone' => ['void'], 'ErrorException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'severity='=>'int', 'filename='=>'?string', 'line='=>'?int', 'previous='=>'?Throwable'], 'ErrorException::__toString' => ['string'], 'ErrorException::getCode' => ['int'], @@ -3310,8 +3304,8 @@ return [ 'gethostbyname' => ['string', 'hostname'=>'string'], 'gethostbynamel' => ['list|false', 'hostname'=>'string'], 'gethostname' => ['string|false'], -'getimagesize' => ['array|false', 'filename'=>'string', '&w_image_info='=>'array'], -'getimagesizefromstring' => ['array|false', 'string'=>'string', '&w_image_info='=>'array'], +'getimagesize' => ['array{0:int, 1: int, 2: int, 3: string, mime: string, channels?: 3|4, bits?: int}|false', 'filename'=>'string', '&w_image_info='=>'array'], +'getimagesizefromstring' => ['array{0:int, 1: int, 2: int, 3: string, mime: string, channels?: 3|4, bits?: int}|false', 'string'=>'string', '&w_image_info='=>'array'], 'getlastmod' => ['int|false'], 'getmxrr' => ['bool', 'hostname'=>'string', '&w_hosts'=>'array', '&w_weights='=>'array'], 'getmygid' => ['int|false'], @@ -3329,7 +3323,7 @@ return [ 'gettimeofday' => ['array'], 'gettimeofday\'1' => ['float', 'as_float='=>'true'], 'gettype' => ['string', 'value'=>'mixed'], -'glob' => ['list|false', 'pattern'=>'non-empty-string', 'flags='=>'int<1, max>'], +'glob' => ['false|list{0?:string, ...}', 'pattern'=>'string', 'flags='=>'int<0, max>'], 'GlobIterator::__construct' => ['void', 'pattern'=>'string', 'flags='=>'int'], 'GlobIterator::count' => ['int'], 'GlobIterator::current' => ['FilesystemIterator|SplFileInfo|string'], @@ -3924,7 +3918,7 @@ return [ 'hash_hmac_algos' => ['list'], 'hash_hmac_file' => ['non-empty-string', 'algo'=>'string', 'filename'=>'string', 'key'=>'string', 'binary='=>'bool'], 'hash_init' => ['HashContext', 'algo'=>'string', 'flags='=>'int', 'key='=>'string', 'options='=>'array{seed:scalar}'], -'hash_pbkdf2' => ['non-empty-string', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'binary='=>'bool'], +'hash_pbkdf2' => ['non-empty-string', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'binary='=>'bool', 'options=' => 'array'], 'hash_update' => ['bool', 'context'=>'HashContext', 'data'=>'string'], 'hash_update_file' => ['bool', 'context'=>'HashContext', 'filename'=>'string', 'stream_context='=>'?resource'], 'hash_update_stream' => ['int', 'context'=>'HashContext', 'stream'=>'resource', 'length='=>'int'], @@ -4347,10 +4341,10 @@ return [ 'http\Message\Parser::stream' => ['int', 'stream'=>'resource', 'flags'=>'int', '&message'=>'http\Message'], 'http\Params::__construct' => ['void', 'params='=>'mixed', 'param_sep='=>'mixed', 'arg_sep='=>'mixed', 'val_sep='=>'mixed', 'flags='=>'mixed'], 'http\Params::__toString' => ['string'], -'http\Params::offsetExists' => ['bool', 'name'=>'mixed'], -'http\Params::offsetGet' => ['mixed', 'name'=>'mixed'], -'http\Params::offsetSet' => ['void', 'name'=>'mixed', 'value'=>'mixed'], -'http\Params::offsetUnset' => ['void', 'name'=>'mixed'], +'http\Params::offsetExists' => ['bool', 'name'=>'int|string'], +'http\Params::offsetGet' => ['mixed', 'name'=>'int|string'], +'http\Params::offsetSet' => ['void', 'name'=>'int|string|null', 'value'=>'mixed'], +'http\Params::offsetUnset' => ['void', 'name'=>'int|string'], 'http\Params::toArray' => ['array'], 'http\Params::toString' => ['string'], 'http\QueryString::__construct' => ['void', 'querystring'=>'string'], @@ -4365,10 +4359,10 @@ return [ 'http\QueryString::getObject' => ['object|mixed', 'name'=>'string', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\QueryString::getString' => ['string|mixed', 'name'=>'string', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\QueryString::mod' => ['http\QueryString', 'params='=>'mixed'], -'http\QueryString::offsetExists' => ['bool', 'offset'=>'mixed'], -'http\QueryString::offsetGet' => ['mixed|null', 'offset'=>'mixed'], -'http\QueryString::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], -'http\QueryString::offsetUnset' => ['void', 'offset'=>'mixed'], +'http\QueryString::offsetExists' => ['bool', 'offset'=>'int|string'], +'http\QueryString::offsetGet' => ['mixed|null', 'offset'=>'int|string'], +'http\QueryString::offsetSet' => ['void', 'offset'=>'int|string|null', 'value'=>'mixed'], +'http\QueryString::offsetUnset' => ['void', 'offset'=>'int|string'], 'http\QueryString::serialize' => ['string'], 'http\QueryString::set' => ['http\QueryString', 'params'=>'mixed'], 'http\QueryString::toArray' => ['array'], @@ -4492,10 +4486,10 @@ return [ 'HttpQueryString::getObject' => ['', 'name'=>'', 'defval'=>'', 'delete'=>''], 'HttpQueryString::getString' => ['', 'name'=>'', 'defval'=>'', 'delete'=>''], 'HttpQueryString::mod' => ['HttpQueryString', 'params'=>'mixed'], -'HttpQueryString::offsetExists' => ['bool', 'offset'=>'mixed'], -'HttpQueryString::offsetGet' => ['mixed', 'offset'=>'mixed'], -'HttpQueryString::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], -'HttpQueryString::offsetUnset' => ['void', 'offset'=>'mixed'], +'HttpQueryString::offsetExists' => ['bool', 'offset'=>'int|string'], +'HttpQueryString::offsetGet' => ['mixed', 'offset'=>'int|string'], +'HttpQueryString::offsetSet' => ['void', 'offset'=>'int|string|null', 'value'=>'mixed'], +'HttpQueryString::offsetUnset' => ['void', 'offset'=>'int|string'], 'HttpQueryString::serialize' => ['string'], 'HttpQueryString::set' => ['string', 'params'=>'mixed'], 'HttpQueryString::singleton' => ['HttpQueryString', 'global='=>'bool'], @@ -5580,21 +5574,21 @@ return [ 'imap_body' => ['string|false', 'imap'=>'IMAP\Connection', 'message_num'=>'int', 'flags='=>'int'], 'imap_bodystruct' => ['stdClass|false', 'imap'=>'IMAP\Connection', 'message_num'=>'int', 'section'=>'string'], 'imap_check' => ['stdClass|false', 'imap'=>'IMAP\Connection'], -'imap_clearflag_full' => ['bool', 'imap'=>'IMAP\Connection', 'sequence'=>'string', 'flag'=>'string', 'options='=>'int'], -'imap_close' => ['bool', 'imap'=>'IMAP\Connection', 'flags='=>'int'], +'imap_clearflag_full' => ['true', 'imap'=>'IMAP\Connection', 'sequence'=>'string', 'flag'=>'string', 'options='=>'int'], +'imap_close' => ['true', 'imap'=>'IMAP\Connection', 'flags='=>'int'], 'imap_create' => ['bool', 'imap'=>'IMAP\Connection', 'mailbox'=>'string'], 'imap_createmailbox' => ['bool', 'imap'=>'IMAP\Connection', 'mailbox'=>'string'], -'imap_delete' => ['bool', 'imap'=>'IMAP\Connection', 'message_nums'=>'string', 'flags='=>'int'], +'imap_delete' => ['true', 'imap'=>'IMAP\Connection', 'message_nums'=>'string', 'flags='=>'int'], 'imap_deletemailbox' => ['bool', 'imap'=>'IMAP\Connection', 'mailbox'=>'string'], 'imap_errors' => ['array|false'], -'imap_expunge' => ['bool', 'imap'=>'IMAP\Connection'], +'imap_expunge' => ['true', 'imap'=>'IMAP\Connection'], 'imap_fetch_overview' => ['array|false', 'imap'=>'IMAP\Connection', 'sequence'=>'string', 'flags='=>'int'], 'imap_fetchbody' => ['string|false', 'imap'=>'IMAP\Connection', 'message_num'=>'int', 'section'=>'string', 'flags='=>'int'], 'imap_fetchheader' => ['string|false', 'imap'=>'IMAP\Connection', 'message_num'=>'int', 'flags='=>'int'], 'imap_fetchmime' => ['string|false', 'imap'=>'IMAP\Connection', 'message_num'=>'int', 'section'=>'string', 'flags='=>'int'], 'imap_fetchstructure' => ['stdClass|false', 'imap'=>'IMAP\Connection', 'message_num'=>'int', 'flags='=>'int'], 'imap_fetchtext' => ['string|false', 'imap'=>'IMAP\Connection', 'message_num'=>'int', 'flags='=>'int'], -'imap_gc' => ['bool', 'imap'=>'IMAP\Connection', 'flags'=>'int'], +'imap_gc' => ['true', 'imap'=>'IMAP\Connection', 'flags'=>'int'], 'imap_get_quota' => ['array|false', 'imap'=>'IMAP\Connection', 'quota_root'=>'string'], 'imap_get_quotaroot' => ['array|false', 'imap'=>'IMAP\Connection', 'mailbox'=>'string'], 'imap_getacl' => ['array|false', 'imap'=>'IMAP\Connection', 'mailbox'=>'string'], @@ -5635,14 +5629,14 @@ return [ 'imap_search' => ['array|false', 'imap'=>'IMAP\Connection', 'criteria'=>'string', 'flags='=>'int', 'charset='=>'string'], 'imap_set_quota' => ['bool', 'imap'=>'IMAP\Connection', 'quota_root'=>'string', 'mailbox_size'=>'int'], 'imap_setacl' => ['bool', 'imap'=>'IMAP\Connection', 'mailbox'=>'string', 'user_id'=>'string', 'rights'=>'string'], -'imap_setflag_full' => ['bool', 'imap'=>'IMAP\Connection', 'sequence'=>'string', 'flag'=>'string', 'options='=>'int'], +'imap_setflag_full' => ['true', 'imap'=>'IMAP\Connection', 'sequence'=>'string', 'flag'=>'string', 'options='=>'int'], 'imap_sort' => ['array|false', 'imap'=>'IMAP\Connection', 'criteria'=>'int', 'reverse'=>'bool', 'flags='=>'int', 'search_criteria='=>'?string', 'charset='=>'?string'], 'imap_status' => ['stdClass|false', 'imap'=>'IMAP\Connection', 'mailbox'=>'string', 'flags'=>'int'], 'imap_subscribe' => ['bool', 'imap'=>'IMAP\Connection', 'mailbox'=>'string'], 'imap_thread' => ['array|false', 'imap'=>'IMAP\Connection', 'flags='=>'int'], 'imap_timeout' => ['int|bool', 'timeout_type'=>'int', 'timeout='=>'int'], 'imap_uid' => ['int|false', 'imap'=>'IMAP\Connection', 'message_num'=>'int'], -'imap_undelete' => ['bool', 'imap'=>'IMAP\Connection', 'message_nums'=>'string', 'flags='=>'int'], +'imap_undelete' => ['true', 'imap'=>'IMAP\Connection', 'message_nums'=>'string', 'flags='=>'int'], 'imap_unsubscribe' => ['bool', 'imap'=>'IMAP\Connection', 'mailbox'=>'string'], 'imap_utf7_decode' => ['string|false', 'string'=>'string'], 'imap_utf7_encode' => ['string', 'string'=>'string'], @@ -5737,11 +5731,11 @@ return [ 'IntlBreakIterator::next' => ['int', 'offset='=>'?int'], 'IntlBreakIterator::preceding' => ['int', 'offset'=>'int'], 'IntlBreakIterator::previous' => ['int'], -'IntlBreakIterator::setText' => ['?bool', 'text'=>'string'], +'IntlBreakIterator::setText' => ['bool', 'text'=>'string'], 'intlcal_add' => ['bool', 'calendar'=>'IntlCalendar', 'field'=>'int', 'value'=>'int'], 'intlcal_after' => ['bool', 'calendar'=>'IntlCalendar', 'other'=>'IntlCalendar'], 'intlcal_before' => ['bool', 'calendar'=>'IntlCalendar', 'other'=>'IntlCalendar'], -'intlcal_clear' => ['bool', 'calendar'=>'IntlCalendar', 'field='=>'?int'], +'intlcal_clear' => ['true', 'calendar'=>'IntlCalendar', 'field='=>'?int'], 'intlcal_create_instance' => ['?IntlCalendar', 'timezone='=>'mixed', 'locale='=>'?string'], 'intlcal_equals' => ['bool', 'calendar'=>'IntlCalendar', 'other'=>'IntlCalendar'], 'intlcal_field_difference' => ['int|false', 'calendar'=>'IntlCalendar', 'timestamp'=>'float', 'field'=>'int'], @@ -5774,8 +5768,8 @@ return [ 'intlcal_roll' => ['bool', 'calendar'=>'IntlCalendar', 'field'=>'int', 'value'=>'mixed'], 'intlcal_set' => ['bool', 'calendar'=>'IntlCalendar', 'year'=>'int', 'month'=>'int'], 'intlcal_set\'1' => ['bool', 'calendar'=>'IntlCalendar', 'year'=>'int', 'month'=>'int', 'dayOfMonth='=>'int', 'hour='=>'int', 'minute='=>'int', 'second='=>'int'], -'intlcal_set_first_day_of_week' => ['bool', 'calendar'=>'IntlCalendar', 'dayOfWeek'=>'int'], -'intlcal_set_lenient' => ['bool', 'calendar'=>'IntlCalendar', 'lenient'=>'bool'], +'intlcal_set_first_day_of_week' => ['true', 'calendar'=>'IntlCalendar', 'dayOfWeek'=>'int'], +'intlcal_set_lenient' => ['true', 'calendar'=>'IntlCalendar', 'lenient'=>'bool'], 'intlcal_set_repeated_wall_time_option' => ['true', 'calendar'=>'IntlCalendar', 'option'=>'int'], 'intlcal_set_skipped_wall_time_option' => ['true', 'calendar'=>'IntlCalendar', 'option'=>'int'], 'intlcal_set_time' => ['bool', 'calendar'=>'IntlCalendar', 'timestamp'=>'float'], @@ -5837,7 +5831,7 @@ return [ 'IntlChar::charType' => ['?int', 'codepoint'=>'int|string'], 'IntlChar::chr' => ['?string', 'codepoint'=>'int|string'], 'IntlChar::digit' => ['int|false|null', 'codepoint'=>'int|string', 'base='=>'int'], -'IntlChar::enumCharNames' => ['?bool', 'start'=>'string|int', 'end'=>'string|int', 'callback'=>'callable(int,int,int):void', 'type='=>'int'], +'IntlChar::enumCharNames' => ['bool', 'start'=>'string|int', 'end'=>'string|int', 'callback'=>'callable(int,int,int):void', 'type='=>'int'], 'IntlChar::enumCharTypes' => ['void', 'callback'=>'callable(int,int,int):void'], 'IntlChar::foldCase' => ['int|string|null', 'codepoint'=>'int|string', 'options='=>'int'], 'IntlChar::forDigit' => ['int', 'digit'=>'int', 'base='=>'int'], @@ -5887,7 +5881,6 @@ return [ 'IntlChar::tolower' => ['int|string|null', 'codepoint'=>'int|string'], 'IntlChar::totitle' => ['int|string|null', 'codepoint'=>'int|string'], 'IntlChar::toupper' => ['int|string|null', 'codepoint'=>'int|string'], -'IntlCodePointBreakIterator::__construct' => ['void'], 'IntlCodePointBreakIterator::createCharacterInstance' => ['?IntlRuleBasedBreakIterator', 'locale='=>'?string'], 'IntlCodePointBreakIterator::createCodePointInstance' => ['IntlCodePointBreakIterator'], 'IntlCodePointBreakIterator::createLineInstance' => ['?IntlRuleBasedBreakIterator', 'locale='=>'?string'], @@ -5908,7 +5901,7 @@ return [ 'IntlCodePointBreakIterator::next' => ['int', 'offset='=>'?int'], 'IntlCodePointBreakIterator::preceding' => ['int', 'offset'=>'int'], 'IntlCodePointBreakIterator::previous' => ['int'], -'IntlCodePointBreakIterator::setText' => ['?bool', 'text'=>'string'], +'IntlCodePointBreakIterator::setText' => ['bool', 'text'=>'string'], 'IntlDateFormatter::__construct' => ['void', 'locale'=>'?string', 'dateType='=>'int', 'timeType='=>'int', 'timezone='=>'IntlTimeZone|DateTimeZone|string|null', 'calendar='=>'IntlCalendar|int|null', 'pattern='=>'?string'], 'IntlDateFormatter::create' => ['?IntlDateFormatter', 'locale'=>'?string', 'dateType='=>'int', 'timeType='=>'int', 'timezone='=>'IntlTimeZone|DateTimeZone|string|null', 'calendar='=>'IntlCalendar|int|null', 'pattern='=>'?string'], 'IntlDateFormatter::format' => ['string|false', 'datetime'=>'IntlCalendar|DateTimeInterface|array{0: int, 1: int, 2: int, 3: int, 4: int, 5: int, 6: int, 7: int, 8: int}|array{tm_sec: int, tm_min: int, tm_hour: int, tm_mday: int, tm_mon: int, tm_year: int, tm_wday: int, tm_yday: int, tm_isdst: int}|string|int|float'], @@ -5929,8 +5922,7 @@ return [ 'IntlDateFormatter::setCalendar' => ['bool', 'calendar'=>'IntlCalendar|int|null'], 'IntlDateFormatter::setLenient' => ['void', 'lenient'=>'bool'], 'IntlDateFormatter::setPattern' => ['bool', 'pattern'=>'string'], -'IntlDateFormatter::setTimeZone' => ['null|false', 'timezone'=>'IntlTimeZone|DateTimeZone|string|null'], -'IntlException::__clone' => ['void'], +'IntlDateFormatter::setTimeZone' => ['bool', 'timezone'=>'IntlTimeZone|DateTimeZone|string|null'], 'IntlException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'IntlException::__toString' => ['string'], 'IntlException::__wakeup' => ['void'], @@ -6026,7 +6018,7 @@ return [ 'IntlRuleBasedBreakIterator::next' => ['int', 'offset='=>'?int'], 'IntlRuleBasedBreakIterator::preceding' => ['int', 'offset'=>'int'], 'IntlRuleBasedBreakIterator::previous' => ['int'], -'IntlRuleBasedBreakIterator::setText' => ['?bool', 'text'=>'string'], +'IntlRuleBasedBreakIterator::setText' => ['bool', 'text'=>'string'], 'IntlTimeZone::countEquivalentIDs' => ['int|false', 'timezoneId'=>'string'], 'IntlTimeZone::createDefault' => ['IntlTimeZone'], 'IntlTimeZone::createEnumeration' => ['IntlIterator|false', 'countryOrRawOffset='=>'IntlTimeZone|string|int|float|null'], @@ -6071,7 +6063,6 @@ return [ 'intltz_use_daylight_time' => ['bool', 'timezone'=>'IntlTimeZone'], 'intlz_create_default' => ['IntlTimeZone'], 'intval' => ['int', 'value'=>'mixed', 'base='=>'int'], -'InvalidArgumentException::__clone' => ['void'], 'InvalidArgumentException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'InvalidArgumentException::__toString' => ['string'], 'InvalidArgumentException::getCode' => ['int'], @@ -6157,7 +6148,6 @@ return [ 'json_last_error' => ['int'], 'json_last_error_msg' => ['string'], 'json_validate' => ['bool', 'json'=>'string', 'depth='=>'positive-int', 'flags='=>'int'], -'JsonException::__clone' => ['void'], 'JsonException::__construct' => ['void', "message="=>"string", 'code='=>'int', 'previous='=>'?Throwable'], 'JsonException::__toString' => ['string'], 'JsonException::__wakeup' => ['void'], @@ -6188,10 +6178,10 @@ return [ 'Judy::memoryUsage' => ['int'], 'Judy::next' => ['mixed', 'index'=>'mixed'], 'Judy::nextEmpty' => ['mixed', 'index'=>'mixed'], -'Judy::offsetExists' => ['bool', 'offset'=>'mixed'], -'Judy::offsetGet' => ['mixed', 'offset'=>'mixed'], -'Judy::offsetSet' => ['bool', 'offset'=>'mixed', 'value'=>'mixed'], -'Judy::offsetUnset' => ['bool', 'offset'=>'mixed'], +'Judy::offsetExists' => ['bool', 'offset'=>'int|string'], +'Judy::offsetGet' => ['mixed', 'offset'=>'int|string'], +'Judy::offsetSet' => ['bool', 'offset'=>'int|string|null', 'value'=>'mixed'], +'Judy::offsetUnset' => ['bool', 'offset'=>'int|string'], 'Judy::prev' => ['mixed', 'index'=>'mixed'], 'Judy::prevEmpty' => ['mixed', 'index'=>'mixed'], 'Judy::size' => ['int'], @@ -6384,7 +6374,6 @@ return [ 'legendObj::free' => ['void'], 'legendObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'legendObj::updateFromString' => ['int', 'snippet'=>'string'], -'LengthException::__clone' => ['void'], 'LengthException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'LengthException::__toString' => ['string'], 'LengthException::getCode' => ['int'], @@ -6497,7 +6486,6 @@ return [ 'log' => ['float', 'num'=>'float', 'base='=>'float'], 'log10' => ['float', 'num'=>'float'], 'log1p' => ['float', 'num'=>'float'], -'LogicException::__clone' => ['void'], 'LogicException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'LogicException::__toString' => ['string'], 'LogicException::getCode' => ['int'], @@ -7059,6 +7047,14 @@ return [ 'MongoDB::setReadPreference' => ['bool', 'read_preference'=>'string', 'tags='=>'array'], 'MongoDB::setSlaveOkay' => ['bool', 'ok='=>'bool'], 'MongoDB::setWriteConcern' => ['bool', 'w'=>'mixed', 'wtimeout='=>'int'], +'MongoDB\BSON\fromJSON' => ['string', 'json' => 'string'], +'MongoDB\BSON\fromPHP' => ['string', 'value' => 'object|array'], +'MongoDB\BSON\toCanonicalExtendedJSON' => ['string', 'bson' => 'string'], +'MongoDB\BSON\toJSON' => ['string', 'bson' => 'string'], +'MongoDB\BSON\toPHP' => ['object|array', 'bson' => 'string', 'typemap=' => '?array'], +'MongoDB\BSON\toRelaxedExtendedJSON' => ['string', 'bson' => 'string'], +'MongoDB\Driver\Monitoring\addSubscriber' => ['void', 'subscriber' => 'MongoDB\Driver\Monitoring\Subscriber'], +'MongoDB\Driver\Monitoring\removeSubscriber' => ['void', 'subscriber' => 'MongoDB\Driver\Monitoring\Subscriber'], 'MongoDB\BSON\Binary::__construct' => ['void', 'data' => 'string', 'type=' => 'int'], 'MongoDB\BSON\Binary::getData' => ['string'], 'MongoDB\BSON\Binary::getType' => ['int'], @@ -7079,10 +7075,28 @@ return [ 'MongoDB\BSON\Decimal128::unserialize' => ['void', 'serialized' => 'string'], 'MongoDB\BSON\Decimal128::jsonSerialize' => ['mixed'], 'MongoDB\BSON\Decimal128Interface::__toString' => ['string'], +'MongoDB\BSON\Document::fromBSON' => ['MongoDB\BSON\Document', 'bson' => 'string'], +'MongoDB\BSON\Document::fromJSON' => ['MongoDB\BSON\Document', 'json' => 'string'], +'MongoDB\BSON\Document::fromPHP' => ['MongoDB\BSON\Document', 'value' => 'object|array'], +'MongoDB\BSON\Document::get' => ['mixed', 'key' => 'string'], +'MongoDB\BSON\Document::getIterator' => ['MongoDB\BSON\Iterator'], +'MongoDB\BSON\Document::has' => ['bool', 'key' => 'string'], +'MongoDB\BSON\Document::toPHP' => ['object|array', 'typeMap=' => '?array'], +'MongoDB\BSON\Document::toCanonicalExtendedJSON' => ['string'], +'MongoDB\BSON\Document::toRelaxedExtendedJSON' => ['string'], +'MongoDB\BSON\Document::__toString' => ['string'], +'MongoDB\BSON\Document::serialize' => ['string'], +'MongoDB\BSON\Document::unserialize' => ['void', 'serialized' => 'string'], +'MongoDB\BSON\Int64::__construct' => ['void', 'value' => 'string|int'], 'MongoDB\BSON\Int64::__toString' => ['string'], 'MongoDB\BSON\Int64::serialize' => ['string'], 'MongoDB\BSON\Int64::unserialize' => ['void', 'serialized' => 'string'], 'MongoDB\BSON\Int64::jsonSerialize' => ['mixed'], +'MongoDB\BSON\Iterator::current' => ['mixed'], +'MongoDB\BSON\Iterator::key' => ['string|int'], +'MongoDB\BSON\Iterator::next' => ['void'], +'MongoDB\BSON\Iterator::rewind' => ['void'], +'MongoDB\BSON\Iterator::valid' => ['bool'], 'MongoDB\BSON\Javascript::__construct' => ['void', 'code' => 'string', 'scope=' => 'object|array|null'], 'MongoDB\BSON\Javascript::getCode' => ['string'], 'MongoDB\BSON\Javascript::getScope' => ['?object'], @@ -7107,6 +7121,14 @@ return [ 'MongoDB\BSON\ObjectId::jsonSerialize' => ['mixed'], 'MongoDB\BSON\ObjectIdInterface::getTimestamp' => ['int'], 'MongoDB\BSON\ObjectIdInterface::__toString' => ['string'], +'MongoDB\BSON\PackedArray::fromPHP' => ['MongoDB\BSON\PackedArray', 'value' => 'array'], +'MongoDB\BSON\PackedArray::get' => ['mixed', 'index' => 'int'], +'MongoDB\BSON\PackedArray::getIterator' => ['MongoDB\BSON\Iterator'], +'MongoDB\BSON\PackedArray::has' => ['bool', 'index' => 'int'], +'MongoDB\BSON\PackedArray::toPHP' => ['object|array', 'typeMap=' => '?array'], +'MongoDB\BSON\PackedArray::__toString' => ['string'], +'MongoDB\BSON\PackedArray::serialize' => ['string'], +'MongoDB\BSON\PackedArray::unserialize' => ['void', 'serialized' => 'string'], 'MongoDB\BSON\Regex::__construct' => ['void', 'pattern' => 'string', 'flags=' => 'string'], 'MongoDB\BSON\Regex::getPattern' => ['string'], 'MongoDB\BSON\Regex::getFlags' => ['string'], @@ -7156,6 +7178,7 @@ return [ 'MongoDB\Driver\ClientEncryption::decrypt' => ['mixed', 'value' => 'MongoDB\BSON\Binary'], 'MongoDB\Driver\ClientEncryption::deleteKey' => ['object', 'keyId' => 'MongoDB\BSON\Binary'], 'MongoDB\Driver\ClientEncryption::encrypt' => ['MongoDB\BSON\Binary', 'value' => 'mixed', 'options=' => '?array'], +'MongoDB\Driver\ClientEncryption::encryptExpression' => ['object', 'expr' => 'object|array', 'options=' => '?array'], 'MongoDB\Driver\ClientEncryption::getKey' => ['?object', 'keyId' => 'MongoDB\BSON\Binary'], 'MongoDB\Driver\ClientEncryption::getKeyByAltName' => ['?object', 'keyAltName' => 'string'], 'MongoDB\Driver\ClientEncryption::getKeys' => ['MongoDB\Driver\Cursor'], @@ -7367,6 +7390,7 @@ return [ 'MongoDB\Driver\WriteResult::getUpsertedIds' => ['array'], 'MongoDB\Driver\WriteResult::getWriteConcernError' => ['?MongoDB\Driver\WriteConcernError'], 'MongoDB\Driver\WriteResult::getWriteErrors' => ['array'], +'MongoDB\Driver\WriteResult::getErrorReplies' => ['array'], 'MongoDB\Driver\WriteResult::isAcknowledged' => ['bool'], 'MongoDBRef::create' => ['array', 'collection'=>'string', 'id'=>'mixed', 'database='=>'string'], 'MongoDBRef::get' => ['?array', 'db'=>'MongoDB', 'ref'=>'array'], @@ -7615,7 +7639,7 @@ return [ 'mt_getrandmax' => ['int'], 'mt_rand' => ['int', 'min'=>'int', 'max'=>'int'], 'mt_rand\'1' => ['int'], -'mt_srand' => ['void', 'seed='=>'int', 'mode='=>'int'], +'mt_srand' => ['void', 'seed='=>'?int', 'mode='=>'int'], 'MultipleIterator::__construct' => ['void', 'flags='=>'int'], 'MultipleIterator::attachIterator' => ['void', 'iterator'=>'Iterator', 'info='=>'string|int|null'], 'MultipleIterator::containsIterator' => ['bool', 'iterator'=>'Iterator'], @@ -8092,8 +8116,8 @@ return [ 'MysqlndUhPreparedStatement::__construct' => ['void'], 'MysqlndUhPreparedStatement::execute' => ['bool', 'statement'=>'mysqlnd_prepared_statement'], 'MysqlndUhPreparedStatement::prepare' => ['bool', 'statement'=>'mysqlnd_prepared_statement', 'query'=>'string'], -'natcasesort' => ['bool', '&rw_array'=>'array'], -'natsort' => ['bool', '&rw_array'=>'array'], +'natcasesort' => ['true', '&rw_array'=>'array'], +'natsort' => ['true', '&rw_array'=>'array'], 'net_get_interfaces' => ['array>|false'], 'newrelic_add_custom_parameter' => ['bool', 'key'=>'string', 'value'=>'bool|float|int|string'], 'newrelic_add_custom_tracer' => ['bool', 'function_name'=>'string'], @@ -8502,7 +8526,6 @@ return [ 'OuterIterator::next' => ['void'], 'OuterIterator::rewind' => ['void'], 'OuterIterator::valid' => ['bool'], -'OutOfBoundsException::__clone' => ['void'], 'OutOfBoundsException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'OutOfBoundsException::__toString' => ['string'], 'OutOfBoundsException::getCode' => ['int'], @@ -8512,7 +8535,6 @@ return [ 'OutOfBoundsException::getPrevious' => ['?Throwable'], 'OutOfBoundsException::getTrace' => ['list\',args?:array}>'], 'OutOfBoundsException::getTraceAsString' => ['string'], -'OutOfRangeException::__clone' => ['void'], 'OutOfRangeException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'OutOfRangeException::__toString' => ['string'], 'OutOfRangeException::getCode' => ['int'], @@ -8539,7 +8561,6 @@ return [ 'outputformatObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'outputformatObj::setOption' => ['void', 'property_name'=>'string', 'new_value'=>'string'], 'outputformatObj::validate' => ['int'], -'OverflowException::__clone' => ['void'], 'OverflowException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'OverflowException::__toString' => ['string'], 'OverflowException::getCode' => ['int'], @@ -8631,7 +8652,6 @@ return [ 'parse_ini_string' => ['array|false', 'ini_string'=>'string', 'process_sections='=>'bool', 'scanner_mode='=>'int'], 'parse_str' => ['void', 'string'=>'string', '&w_result'=>'array'], 'parse_url' => ['int|string|array|null|false', 'url'=>'string', 'component='=>'int'], -'ParseError::__clone' => ['void'], 'ParseError::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'ParseError::__toString' => ['string'], 'ParseError::getCode' => ['int'], @@ -9363,7 +9383,7 @@ return [ 'posix_getppid' => ['int'], 'posix_getpwnam' => ['array{name: string, passwd: string, uid: int, gid: int, gecos: string, dir: string, shell: string}|false', 'username'=>'string'], 'posix_getpwuid' => ['array{name: string, passwd: string, uid: int, gid: int, gecos: string, dir: string, shell: string}|false', 'user_id'=>'int'], -'posix_getrlimit' => ['array{"soft core": string, "hard core": string, "soft data": string, "hard data": string, "soft stack": integer, "hard stack": string, "soft totalmem": string, "hard totalmem": string, "soft rss": string, "hard rss": string, "soft maxproc": integer, "hard maxproc": integer, "soft memlock": integer, "hard memlock": integer, "soft cpu": string, "hard cpu": string, "soft filesize": string, "hard filesize": string, "soft openfiles": integer, "hard openfiles": integer}|false'], +'posix_getrlimit' => ['array{"soft core": string, "hard core": string, "soft data": string, "hard data": string, "soft stack": integer, "hard stack": string, "soft totalmem": string, "hard totalmem": string, "soft rss": string, "hard rss": string, "soft maxproc": integer, "hard maxproc": integer, "soft memlock": integer, "hard memlock": integer, "soft cpu": string, "hard cpu": string, "soft filesize": string, "hard filesize": string, "soft openfiles": integer, "hard openfiles": integer}|false', 'resource=' => '?int'], 'posix_getsid' => ['int|false', 'process_id'=>'int'], 'posix_getuid' => ['int'], 'posix_initgroups' => ['bool', 'username'=>'string', 'group_id'=>'int'], @@ -9403,7 +9423,7 @@ return [ 'print' => ['int', 'arg'=>'string'], 'print_r' => ['string', 'value'=>'mixed'], 'print_r\'1' => ['true', 'value'=>'mixed', 'return='=>'bool'], -'printf' => ['int', 'format'=>'string', '...values='=>'string|int|float'], +'printf' => ['int<0, max>', 'format'=>'string', '...values='=>'string|int|float'], 'proc_close' => ['int', 'process'=>'resource'], 'proc_get_status' => ['array{command: string, pid: int, running: bool, signaled: bool, stopped: bool, exitcode: int, termsig: int, stopsig: int}', 'process'=>'resource'], 'proc_nice' => ['bool', 'priority'=>'int'], @@ -9624,7 +9644,6 @@ return [ 'random_bytes' => ['non-empty-string', 'length'=>'positive-int'], 'random_int' => ['int', 'min'=>'int', 'max'=>'int'], 'range' => ['non-empty-array', 'start'=>'string|int|float', 'end'=>'string|int|float', 'step='=>'int<1, max>|float'], -'RangeException::__clone' => ['void'], 'RangeException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'RangeException::__toString' => ['string'], 'RangeException::getCode' => ['int'], @@ -9814,7 +9833,7 @@ return [ 'RecursiveArrayIterator::next' => ['void'], 'RecursiveArrayIterator::offsetExists' => ['bool', 'key'=>'string|int'], 'RecursiveArrayIterator::offsetGet' => ['mixed', 'key'=>'string|int'], -'RecursiveArrayIterator::offsetSet' => ['void', 'key'=>'string|int', 'value'=>'string'], +'RecursiveArrayIterator::offsetSet' => ['void', 'key'=>'string|int|null', 'value'=>'string'], 'RecursiveArrayIterator::offsetUnset' => ['void', 'key'=>'string|int'], 'RecursiveArrayIterator::rewind' => ['void'], 'RecursiveArrayIterator::seek' => ['void', 'offset'=>'int'], @@ -10624,12 +10643,10 @@ return [ 'ReflectionMethod::isVariadic' => ['bool'], 'ReflectionMethod::returnsReference' => ['bool'], 'ReflectionMethod::setAccessible' => ['void', 'accessible'=>'bool'], -'ReflectionNamedType::__clone' => ['void'], 'ReflectionNamedType::__toString' => ['string'], 'ReflectionNamedType::allowsNull' => ['bool'], 'ReflectionNamedType::getName' => ['string'], 'ReflectionNamedType::isBuiltin' => ['bool'], -'ReflectionObject::__clone' => ['void'], 'ReflectionObject::__construct' => ['void', 'object'=>'object'], 'ReflectionObject::__toString' => ['string'], 'ReflectionObject::getConstant' => ['mixed', 'name'=>'string'], @@ -10814,7 +10831,7 @@ return [ 'RRDGraph::setOptions' => ['void', 'options'=>'array'], 'RRDUpdater::__construct' => ['void', 'path'=>'string'], 'RRDUpdater::update' => ['bool', 'values'=>'array', 'time='=>'string'], -'rsort' => ['bool', '&rw_array'=>'array', 'flags='=>'int'], +'rsort' => ['true', '&rw_array'=>'array', 'flags='=>'int'], 'rtrim' => ['string', 'string'=>'string', 'characters='=>'string'], 'runkit7_constant_add' => ['bool', 'constant_name'=>'string', 'value'=>'mixed', 'new_visibility='=>'int'], 'runkit7_constant_redefine' => ['bool', 'constant_name'=>'string', 'value'=>'mixed', 'new_visibility='=>'?int'], @@ -10861,7 +10878,6 @@ return [ 'Runkit_Sandbox_Parent::__construct' => ['void'], 'runkit_superglobals' => ['array'], 'runkit_zval_inspect' => ['array', 'value'=>'mixed'], -'RuntimeException::__clone' => ['void'], 'RuntimeException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'RuntimeException::__toString' => ['string'], 'RuntimeException::getCode' => ['int'], @@ -11303,7 +11319,7 @@ return [ 'SimpleXMLElement::getNamespaces' => ['array', 'recursive='=>'bool'], 'SimpleXMLElement::offsetExists' => ['bool', 'offset'=>'int|string'], 'SimpleXMLElement::offsetGet' => ['SimpleXMLElement', 'offset'=>'int|string'], -'SimpleXMLElement::offsetSet' => ['void', 'offset'=>'int|string', 'value'=>'mixed'], +'SimpleXMLElement::offsetSet' => ['void', 'offset'=>'int|string|null', 'value'=>'mixed'], 'SimpleXMLElement::offsetUnset' => ['void', 'offset'=>'int|string'], 'SimpleXMLElement::registerXPathNamespace' => ['bool', 'prefix'=>'string', 'namespace'=>'string'], 'SimpleXMLElement::saveXML' => ['string|bool', 'filename='=>'?string'], @@ -12721,7 +12737,7 @@ return [ 'sqlsrv_send_stream_data' => ['bool', 'stmt'=>'resource'], 'sqlsrv_server_info' => ['array', 'conn'=>'resource'], 'sqrt' => ['float', 'num'=>'float'], -'srand' => ['void', 'seed='=>'int', 'mode='=>'int'], +'srand' => ['void', 'seed='=>'?int', 'mode='=>'int'], 'sscanf' => ['list|int|null', 'string'=>'string', 'format'=>'string', '&...w_vars='=>'string|int|float|null'], 'ssdeep_fuzzy_compare' => ['int', 'signature1'=>'string', 'signature2'=>'string'], 'ssdeep_fuzzy_hash' => ['string', 'to_hash'=>'string'], @@ -13616,10 +13632,10 @@ return [ 'Thread::merge' => ['bool', 'from'=>'', 'overwrite='=>'mixed'], 'Thread::notify' => ['bool'], 'Thread::notifyOne' => ['bool'], -'Thread::offsetExists' => ['bool', 'offset'=>'mixed'], -'Thread::offsetGet' => ['mixed', 'offset'=>'mixed'], -'Thread::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], -'Thread::offsetUnset' => ['void', 'offset'=>'mixed'], +'Thread::offsetExists' => ['bool', 'offset'=>'int|string'], +'Thread::offsetGet' => ['mixed', 'offset'=>'int|string'], +'Thread::offsetSet' => ['void', 'offset'=>'int|string|null', 'value'=>'mixed'], +'Thread::offsetUnset' => ['void', 'offset'=>'int|string'], 'Thread::pop' => ['bool'], 'Thread::run' => ['void'], 'Thread::setGarbage' => ['void'], @@ -13645,10 +13661,10 @@ return [ 'Threaded::merge' => ['bool', 'from'=>'mixed', 'overwrite='=>'bool'], 'Threaded::notify' => ['bool'], 'Threaded::notifyOne' => ['bool'], -'Threaded::offsetExists' => ['bool', 'offset'=>'mixed'], -'Threaded::offsetGet' => ['mixed', 'offset'=>'mixed'], -'Threaded::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], -'Threaded::offsetUnset' => ['void', 'offset'=>'mixed'], +'Threaded::offsetExists' => ['bool', 'offset'=>'int|string'], +'Threaded::offsetGet' => ['mixed', 'offset'=>'int|string'], +'Threaded::offsetSet' => ['void', 'offset'=>'int|string|null', 'value'=>'mixed'], +'Threaded::offsetUnset' => ['void', 'offset'=>'int|string'], 'Threaded::pop' => ['bool'], 'Threaded::run' => ['void'], 'Threaded::setGarbage' => ['void'], @@ -13973,7 +13989,6 @@ return [ 'transliterator_transliterate' => ['string|false', 'transliterator'=>'Transliterator|string', 'string'=>'string', 'start='=>'int', 'end='=>'int'], 'trigger_error' => ['bool', 'message'=>'string', 'error_level='=>'256|512|1024|16384'], 'trim' => ['string', 'string'=>'string', 'characters='=>'string'], -'TypeError::__clone' => ['void'], 'TypeError::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'TypeError::__toString' => ['string'], 'TypeError::getCode' => ['int'], @@ -14196,7 +14211,6 @@ return [ 'ui\window::setTitle' => ['', 'title'=>'string'], 'uksort' => ['true', '&rw_array'=>'array', 'callback'=>'callable(mixed,mixed):int'], 'umask' => ['int', 'mask='=>'?int'], -'UnderflowException::__clone' => ['void'], 'UnderflowException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'UnderflowException::__toString' => ['string'], 'UnderflowException::getCode' => ['int'], @@ -14206,7 +14220,6 @@ return [ 'UnderflowException::getPrevious' => ['?Throwable'], 'UnderflowException::getTrace' => ['list\',args?:array}>'], 'UnderflowException::getTraceAsString' => ['string'], -'UnexpectedValueException::__clone' => ['void'], 'UnexpectedValueException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'], 'UnexpectedValueException::__toString' => ['string'], 'UnexpectedValueException::getCode' => ['int'], @@ -14364,7 +14377,7 @@ return [ 'VarnishStat::getSnapshot' => ['array'], 'version_compare' => ['bool', 'version1'=>'string', 'version2'=>'string', 'operator'=>'\'<\'|\'lt\'|\'<=\'|\'le\'|\'>\'|\'gt\'|\'>=\'|\'ge\'|\'==\'|\'=\'|\'eq\'|\'!=\'|\'<>\'|\'ne\''], 'version_compare\'1' => ['int', 'version1'=>'string', 'version2'=>'string'], -'vfprintf' => ['int', 'stream'=>'resource', 'format'=>'string', 'values'=>'array'], +'vfprintf' => ['int<0, max>', 'stream'=>'resource', 'format'=>'string', 'values'=>'array'], 'virtual' => ['bool', 'uri'=>'string'], 'vpopmail_add_alias_domain' => ['bool', 'domain'=>'string', 'aliasdomain'=>'string'], 'vpopmail_add_alias_domain_ex' => ['bool', 'olddomain'=>'string', 'newdomain'=>'string'], @@ -14383,8 +14396,8 @@ return [ 'vpopmail_error' => ['string'], 'vpopmail_passwd' => ['bool', 'user'=>'string', 'domain'=>'string', 'password'=>'string', 'apop='=>'bool'], 'vpopmail_set_user_quota' => ['bool', 'user'=>'string', 'domain'=>'string', 'quota'=>'string'], -'vprintf' => ['int', 'format'=>'string', 'values'=>'array'], -'vsprintf' => ['string', 'format'=>'string', 'values'=>'array'], +'vprintf' => ['int<0, max>', 'format'=>'string', 'values'=>'array'], +'vsprintf' => ['string', 'format'=>'string', 'values'=>'array'], 'Vtiful\Kernel\Chart::__construct' => ['void', 'handle'=>'resource', 'type'=>'int'], 'Vtiful\Kernel\Chart::axisNameX' => ['Vtiful\Kernel\Chart', 'name'=>'string'], 'Vtiful\Kernel\Chart::axisNameY' => ['Vtiful\Kernel\Chart', 'name'=>'string'], @@ -14570,10 +14583,10 @@ return [ 'Worker::merge' => ['bool', 'from'=>'', 'overwrite='=>'mixed'], 'Worker::notify' => ['bool'], 'Worker::notifyOne' => ['bool'], -'Worker::offsetExists' => ['bool', 'offset'=>'mixed'], -'Worker::offsetGet' => ['mixed', 'offset'=>'mixed'], -'Worker::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], -'Worker::offsetUnset' => ['void', 'offset'=>'mixed'], +'Worker::offsetExists' => ['bool', 'offset'=>'int|string'], +'Worker::offsetGet' => ['mixed', 'offset'=>'int|string'], +'Worker::offsetSet' => ['void', 'offset'=>'int|string|null', 'value'=>'mixed'], +'Worker::offsetUnset' => ['void', 'offset'=>'int|string'], 'Worker::pop' => ['bool'], 'Worker::run' => ['void'], 'Worker::setGarbage' => ['void'], @@ -14903,10 +14916,10 @@ return [ 'Yaf\Config\Ini::get' => ['mixed', 'name='=>'mixed'], 'Yaf\Config\Ini::key' => ['int|string'], 'Yaf\Config\Ini::next' => ['void'], -'Yaf\Config\Ini::offsetExists' => ['bool', 'name'=>'mixed'], -'Yaf\Config\Ini::offsetGet' => ['mixed', 'name'=>'mixed'], -'Yaf\Config\Ini::offsetSet' => ['void', 'name'=>'mixed', 'value'=>'mixed'], -'Yaf\Config\Ini::offsetUnset' => ['void', 'name'=>'mixed'], +'Yaf\Config\Ini::offsetExists' => ['bool', 'name'=>'int|string'], +'Yaf\Config\Ini::offsetGet' => ['mixed', 'name'=>'int|string'], +'Yaf\Config\Ini::offsetSet' => ['void', 'name'=>'int|string|null', 'value'=>'mixed'], +'Yaf\Config\Ini::offsetUnset' => ['void', 'name'=>'int|string'], 'Yaf\Config\Ini::readonly' => ['bool'], 'Yaf\Config\Ini::rewind' => ['void'], 'Yaf\Config\Ini::set' => ['Yaf\Config_Abstract', 'name'=>'string', 'value'=>'mixed'], @@ -14921,10 +14934,10 @@ return [ 'Yaf\Config\Simple::get' => ['mixed', 'name='=>'mixed'], 'Yaf\Config\Simple::key' => ['int|string'], 'Yaf\Config\Simple::next' => ['void'], -'Yaf\Config\Simple::offsetExists' => ['bool', 'name'=>'mixed'], -'Yaf\Config\Simple::offsetGet' => ['mixed', 'name'=>'mixed'], -'Yaf\Config\Simple::offsetSet' => ['void', 'name'=>'mixed', 'value'=>'mixed'], -'Yaf\Config\Simple::offsetUnset' => ['void', 'name'=>'mixed'], +'Yaf\Config\Simple::offsetExists' => ['bool', 'name'=>'int|string'], +'Yaf\Config\Simple::offsetGet' => ['mixed', 'name'=>'int|string'], +'Yaf\Config\Simple::offsetSet' => ['void', 'name'=>'int|string|null', 'value'=>'mixed'], +'Yaf\Config\Simple::offsetUnset' => ['void', 'name'=>'int|string'], 'Yaf\Config\Simple::readonly' => ['bool'], 'Yaf\Config\Simple::rewind' => ['void'], 'Yaf\Config\Simple::set' => ['Yaf\Config_Abstract', 'name'=>'string', 'value'=>'mixed'], @@ -15191,10 +15204,10 @@ return [ 'Yaf\Session::has' => ['bool', 'name'=>'string'], 'Yaf\Session::key' => ['int|string'], 'Yaf\Session::next' => ['void'], -'Yaf\Session::offsetExists' => ['bool', 'name'=>'mixed'], -'Yaf\Session::offsetGet' => ['mixed', 'name'=>'mixed'], -'Yaf\Session::offsetSet' => ['void', 'name'=>'mixed', 'value'=>'mixed'], -'Yaf\Session::offsetUnset' => ['void', 'name'=>'mixed'], +'Yaf\Session::offsetExists' => ['bool', 'name'=>'int|string'], +'Yaf\Session::offsetGet' => ['mixed', 'name'=>'int|string'], +'Yaf\Session::offsetSet' => ['void', 'name'=>'int|string|null', 'value'=>'mixed'], +'Yaf\Session::offsetUnset' => ['void', 'name'=>'int|string'], 'Yaf\Session::rewind' => ['void'], 'Yaf\Session::set' => ['Yaf\Session|false', 'name'=>'string', 'value'=>'mixed'], 'Yaf\Session::start' => ['Yaf\Session'], diff --git a/vendor/vimeo/psalm/dictionaries/CallMap_83_delta.php b/vendor/vimeo/psalm/dictionaries/CallMap_83_delta.php index 2d27020d..9bcf76de 100644 --- a/vendor/vimeo/psalm/dictionaries/CallMap_83_delta.php +++ b/vendor/vimeo/psalm/dictionaries/CallMap_83_delta.php @@ -25,8 +25,124 @@ return [ 'old' => ['array{runs:int,collected:int,threshold:int,roots:int}'], 'new' => ['array{runs:int,collected:int,threshold:int,roots:int,running:bool,protected:bool,full:bool,buffer_size:int}'], ], + 'srand' => [ + 'old' => ['void', 'seed='=>'int', 'mode='=>'int'], + 'new' => ['void', 'seed='=>'?int', 'mode='=>'int'], + ], + 'mt_srand' => [ + 'old' => ['void', 'seed='=>'int', 'mode='=>'int'], + 'new' =>['void', 'seed='=>'?int', 'mode='=>'int'], + ], + 'posix_getrlimit' => [ + 'old' => ['array{"soft core": string, "hard core": string, "soft data": string, "hard data": string, "soft stack": integer, "hard stack": string, "soft totalmem": string, "hard totalmem": string, "soft rss": string, "hard rss": string, "soft maxproc": integer, "hard maxproc": integer, "soft memlock": integer, "hard memlock": integer, "soft cpu": string, "hard cpu": string, "soft filesize": string, "hard filesize": string, "soft openfiles": integer, "hard openfiles": integer}|false'], + 'new' => ['array{"soft core": string, "hard core": string, "soft data": string, "hard data": string, "soft stack": integer, "hard stack": string, "soft totalmem": string, "hard totalmem": string, "soft rss": string, "hard rss": string, "soft maxproc": integer, "hard maxproc": integer, "soft memlock": integer, "hard memlock": integer, "soft cpu": string, "hard cpu": string, "soft filesize": string, "hard filesize": string, "soft openfiles": integer, "hard openfiles": integer}|false', 'resource=' => '?int'], + ], + 'natcasesort' => [ + 'old' => ['bool', '&rw_array'=>'array'], + 'new' => ['true', '&rw_array'=>'array'], + ], + 'natsort' => [ + 'old' => ['bool', '&rw_array'=>'array'], + 'new' => ['true', '&rw_array'=>'array'], + ], + 'rsort' => [ + 'old' => ['bool', '&rw_array'=>'array', 'flags='=>'int'], + 'new' => ['true', '&rw_array'=>'array', 'flags='=>'int'], + ], + 'hash_pbkdf2' => [ + 'old' => ['non-empty-string', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'binary='=>'bool'], + 'new' => ['non-empty-string', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'binary='=>'bool', 'options=' => 'array'], + ], + 'imap_setflag_full' => [ + 'old' => ['bool', 'imap'=>'IMAP\Connection', 'sequence'=>'string', 'flag'=>'string', 'options='=>'int'], + 'new' => ['true', 'imap'=>'IMAP\Connection', 'sequence'=>'string', 'flag'=>'string', 'options='=>'int'], + ], + 'imap_expunge' => [ + 'old' => ['bool', 'imap'=>'IMAP\Connection'], + 'new' => ['true', 'imap'=>'IMAP\Connection'], + ], + 'imap_gc' => [ + 'old' => ['bool', 'imap'=>'IMAP\Connection', 'flags'=>'int'], + 'new' => ['true', 'imap'=>'IMAP\Connection', 'flags'=>'int'], + ], + 'imap_undelete' => [ + 'old' => ['bool', 'imap'=>'IMAP\Connection', 'message_nums'=>'string', 'flags='=>'int'], + 'new' => ['true', 'imap'=>'IMAP\Connection', 'message_nums'=>'string', 'flags='=>'int'], + ], + 'imap_delete' => [ + 'old' => ['bool', 'imap'=>'IMAP\Connection', 'message_nums'=>'string', 'flags='=>'int'], + 'new' => ['true', 'imap'=>'IMAP\Connection', 'message_nums'=>'string', 'flags='=>'int'], + ], + 'imap_clearflag_full' => [ + 'old' => ['bool', 'imap'=>'IMAP\Connection', 'sequence'=>'string', 'flag'=>'string', 'options='=>'int'], + 'new' => ['true', 'imap'=>'IMAP\Connection', 'sequence'=>'string', 'flag'=>'string', 'options='=>'int'], + ], + 'imap_close' => [ + 'old' => ['bool', 'imap'=>'IMAP\Connection', 'flags='=>'int'], + 'new' => ['true', 'imap'=>'IMAP\Connection', 'flags='=>'int'], + ], + 'intlcal_clear' => [ + 'old' => ['bool', 'calendar'=>'IntlCalendar', 'field='=>'?int'], + 'new' => ['true', 'calendar'=>'IntlCalendar', 'field='=>'?int'], + ], + 'intlcal_set_lenient' => [ + 'old' => ['bool', 'calendar'=>'IntlCalendar', 'lenient'=>'bool'], + 'new' => ['true', 'calendar'=>'IntlCalendar', 'lenient'=>'bool'], + ], + 'intlcal_set_first_day_of_week' => [ + 'old' => ['bool', 'calendar'=>'IntlCalendar', 'dayOfWeek'=>'int'], + 'new' => ['true', 'calendar'=>'IntlCalendar', 'dayOfWeek'=>'int'], + ], + 'datefmt_set_timezone' => [ + 'old' => ['false|null', 'formatter'=>'IntlDateFormatter', 'timezone'=>'IntlTimeZone|DateTimeZone|string|null'], + 'new' => ['bool', 'formatter'=>'IntlDateFormatter', 'timezone'=>'IntlTimeZone|DateTimeZone|string|null'], + ], + 'IntlRuleBasedBreakIterator::setText' => [ + 'old' => ['?bool', 'text'=>'string'], + 'new' => ['bool', 'text'=>'string'], + ], + 'IntlCodePointBreakIterator::setText' => [ + 'old' => ['?bool', 'text'=>'string'], + 'new' => ['bool', 'text'=>'string'], + ], + 'IntlDateFormatter::setTimeZone' => [ + 'old' => ['null|false', 'timezone'=>'IntlTimeZone|DateTimeZone|string|null'], + 'new' => ['bool', 'timezone'=>'IntlTimeZone|DateTimeZone|string|null'], + ], + 'IntlChar::enumCharNames' => [ + 'old' => ['?bool', 'start'=>'string|int', 'end'=>'string|int', 'callback'=>'callable(int,int,int):void', 'type='=>'int'], + 'new' => ['bool', 'start'=>'string|int', 'end'=>'string|int', 'callback'=>'callable(int,int,int):void', 'type='=>'int'], + ], + 'IntlBreakIterator::setText' => [ + 'old' => ['?bool', 'text'=>'string'], + 'new' => ['bool', 'text'=>'string'], + ], ], 'removed' => [ + 'OutOfBoundsException::__clone' => ['void'], + 'ArgumentCountError::__clone' => ['void'], + 'ArithmeticError::__clone' => ['void'], + 'BadFunctionCallException::__clone' => ['void'], + 'BadMethodCallException::__clone' => ['void'], + 'ClosedGeneratorException::__clone' => ['void'], + 'DomainException::__clone' => ['void'], + 'ErrorException::__clone' => ['void'], + 'IntlException::__clone' => ['void'], + 'InvalidArgumentException::__clone' => ['void'], + 'JsonException::__clone' => ['void'], + 'LengthException::__clone' => ['void'], + 'LogicException::__clone' => ['void'], + 'OutOfRangeException::__clone' => ['void'], + 'OverflowException::__clone' => ['void'], + 'ParseError::__clone' => ['void'], + 'RangeException::__clone' => ['void'], + 'ReflectionNamedType::__clone' => ['void'], + 'ReflectionObject::__clone' => ['void'], + 'RuntimeException::__clone' => ['void'], + 'TypeError::__clone' => ['void'], + 'UnderflowException::__clone' => ['void'], + 'UnexpectedValueException::__clone' => ['void'], + 'IntlCodePointBreakIterator::__construct' => ['void'], ], ]; diff --git a/vendor/vimeo/psalm/dictionaries/CallMap_historical.php b/vendor/vimeo/psalm/dictionaries/CallMap_historical.php index a88bab36..d20efff9 100644 --- a/vendor/vimeo/psalm/dictionaries/CallMap_historical.php +++ b/vendor/vimeo/psalm/dictionaries/CallMap_historical.php @@ -209,10 +209,10 @@ return [ 'ArithmeticError::getPrevious' => ['?Throwable'], 'ArithmeticError::getTrace' => ['list\',args?:array}>'], 'ArithmeticError::getTraceAsString' => ['string'], - 'ArrayAccess::offsetExists' => ['bool', 'offset'=>'mixed'], - 'ArrayAccess::offsetGet' => ['mixed', 'offset'=>'mixed'], - 'ArrayAccess::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], - 'ArrayAccess::offsetUnset' => ['void', 'offset'=>'mixed'], + 'ArrayAccess::offsetExists' => ['bool', 'offset'=>'int|string'], + 'ArrayAccess::offsetGet' => ['mixed', 'offset'=>'int|string'], + 'ArrayAccess::offsetSet' => ['void', 'offset'=>'int|string|null', 'value'=>'mixed'], + 'ArrayAccess::offsetUnset' => ['void', 'offset'=>'int|string'], 'ArrayIterator::__construct' => ['void', 'array='=>'array|object', 'flags='=>'int'], 'ArrayIterator::append' => ['void', 'value'=>'mixed'], 'ArrayIterator::asort' => ['true', 'flags='=>'int'], @@ -227,7 +227,7 @@ return [ 'ArrayIterator::next' => ['void'], 'ArrayIterator::offsetExists' => ['bool', 'key'=>'string|int'], 'ArrayIterator::offsetGet' => ['mixed', 'key'=>'string|int'], - 'ArrayIterator::offsetSet' => ['void', 'key'=>'string|int', 'value'=>'mixed'], + 'ArrayIterator::offsetSet' => ['void', 'key'=>'string|int|null', 'value'=>'mixed'], 'ArrayIterator::offsetUnset' => ['void', 'key'=>'string|int'], 'ArrayIterator::rewind' => ['void'], 'ArrayIterator::seek' => ['void', 'offset'=>'int'], @@ -251,7 +251,7 @@ return [ 'ArrayObject::natsort' => ['true'], 'ArrayObject::offsetExists' => ['bool', 'key'=>'int|string'], 'ArrayObject::offsetGet' => ['mixed|null', 'key'=>'int|string'], - 'ArrayObject::offsetSet' => ['void', 'key'=>'int|string', 'value'=>'mixed'], + 'ArrayObject::offsetSet' => ['void', 'key'=>'int|string|null', 'value'=>'mixed'], 'ArrayObject::offsetUnset' => ['void', 'key'=>'int|string'], 'ArrayObject::serialize' => ['string'], 'ArrayObject::setFlags' => ['void', 'flags'=>'int'], @@ -2236,10 +2236,10 @@ return [ 'HttpQueryString::getObject' => ['', 'name'=>'', 'defval'=>'', 'delete'=>''], 'HttpQueryString::getString' => ['', 'name'=>'', 'defval'=>'', 'delete'=>''], 'HttpQueryString::mod' => ['HttpQueryString', 'params'=>'mixed'], - 'HttpQueryString::offsetExists' => ['bool', 'offset'=>'mixed'], - 'HttpQueryString::offsetGet' => ['mixed', 'offset'=>'mixed'], - 'HttpQueryString::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], - 'HttpQueryString::offsetUnset' => ['void', 'offset'=>'mixed'], + 'HttpQueryString::offsetExists' => ['bool', 'offset'=>'int|string'], + 'HttpQueryString::offsetGet' => ['mixed', 'offset'=>'int|string'], + 'HttpQueryString::offsetSet' => ['void', 'offset'=>'int|string|null', 'value'=>'mixed'], + 'HttpQueryString::offsetUnset' => ['void', 'offset'=>'int|string'], 'HttpQueryString::serialize' => ['string'], 'HttpQueryString::set' => ['string', 'params'=>'mixed'], 'HttpQueryString::singleton' => ['HttpQueryString', 'global='=>'bool'], @@ -3289,10 +3289,10 @@ return [ 'Judy::memoryUsage' => ['int'], 'Judy::next' => ['mixed', 'index'=>'mixed'], 'Judy::nextEmpty' => ['mixed', 'index'=>'mixed'], - 'Judy::offsetExists' => ['bool', 'offset'=>'mixed'], - 'Judy::offsetGet' => ['mixed', 'offset'=>'mixed'], - 'Judy::offsetSet' => ['bool', 'offset'=>'mixed', 'value'=>'mixed'], - 'Judy::offsetUnset' => ['bool', 'offset'=>'mixed'], + 'Judy::offsetExists' => ['bool', 'offset'=>'int|string'], + 'Judy::offsetGet' => ['mixed', 'offset'=>'int|string'], + 'Judy::offsetSet' => ['bool', 'offset'=>'int|string|null', 'value'=>'mixed'], + 'Judy::offsetUnset' => ['bool', 'offset'=>'int|string'], 'Judy::prev' => ['mixed', 'index'=>'mixed'], 'Judy::prevEmpty' => ['mixed', 'index'=>'mixed'], 'Judy::size' => ['int'], @@ -3731,6 +3731,14 @@ return [ 'MongoDBRef::create' => ['array', 'collection'=>'string', 'id'=>'mixed', 'database='=>'string'], 'MongoDBRef::get' => ['?array', 'db'=>'MongoDB', 'ref'=>'array'], 'MongoDBRef::isRef' => ['bool', 'ref'=>'mixed'], + 'MongoDB\BSON\fromJSON' => ['string', 'json' => 'string'], + 'MongoDB\BSON\fromPHP' => ['string', 'value' => 'object|array'], + 'MongoDB\BSON\toCanonicalExtendedJSON' => ['string', 'bson' => 'string'], + 'MongoDB\BSON\toJSON' => ['string', 'bson' => 'string'], + 'MongoDB\BSON\toPHP' => ['object|array', 'bson' => 'string', 'typemap=' => '?array'], + 'MongoDB\BSON\toRelaxedExtendedJSON' => ['string', 'bson' => 'string'], + 'MongoDB\Driver\Monitoring\addSubscriber' => ['void', 'subscriber' => 'MongoDB\Driver\Monitoring\Subscriber'], + 'MongoDB\Driver\Monitoring\removeSubscriber' => ['void', 'subscriber' => 'MongoDB\Driver\Monitoring\Subscriber'], 'MongoDB\BSON\Binary::__construct' => ['void', 'data' => 'string', 'type=' => 'int'], 'MongoDB\BSON\Binary::getData' => ['string'], 'MongoDB\BSON\Binary::getType' => ['int'], @@ -3751,10 +3759,28 @@ return [ 'MongoDB\BSON\Decimal128::unserialize' => ['void', 'serialized' => 'string'], 'MongoDB\BSON\Decimal128::jsonSerialize' => ['mixed'], 'MongoDB\BSON\Decimal128Interface::__toString' => ['string'], + 'MongoDB\BSON\Document::fromBSON' => ['MongoDB\BSON\Document', 'bson' => 'string'], + 'MongoDB\BSON\Document::fromJSON' => ['MongoDB\BSON\Document', 'json' => 'string'], + 'MongoDB\BSON\Document::fromPHP' => ['MongoDB\BSON\Document', 'value' => 'object|array'], + 'MongoDB\BSON\Document::get' => ['mixed', 'key' => 'string'], + 'MongoDB\BSON\Document::getIterator' => ['MongoDB\BSON\Iterator'], + 'MongoDB\BSON\Document::has' => ['bool', 'key' => 'string'], + 'MongoDB\BSON\Document::toPHP' => ['object|array', 'typeMap=' => '?array'], + 'MongoDB\BSON\Document::toCanonicalExtendedJSON' => ['string'], + 'MongoDB\BSON\Document::toRelaxedExtendedJSON' => ['string'], + 'MongoDB\BSON\Document::__toString' => ['string'], + 'MongoDB\BSON\Document::serialize' => ['string'], + 'MongoDB\BSON\Document::unserialize' => ['void', 'serialized' => 'string'], + 'MongoDB\BSON\Int64::__construct' => ['void', 'value' => 'string|int'], 'MongoDB\BSON\Int64::__toString' => ['string'], 'MongoDB\BSON\Int64::serialize' => ['string'], 'MongoDB\BSON\Int64::unserialize' => ['void', 'serialized' => 'string'], 'MongoDB\BSON\Int64::jsonSerialize' => ['mixed'], + 'MongoDB\BSON\Iterator::current' => ['mixed'], + 'MongoDB\BSON\Iterator::key' => ['string|int'], + 'MongoDB\BSON\Iterator::next' => ['void'], + 'MongoDB\BSON\Iterator::rewind' => ['void'], + 'MongoDB\BSON\Iterator::valid' => ['bool'], 'MongoDB\BSON\Javascript::__construct' => ['void', 'code' => 'string', 'scope=' => 'object|array|null'], 'MongoDB\BSON\Javascript::getCode' => ['string'], 'MongoDB\BSON\Javascript::getScope' => ['?object'], @@ -3779,6 +3805,14 @@ return [ 'MongoDB\BSON\ObjectId::jsonSerialize' => ['mixed'], 'MongoDB\BSON\ObjectIdInterface::getTimestamp' => ['int'], 'MongoDB\BSON\ObjectIdInterface::__toString' => ['string'], + 'MongoDB\BSON\PackedArray::fromPHP' => ['MongoDB\BSON\PackedArray', 'value' => 'array'], + 'MongoDB\BSON\PackedArray::get' => ['mixed', 'index' => 'int'], + 'MongoDB\BSON\PackedArray::getIterator' => ['MongoDB\BSON\Iterator'], + 'MongoDB\BSON\PackedArray::has' => ['bool', 'index' => 'int'], + 'MongoDB\BSON\PackedArray::toPHP' => ['object|array', 'typeMap=' => '?array'], + 'MongoDB\BSON\PackedArray::__toString' => ['string'], + 'MongoDB\BSON\PackedArray::serialize' => ['string'], + 'MongoDB\BSON\PackedArray::unserialize' => ['void', 'serialized' => 'string'], 'MongoDB\BSON\Regex::__construct' => ['void', 'pattern' => 'string', 'flags=' => 'string'], 'MongoDB\BSON\Regex::getPattern' => ['string'], 'MongoDB\BSON\Regex::getFlags' => ['string'], @@ -3828,6 +3862,7 @@ return [ 'MongoDB\Driver\ClientEncryption::decrypt' => ['mixed', 'value' => 'MongoDB\BSON\Binary'], 'MongoDB\Driver\ClientEncryption::deleteKey' => ['object', 'keyId' => 'MongoDB\BSON\Binary'], 'MongoDB\Driver\ClientEncryption::encrypt' => ['MongoDB\BSON\Binary', 'value' => 'mixed', 'options=' => '?array'], + 'MongoDB\Driver\ClientEncryption::encryptExpression' => ['object', 'expr' => 'object|array', 'options=' => '?array'], 'MongoDB\Driver\ClientEncryption::getKey' => ['?object', 'keyId' => 'MongoDB\BSON\Binary'], 'MongoDB\Driver\ClientEncryption::getKeyByAltName' => ['?object', 'keyAltName' => 'string'], 'MongoDB\Driver\ClientEncryption::getKeys' => ['MongoDB\Driver\Cursor'], @@ -4039,6 +4074,7 @@ return [ 'MongoDB\Driver\WriteResult::getUpsertedIds' => ['array'], 'MongoDB\Driver\WriteResult::getWriteConcernError' => ['?MongoDB\Driver\WriteConcernError'], 'MongoDB\Driver\WriteResult::getWriteErrors' => ['array'], + 'MongoDB\Driver\WriteResult::getErrorReplies' => ['array'], 'MongoDB\Driver\WriteResult::isAcknowledged' => ['bool'], 'MongoDate::__construct' => ['void', 'second='=>'int', 'usecond='=>'int'], 'MongoDate::__toString' => ['string'], @@ -5137,7 +5173,7 @@ return [ 'RecursiveArrayIterator::next' => ['void'], 'RecursiveArrayIterator::offsetExists' => ['bool', 'key'=>'string|int'], 'RecursiveArrayIterator::offsetGet' => ['mixed', 'key'=>'string|int'], - 'RecursiveArrayIterator::offsetSet' => ['void', 'key'=>'string|int', 'value'=>'string'], + 'RecursiveArrayIterator::offsetSet' => ['void', 'key'=>'string|int|null', 'value'=>'string'], 'RecursiveArrayIterator::offsetUnset' => ['void', 'key'=>'string|int'], 'RecursiveArrayIterator::rewind' => ['void'], 'RecursiveArrayIterator::seek' => ['void', 'offset'=>'int'], @@ -6641,7 +6677,7 @@ return [ 'SimpleXMLElement::getNamespaces' => ['array', 'recursive='=>'bool'], 'SimpleXMLElement::offsetExists' => ['bool', 'offset'=>'int|string'], 'SimpleXMLElement::offsetGet' => ['SimpleXMLElement', 'offset'=>'int|string'], - 'SimpleXMLElement::offsetSet' => ['void', 'offset'=>'int|string', 'value'=>'mixed'], + 'SimpleXMLElement::offsetSet' => ['void', 'offset'=>'int|string|null', 'value'=>'mixed'], 'SimpleXMLElement::offsetUnset' => ['void', 'offset'=>'int|string'], 'SimpleXMLElement::registerXPathNamespace' => ['bool', 'prefix'=>'string', 'namespace'=>'string'], 'SimpleXMLElement::saveXML' => ['string|bool', 'filename='=>'string'], @@ -7871,10 +7907,10 @@ return [ 'Thread::merge' => ['bool', 'from'=>'', 'overwrite='=>'mixed'], 'Thread::notify' => ['bool'], 'Thread::notifyOne' => ['bool'], - 'Thread::offsetExists' => ['bool', 'offset'=>'mixed'], - 'Thread::offsetGet' => ['mixed', 'offset'=>'mixed'], - 'Thread::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], - 'Thread::offsetUnset' => ['void', 'offset'=>'mixed'], + 'Thread::offsetExists' => ['bool', 'offset'=>'int|string'], + 'Thread::offsetGet' => ['mixed', 'offset'=>'int|string'], + 'Thread::offsetSet' => ['void', 'offset'=>'int|string|null', 'value'=>'mixed'], + 'Thread::offsetUnset' => ['void', 'offset'=>'int|string'], 'Thread::pop' => ['bool'], 'Thread::run' => ['void'], 'Thread::setGarbage' => ['void'], @@ -7900,10 +7936,10 @@ return [ 'Threaded::merge' => ['bool', 'from'=>'mixed', 'overwrite='=>'bool'], 'Threaded::notify' => ['bool'], 'Threaded::notifyOne' => ['bool'], - 'Threaded::offsetExists' => ['bool', 'offset'=>'mixed'], - 'Threaded::offsetGet' => ['mixed', 'offset'=>'mixed'], - 'Threaded::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], - 'Threaded::offsetUnset' => ['void', 'offset'=>'mixed'], + 'Threaded::offsetExists' => ['bool', 'offset'=>'int|string'], + 'Threaded::offsetGet' => ['mixed', 'offset'=>'int|string'], + 'Threaded::offsetSet' => ['void', 'offset'=>'int|string|null', 'value'=>'mixed'], + 'Threaded::offsetUnset' => ['void', 'offset'=>'int|string'], 'Threaded::pop' => ['bool'], 'Threaded::run' => ['void'], 'Threaded::setGarbage' => ['void'], @@ -8208,10 +8244,10 @@ return [ 'Worker::merge' => ['bool', 'from'=>'', 'overwrite='=>'mixed'], 'Worker::notify' => ['bool'], 'Worker::notifyOne' => ['bool'], - 'Worker::offsetExists' => ['bool', 'offset'=>'mixed'], - 'Worker::offsetGet' => ['mixed', 'offset'=>'mixed'], - 'Worker::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], - 'Worker::offsetUnset' => ['void', 'offset'=>'mixed'], + 'Worker::offsetExists' => ['bool', 'offset'=>'int|string'], + 'Worker::offsetGet' => ['mixed', 'offset'=>'int|string'], + 'Worker::offsetSet' => ['void', 'offset'=>'int|string|null', 'value'=>'mixed'], + 'Worker::offsetUnset' => ['void', 'offset'=>'int|string'], 'Worker::pop' => ['bool'], 'Worker::run' => ['void'], 'Worker::setGarbage' => ['void'], @@ -8368,10 +8404,10 @@ return [ 'Yaf\Config\Ini::get' => ['mixed', 'name='=>'mixed'], 'Yaf\Config\Ini::key' => ['int|string'], 'Yaf\Config\Ini::next' => ['void'], - 'Yaf\Config\Ini::offsetExists' => ['bool', 'name'=>'mixed'], - 'Yaf\Config\Ini::offsetGet' => ['mixed', 'name'=>'mixed'], - 'Yaf\Config\Ini::offsetSet' => ['void', 'name'=>'mixed', 'value'=>'mixed'], - 'Yaf\Config\Ini::offsetUnset' => ['void', 'name'=>'mixed'], + 'Yaf\Config\Ini::offsetExists' => ['bool', 'name'=>'int|string'], + 'Yaf\Config\Ini::offsetGet' => ['mixed', 'name'=>'int|string'], + 'Yaf\Config\Ini::offsetSet' => ['void', 'name'=>'int|string|null', 'value'=>'mixed'], + 'Yaf\Config\Ini::offsetUnset' => ['void', 'name'=>'int|string'], 'Yaf\Config\Ini::readonly' => ['bool'], 'Yaf\Config\Ini::rewind' => ['void'], 'Yaf\Config\Ini::set' => ['Yaf\Config_Abstract', 'name'=>'string', 'value'=>'mixed'], @@ -8386,10 +8422,10 @@ return [ 'Yaf\Config\Simple::get' => ['mixed', 'name='=>'mixed'], 'Yaf\Config\Simple::key' => ['int|string'], 'Yaf\Config\Simple::next' => ['void'], - 'Yaf\Config\Simple::offsetExists' => ['bool', 'name'=>'mixed'], - 'Yaf\Config\Simple::offsetGet' => ['mixed', 'name'=>'mixed'], - 'Yaf\Config\Simple::offsetSet' => ['void', 'name'=>'mixed', 'value'=>'mixed'], - 'Yaf\Config\Simple::offsetUnset' => ['void', 'name'=>'mixed'], + 'Yaf\Config\Simple::offsetExists' => ['bool', 'name'=>'int|string'], + 'Yaf\Config\Simple::offsetGet' => ['mixed', 'name'=>'int|string'], + 'Yaf\Config\Simple::offsetSet' => ['void', 'name'=>'int|string|null', 'value'=>'mixed'], + 'Yaf\Config\Simple::offsetUnset' => ['void', 'name'=>'int|string'], 'Yaf\Config\Simple::readonly' => ['bool'], 'Yaf\Config\Simple::rewind' => ['void'], 'Yaf\Config\Simple::set' => ['Yaf\Config_Abstract', 'name'=>'string', 'value'=>'mixed'], @@ -8656,10 +8692,10 @@ return [ 'Yaf\Session::has' => ['bool', 'name'=>'string'], 'Yaf\Session::key' => ['int|string'], 'Yaf\Session::next' => ['void'], - 'Yaf\Session::offsetExists' => ['bool', 'name'=>'mixed'], - 'Yaf\Session::offsetGet' => ['mixed', 'name'=>'mixed'], - 'Yaf\Session::offsetSet' => ['void', 'name'=>'mixed', 'value'=>'mixed'], - 'Yaf\Session::offsetUnset' => ['void', 'name'=>'mixed'], + 'Yaf\Session::offsetExists' => ['bool', 'name'=>'int|string'], + 'Yaf\Session::offsetGet' => ['mixed', 'name'=>'int|string'], + 'Yaf\Session::offsetSet' => ['void', 'name'=>'int|string|null', 'value'=>'mixed'], + 'Yaf\Session::offsetUnset' => ['void', 'name'=>'int|string'], 'Yaf\Session::rewind' => ['void'], 'Yaf\Session::set' => ['Yaf\Session|false', 'name'=>'string', 'value'=>'mixed'], 'Yaf\Session::start' => ['Yaf\Session'], @@ -9404,7 +9440,8 @@ return [ 'atan' => ['float', 'num'=>'float'], 'atan2' => ['float', 'y'=>'float', 'x'=>'float'], 'atanh' => ['float', 'num'=>'float'], - 'base64_decode' => ['string|false', 'string'=>'string', 'strict='=>'bool'], + 'base64_decode' => ['string', 'string'=>'string', 'strict='=>'false'], + 'base64_decode\'1' => ['string|false', 'string'=>'string', 'strict='=>'true'], 'base64_encode' => ['string', 'string'=>'string'], 'base_convert' => ['string', 'num'=>'string', 'from_base'=>'int', 'to_base'=>'int'], 'basename' => ['string', 'path'=>'string', 'suffix='=>'string'], @@ -9966,7 +10003,7 @@ return [ 'dcgettext' => ['string', 'domain'=>'string', 'message'=>'string', 'category'=>'int'], 'dcngettext' => ['string', 'domain'=>'string', 'singular'=>'string', 'plural'=>'string', 'count'=>'int', 'category'=>'int'], 'deaggregate' => ['', 'object'=>'object', 'class_name='=>'string'], - 'debug_backtrace' => ['list', 'options='=>'int', 'limit='=>'int'], + 'debug_backtrace' => ['list', 'options='=>'int', 'limit='=>'int'], 'debug_print_backtrace' => ['void', 'options='=>'int', 'limit='=>'int'], 'debug_zval_dump' => ['void', 'value'=>'mixed', '...values='=>'mixed'], 'debugger_connect' => [''], @@ -9994,7 +10031,7 @@ return [ 'dio_truncate' => ['bool', 'fd'=>'resource', 'offset'=>'int'], 'dio_write' => ['int', 'fd'=>'resource', 'data'=>'string', 'length='=>'int'], 'dir' => ['Directory|false', 'directory'=>'string', 'context='=>'resource'], - 'dirname' => ['string', 'path'=>'string', 'levels='=>'int'], + 'dirname' => ['string', 'path'=>'string', 'levels='=>'int<1, max>'], 'disk_free_space' => ['float|false', 'directory'=>'string'], 'disk_total_space' => ['float|false', 'directory'=>'string'], 'diskfreespace' => ['float|false', 'directory'=>'string'], @@ -10708,8 +10745,8 @@ return [ 'gethostbyname' => ['string', 'hostname'=>'string'], 'gethostbynamel' => ['list|false', 'hostname'=>'string'], 'gethostname' => ['string|false'], - 'getimagesize' => ['array|false', 'filename'=>'string', '&w_image_info='=>'array'], - 'getimagesizefromstring' => ['array|false', 'string'=>'string', '&w_image_info='=>'array'], + 'getimagesize' => ['array{0:int, 1: int, 2: int, 3: string, mime: string, channels?: 3|4, bits?: int}|false', 'filename'=>'string', '&w_image_info='=>'array'], + 'getimagesizefromstring' => ['array{0:int, 1: int, 2: int, 3: string, mime: string, channels?: 3|4, bits?: int}|false', 'string'=>'string', '&w_image_info='=>'array'], 'getlastmod' => ['int|false'], 'getmxrr' => ['bool', 'hostname'=>'string', '&w_hosts'=>'array', '&w_weights='=>'array'], 'getmygid' => ['int|false'], @@ -10727,7 +10764,7 @@ return [ 'gettimeofday' => ['array'], 'gettimeofday\'1' => ['float', 'as_float='=>'true'], 'gettype' => ['string', 'value'=>'mixed'], - 'glob' => ['list|false', 'pattern'=>'non-empty-string', 'flags='=>'int<1, max>'], + 'glob' => ['false|list{0?:string, ...}', 'pattern'=>'string', 'flags='=>'int<0, max>'], 'gmdate' => ['string', 'format'=>'string', 'timestamp='=>'int'], 'gmmktime' => ['int|false', 'hour='=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'], 'gmp_abs' => ['GMP', 'num'=>'GMP|string|int'], @@ -11306,10 +11343,10 @@ return [ 'http\Message\Parser::stream' => ['int', 'stream'=>'resource', 'flags'=>'int', '&message'=>'http\Message'], 'http\Params::__construct' => ['void', 'params='=>'mixed', 'param_sep='=>'mixed', 'arg_sep='=>'mixed', 'val_sep='=>'mixed', 'flags='=>'mixed'], 'http\Params::__toString' => ['string'], - 'http\Params::offsetExists' => ['bool', 'name'=>'mixed'], - 'http\Params::offsetGet' => ['mixed', 'name'=>'mixed'], - 'http\Params::offsetSet' => ['void', 'name'=>'mixed', 'value'=>'mixed'], - 'http\Params::offsetUnset' => ['void', 'name'=>'mixed'], + 'http\Params::offsetExists' => ['bool', 'name'=>'int|string'], + 'http\Params::offsetGet' => ['mixed', 'name'=>'int|string'], + 'http\Params::offsetSet' => ['void', 'name'=>'int|string|null', 'value'=>'mixed'], + 'http\Params::offsetUnset' => ['void', 'name'=>'int|string'], 'http\Params::toArray' => ['array'], 'http\Params::toString' => ['string'], 'http\QueryString::__construct' => ['void', 'querystring'=>'string'], @@ -11324,10 +11361,10 @@ return [ 'http\QueryString::getObject' => ['object|mixed', 'name'=>'string', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\QueryString::getString' => ['string|mixed', 'name'=>'string', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\QueryString::mod' => ['http\QueryString', 'params='=>'mixed'], - 'http\QueryString::offsetExists' => ['bool', 'offset'=>'mixed'], - 'http\QueryString::offsetGet' => ['mixed|null', 'offset'=>'mixed'], - 'http\QueryString::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], - 'http\QueryString::offsetUnset' => ['void', 'offset'=>'mixed'], + 'http\QueryString::offsetExists' => ['bool', 'offset'=>'int|string'], + 'http\QueryString::offsetGet' => ['mixed|null', 'offset'=>'int|string'], + 'http\QueryString::offsetSet' => ['void', 'offset'=>'int|string|null', 'value'=>'mixed'], + 'http\QueryString::offsetUnset' => ['void', 'offset'=>'int|string'], 'http\QueryString::serialize' => ['string'], 'http\QueryString::set' => ['http\QueryString', 'params'=>'mixed'], 'http\QueryString::toArray' => ['array'], @@ -13554,7 +13591,7 @@ return [ 'print' => ['int', 'arg'=>'string'], 'print_r' => ['string', 'value'=>'mixed'], 'print_r\'1' => ['true', 'value'=>'mixed', 'return='=>'bool'], - 'printf' => ['int', 'format'=>'string', '...values='=>'string|int|float'], + 'printf' => ['int<0, max>', 'format'=>'string', '...values='=>'string|int|float'], 'proc_close' => ['int', 'process'=>'resource'], 'proc_get_status' => ['array{command: string, pid: int, running: bool, signaled: bool, stopped: bool, exitcode: int, termsig: int, stopsig: int}|false', 'process'=>'resource'], 'proc_nice' => ['bool', 'priority'=>'int'], @@ -15317,7 +15354,7 @@ return [ 'variant_xor' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'version_compare' => ['bool', 'version1'=>'string', 'version2'=>'string', 'operator'=>'\'<\'|\'lt\'|\'<=\'|\'le\'|\'>\'|\'gt\'|\'>=\'|\'ge\'|\'==\'|\'=\'|\'eq\'|\'!=\'|\'<>\'|\'ne\''], 'version_compare\'1' => ['int', 'version1'=>'string', 'version2'=>'string'], - 'vfprintf' => ['int', 'stream'=>'resource', 'format'=>'string', 'values'=>'array'], + 'vfprintf' => ['int<0, max>', 'stream'=>'resource', 'format'=>'string', 'values'=>'array'], 'virtual' => ['bool', 'uri'=>'string'], 'vpopmail_add_alias_domain' => ['bool', 'domain'=>'string', 'aliasdomain'=>'string'], 'vpopmail_add_alias_domain_ex' => ['bool', 'olddomain'=>'string', 'newdomain'=>'string'], @@ -15336,8 +15373,8 @@ return [ 'vpopmail_error' => ['string'], 'vpopmail_passwd' => ['bool', 'user'=>'string', 'domain'=>'string', 'password'=>'string', 'apop='=>'bool'], 'vpopmail_set_user_quota' => ['bool', 'user'=>'string', 'domain'=>'string', 'quota'=>'string'], - 'vprintf' => ['int', 'format'=>'string', 'values'=>'array'], - 'vsprintf' => ['string', 'format'=>'string', 'values'=>'array'], + 'vprintf' => ['int<0, max>', 'format'=>'string', 'values'=>'array'], + 'vsprintf' => ['string', 'format'=>'string', 'values'=>'array'], 'w32api_deftype' => ['bool', 'typename'=>'string', 'member1_type'=>'string', 'member1_name'=>'string', '...args='=>'string'], 'w32api_init_dtype' => ['resource', 'typename'=>'string', 'value'=>'', '...args='=>''], 'w32api_invoke_function' => ['', 'funcname'=>'string', 'argument'=>'', '...args='=>''], diff --git a/vendor/vimeo/psalm/docs/annotating_code/type_syntax/array_types.md b/vendor/vimeo/psalm/docs/annotating_code/type_syntax/array_types.md index 7a3c00f9..2846a9a2 100644 --- a/vendor/vimeo/psalm/docs/annotating_code/type_syntax/array_types.md +++ b/vendor/vimeo/psalm/docs/annotating_code/type_syntax/array_types.md @@ -126,6 +126,19 @@ Optional keys can be denoted by a trailing `?`, e.g.: /** @return array{optional?: string, bar: int} */ ``` +You can use "one-line" comments (similar to PHP), e.g: + +```php +/** @return array { // Array with comments. + * // Comments can be placed on their own line. + * foo: string, // An array key description. + * bar: array {, // Another array key description. + * 'foo//bar': string, // Array key with "//" in it's name. + * }, + * } + */ +``` + Tip: if you find yourself copying the same complex array shape over and over again to avoid `InvalidArgument` issues, try using [type aliases](utility_types.md#type-aliases), instead. ### Validating array shapes diff --git a/vendor/vimeo/psalm/docs/annotating_code/type_syntax/atomic_types.md b/vendor/vimeo/psalm/docs/annotating_code/type_syntax/atomic_types.md index 612cf9f7..6a710588 100644 --- a/vendor/vimeo/psalm/docs/annotating_code/type_syntax/atomic_types.md +++ b/vendor/vimeo/psalm/docs/annotating_code/type_syntax/atomic_types.md @@ -46,7 +46,7 @@ Atomic types are the basic building block of all type information used in Psalm. * [`key-of`](utility_types.md#key-oft) * [`value-of`](utility_types.md#value-oft) * [`properties-of`](utility_types.md#properties-oft) - * [`class-string-map`](utility_types.md#class-string-mapt-as-foo-t) + * [`class-string-map`](utility_types.md#class-string-mapt-of-foo-t) * [`T[K]`](utility_types.md#tk) * [Type aliases](utility_types.md#type-aliases) * [Variable templates](utility_types.md#variable-templates) diff --git a/vendor/vimeo/psalm/docs/running_psalm/configuration.md b/vendor/vimeo/psalm/docs/running_psalm/configuration.md index 43f42c3b..f4976aaa 100644 --- a/vendor/vimeo/psalm/docs/running_psalm/configuration.md +++ b/vendor/vimeo/psalm/docs/running_psalm/configuration.md @@ -414,6 +414,14 @@ Whether or not to allow `require`/`include` calls in your PHP. Defaults to `true ``` Allows you to hard-code a serializer for Psalm to use when caching data. By default, Psalm uses `ext-igbinary` *if* the version is greater than or equal to 2.0.5, otherwise it defaults to PHP's built-in serializer. +#### compressor +```xml + +``` +Allows you to hard-code a compressor for Psalm's cache. By default, Psalm uses `ext-zlib` deflate, if it's enabled. + #### threads ```xml + ``` diff --git a/vendor/vimeo/psalm/docs/running_psalm/language_server.md b/vendor/vimeo/psalm/docs/running_psalm/language_server.md index 47504068..3d80a91c 100644 --- a/vendor/vimeo/psalm/docs/running_psalm/language_server.md +++ b/vendor/vimeo/psalm/docs/running_psalm/language_server.md @@ -6,7 +6,9 @@ It currently supports diagnostics (i.e. finding errors and warnings), go-to-defi It works well in a variety of editors (listed alphabetically): -## Emacs +## Client configuration + +### Emacs I got it working with [eglot](https://github.com/joaotavora/eglot) @@ -27,13 +29,13 @@ This is the config I used: ) ``` -## PhpStorm +### PhpStorm -### Native Support +#### Native Support As of PhpStorm 2020.3 support for psalm is supported and on by default, you can read more about that [here](https://www.jetbrains.com/help/phpstorm/using-psalm.html) -### With LSP +#### With LSP Alternatively, psalm works with `gtache/intellij-lsp` plugin ([Jetbrains-approved version](https://plugins.jetbrains.com/plugin/10209-lsp-support), [latest version](https://github.com/gtache/intellij-lsp/releases/tag/v1.6.0)). @@ -51,7 +53,7 @@ In the "Server definitions" tab you should add a definition for Psalm: In the "Timeouts" tab you can adjust the initialization timeout. This is important if you have a large project. You should set the "Init" value to the number of milliseconds you allow Psalm to scan your entire project and your project's dependencies. For opening a couple of projects that use large PHP frameworks, on a high-end business laptop, try `240000` milliseconds for Init. -## Sublime Text +### Sublime Text I use the excellent Sublime [LSP plugin](https://github.com/tomv564/LSP) with the following config(Package Settings > LSP > Settings): ```json @@ -64,7 +66,7 @@ I use the excellent Sublime [LSP plugin](https://github.com/tomv564/LSP) with th } ``` -## Vim & Neovim +### Vim & Neovim **ALE** @@ -105,6 +107,15 @@ Add settings to `coc-settings.json`: } ``` -## VS Code +### VS Code [Get the Psalm plugin here](https://marketplace.visualstudio.com/items?itemName=getpsalm.psalm-vscode-plugin) (Requires VS Code 1.26+): + +## Running the server in a docker container + +Make sure you use `--map-folder` option. Using it without argument will map the server's CWD to the host's project root folder. You can also specify a custom mapping. For example: +```bash +docker-compose exec php /usr/share/php/psalm/psalm-language-server \ + -r=/var/www/html \ + --map-folder=/var/www/html:$PWD +``` diff --git a/vendor/vimeo/psalm/src/Psalm/Codebase.php b/vendor/vimeo/psalm/src/Psalm/Codebase.php index d6caa46d..56a9aab5 100644 --- a/vendor/vimeo/psalm/src/Psalm/Codebase.php +++ b/vendor/vimeo/psalm/src/Psalm/Codebase.php @@ -533,11 +533,12 @@ final class Codebase public function cacheClassLikeStorage(ClassLikeStorage $classlike_storage, string $file_path): void { - $file_contents = $this->file_provider->getContents($file_path); - - if ($this->classlike_storage_provider->cache) { - $this->classlike_storage_provider->cache->writeToCache($classlike_storage, $file_path, $file_contents); + if (!$this->classlike_storage_provider->cache) { + return; } + + $file_contents = $this->file_provider->getContents($file_path); + $this->classlike_storage_provider->cache->writeToCache($classlike_storage, $file_path, $file_contents); } public function exhumeClassLikeStorage(string $fq_classlike_name, string $file_path): void @@ -553,6 +554,8 @@ final class Codebase $this->classlikes->addFullyQualifiedTraitName($storage->name, $file_path); } elseif ($storage->is_interface) { $this->classlikes->addFullyQualifiedInterfaceName($storage->name, $file_path); + } elseif ($storage->is_enum) { + $this->classlikes->addFullyQualifiedEnumName($storage->name, $file_path); } else { $this->classlikes->addFullyQualifiedClassName($storage->name, $file_path); } diff --git a/vendor/vimeo/psalm/src/Psalm/Config.php b/vendor/vimeo/psalm/src/Psalm/Config.php index fcc1fbea..e84a134f 100644 --- a/vendor/vimeo/psalm/src/Psalm/Config.php +++ b/vendor/vimeo/psalm/src/Psalm/Config.php @@ -68,6 +68,7 @@ use function file_exists; use function file_get_contents; use function flock; use function fopen; +use function function_exists; use function get_class; use function get_defined_constants; use function get_defined_functions; @@ -331,6 +332,9 @@ class Config /** @var bool */ public $use_igbinary = false; + /** @var 'lz4'|'deflate'|'off' */ + public $compressor = 'off'; + /** * @var bool */ @@ -1188,12 +1192,43 @@ class Config if (isset($config_xml['serializer'])) { $attribute_text = (string) $config_xml['serializer']; $config->use_igbinary = $attribute_text === 'igbinary'; + if ($config->use_igbinary + && ( + !function_exists('igbinary_serialize') + || !function_exists('igbinary_unserialize') + ) + ) { + $config->use_igbinary = false; + $config->config_warnings[] = '"serializer" set to "igbinary" but ext-igbinary seems to be missing on ' . + 'the system. Using php\'s build-in serializer.'; + } } elseif ($igbinary_version = phpversion('igbinary')) { $config->use_igbinary = version_compare($igbinary_version, '2.0.5') >= 0; } + if (isset($config_xml['compressor'])) { + $compressor = (string) $config_xml['compressor']; + if ($compressor === 'lz4') { + if (function_exists('lz4_compress') && function_exists('lz4_uncompress')) { + $config->compressor = 'lz4'; + } else { + $config->config_warnings[] = '"compressor" set to "lz4" but ext-lz4 seems to be missing on the ' . + 'system. Disabling cache compressor.'; + } + } elseif ($compressor === 'deflate') { + if (function_exists('gzinflate') && function_exists('gzdeflate')) { + $config->compressor = 'deflate'; + } else { + $config->config_warnings[] = '"compressor" set to "deflate" but zlib seems to be missing on the ' . + 'system. Disabling cache compressor.'; + } + } + } elseif (function_exists('gzinflate') && function_exists('gzdeflate')) { + $config->compressor = 'deflate'; + } + if (!isset($config_xml['findUnusedBaselineEntry'])) { - $config->config_warnings[] = '"findUnusedBaselineEntry" will be defaulted to "true" in Psalm 6.' + $config->config_warnings[] = '"findUnusedBaselineEntry" will default to "true" in Psalm 6.' . ' You should explicitly enable or disable this setting.'; } @@ -1202,7 +1237,7 @@ class Config $config->find_unused_code = $attribute_text === 'true' || $attribute_text === '1'; $config->find_unused_variables = $config->find_unused_code; } else { - $config->config_warnings[] = '"findUnusedCode" will be defaulted to "true" in Psalm 6.' + $config->config_warnings[] = '"findUnusedCode" will default to "true" in Psalm 6.' . ' You should explicitly enable or disable this setting.'; } @@ -2218,28 +2253,27 @@ class Config $codebase->register_stub_files = true; $dir_lvl_2 = dirname(__DIR__, 2); + $stubsDir = $dir_lvl_2 . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR; $this->internal_stubs = [ - $dir_lvl_2 . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'CoreGenericFunctions.phpstub', - $dir_lvl_2 . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'CoreGenericClasses.phpstub', - $dir_lvl_2 . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'CoreGenericIterators.phpstub', - $dir_lvl_2 . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'CoreImmutableClasses.phpstub', - $dir_lvl_2 . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'Reflection.phpstub', - $dir_lvl_2 . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'SPL.phpstub', + $stubsDir . 'CoreGenericFunctions.phpstub', + $stubsDir . 'CoreGenericClasses.phpstub', + $stubsDir . 'CoreGenericIterators.phpstub', + $stubsDir . 'CoreImmutableClasses.phpstub', + $stubsDir . 'Reflection.phpstub', + $stubsDir . 'SPL.phpstub', ]; if ($codebase->analysis_php_version_id >= 8_00_00) { - $stringable_path = $dir_lvl_2 . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'Php80.phpstub'; - $this->internal_stubs[] = $stringable_path; + $this->internal_stubs[] = $stubsDir . 'CoreGenericAttributes.phpstub'; + $this->internal_stubs[] = $stubsDir . 'Php80.phpstub'; } if ($codebase->analysis_php_version_id >= 8_01_00) { - $stringable_path = $dir_lvl_2 . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'Php81.phpstub'; - $this->internal_stubs[] = $stringable_path; + $this->internal_stubs[] = $stubsDir . 'Php81.phpstub'; } if ($codebase->analysis_php_version_id >= 8_02_00) { - $stringable_path = $dir_lvl_2 . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'Php82.phpstub'; - $this->internal_stubs[] = $stringable_path; + $this->internal_stubs[] = $stubsDir . 'Php82.phpstub'; $this->php_extensions['random'] = true; // random is a part of the PHP core starting from PHP 8.2 } diff --git a/vendor/vimeo/psalm/src/Psalm/Config/Creator.php b/vendor/vimeo/psalm/src/Psalm/Config/Creator.php index 2ce9f3c5..a2fe9646 100644 --- a/vendor/vimeo/psalm/src/Psalm/Config/Creator.php +++ b/vendor/vimeo/psalm/src/Psalm/Config/Creator.php @@ -23,6 +23,7 @@ use function glob; use function implode; use function is_array; use function is_dir; +use function is_string; use function json_decode; use function ksort; use function max; @@ -46,6 +47,7 @@ final class Creator xmlns="https://getpsalm.org/schema/config" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" findUnusedBaselineEntry="true" + findUnusedCode="true" > @@ -249,6 +251,10 @@ final class Creator } foreach ($paths as $path) { + if (!is_string($path)) { + continue; + } + if ($path === '') { $nodes = [...$nodes, ...self::guessPhpFileDirs($current_dir)]; diff --git a/vendor/vimeo/psalm/src/Psalm/Config/FileFilter.php b/vendor/vimeo/psalm/src/Psalm/Config/FileFilter.php index cefa55b0..6e51d088 100644 --- a/vendor/vimeo/psalm/src/Psalm/Config/FileFilter.php +++ b/vendor/vimeo/psalm/src/Psalm/Config/FileFilter.php @@ -10,12 +10,18 @@ use SimpleXMLElement; use function array_filter; use function array_map; +use function array_merge; +use function array_shift; +use function count; use function explode; use function glob; use function in_array; use function is_dir; use function is_iterable; +use function is_string; use function preg_match; +use function preg_replace; +use function preg_split; use function readlink; use function realpath; use function restore_error_handler; @@ -52,12 +58,12 @@ class FileFilter protected $fq_classlike_names = []; /** - * @var array + * @var array */ protected $fq_classlike_patterns = []; /** - * @var array + * @var array */ protected $method_ids = []; @@ -129,10 +135,12 @@ class FileFilter } if (strpos($prospective_directory_path, '*') !== false) { - $globs = array_map( - 'realpath', - glob($prospective_directory_path, GLOB_ONLYDIR), - ); + // Strip meaningless trailing recursive wildcard like "path/**/" or "path/**" + $prospective_directory_path = preg_replace('#(\/\*\*)+\/?$#', '/', $prospective_directory_path); + // Split by /**/, allow duplicated wildcards like "path/**/**/path" and any leading dir separator. + /** @var non-empty-list $path_parts */ + $path_parts = preg_split('#(\/|\\\)(\*\*\/)+#', $prospective_directory_path); + $globs = self::recursiveGlob($path_parts, true); if (empty($globs)) { if ($allow_missing_files) { @@ -145,8 +153,8 @@ class FileFilter ); } - foreach ($globs as $glob_index => $directory_path) { - if (!$directory_path) { + foreach ($globs as $glob_index => $glob_directory_path) { + if (!$glob_directory_path) { if ($allow_missing_files) { continue; } @@ -158,14 +166,14 @@ class FileFilter } if ($ignore_type_stats && $filter instanceof ProjectFileFilter) { - $filter->ignore_type_stats[$directory_path] = true; + $filter->ignore_type_stats[$glob_directory_path] = true; } if ($declare_strict_types && $filter instanceof ProjectFileFilter) { - $filter->declare_strict_types[$directory_path] = true; + $filter->declare_strict_types[$glob_directory_path] = true; } - $filter->addDirectory($directory_path); + $filter->addDirectory($glob_directory_path); } continue; } @@ -246,13 +254,10 @@ class FileFilter } if (strpos($prospective_file_path, '*') !== false) { - $globs = array_map( - 'realpath', - array_filter( - glob($prospective_file_path, GLOB_NOSORT), - 'file_exists', - ), - ); + // Split by /**/, allow duplicated wildcards like "path/**/**/path" and any leading dir separator. + /** @var non-empty-list $path_parts */ + $path_parts = preg_split('#(\/|\\\)(\*\*\/)+#', $prospective_file_path); + $globs = self::recursiveGlob($path_parts, false); if (empty($globs)) { if ($allow_missing_files) { @@ -265,14 +270,18 @@ class FileFilter ); } - foreach ($globs as $glob_index => $file_path) { - if (!$file_path && !$allow_missing_files) { + foreach ($globs as $glob_index => $glob_file_path) { + if (!$glob_file_path) { + if ($allow_missing_files) { + continue; + } + throw new ConfigException( 'Could not resolve config path to ' . $base_dir . DIRECTORY_SEPARATOR . $file_path . ':' . $glob_index, ); } - $filter->addFile($file_path); + $filter->addFile($glob_file_path); } continue; } @@ -306,14 +315,18 @@ class FileFilter if (isset($config['referencedMethod']) && is_iterable($config['referencedMethod'])) { /** @var array $referenced_method */ foreach ($config['referencedMethod'] as $referenced_method) { - $method_id = (string) ($referenced_method['name'] ?? ''); - - if (!preg_match('/^[^:]+::[^:]+$/', $method_id) && !static::isRegularExpression($method_id)) { + $method_id = $referenced_method['name'] ?? ''; + if (!is_string($method_id) + || (!preg_match('/^[^:]+::[^:]+$/', $method_id) && !static::isRegularExpression($method_id))) { throw new ConfigException( - 'Invalid referencedMethod ' . $method_id, + 'Invalid referencedMethod ' . ((string) $method_id), ); } + if ($method_id === '') { + continue; + } + $filter->method_ids[] = strtolower($method_id); } } @@ -321,7 +334,21 @@ class FileFilter if (isset($config['referencedFunction']) && is_iterable($config['referencedFunction'])) { /** @var array $referenced_function */ foreach ($config['referencedFunction'] as $referenced_function) { - $filter->method_ids[] = strtolower((string) ($referenced_function['name'] ?? '')); + $function_id = $referenced_function['name'] ?? ''; + if (!is_string($function_id) + || (!preg_match('/^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$/', $function_id) + && !preg_match('/^[^:]+::[^:]+$/', $function_id) // methods are also allowed + && !static::isRegularExpression($function_id))) { + throw new ConfigException( + 'Invalid referencedFunction ' . ((string) $function_id), + ); + } + + if ($function_id === '') { + continue; + } + + $filter->method_ids[] = strtolower($function_id); } } @@ -433,8 +460,15 @@ class FileFilter return self::loadFromArray($config, $base_dir, $inclusive); } + /** + * @psalm-assert-if-true non-empty-string $string + */ private static function isRegularExpression(string $string): bool { + if ($string === '') { + return false; + } + set_error_handler( static fn(): bool => true, E_WARNING, @@ -445,6 +479,39 @@ class FileFilter return $is_regexp; } + /** + * @mutation-free + * @param non-empty-list $parts + * @return array + */ + private static function recursiveGlob(array $parts, bool $only_dir): array + { + if (count($parts) < 2) { + if ($only_dir) { + $list = glob($parts[0], GLOB_ONLYDIR | GLOB_NOSORT) ?: []; + } else { + $list = array_filter( + glob($parts[0], GLOB_NOSORT) ?: [], + 'file_exists', + ); + } + + return array_map('realpath', $list); + } + + $first_dir = self::slashify($parts[0]); + $paths = glob($first_dir . '*', GLOB_ONLYDIR | GLOB_NOSORT); + $result = []; + foreach ($paths as $path) { + $parts[0] = $path; + $result = array_merge($result, self::recursiveGlob($parts, $only_dir)); + } + array_shift($parts); + $parts[0] = $first_dir . $parts[0]; + + return array_merge($result, self::recursiveGlob($parts, $only_dir)); + } + /** * @psalm-pure */ diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Algebra.php b/vendor/vimeo/psalm/src/Psalm/Internal/Algebra.php index 0f581fc8..d2b16a26 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Algebra.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Algebra.php @@ -4,6 +4,9 @@ namespace Psalm\Internal; use Psalm\Exception\ComplicatedExpressionException; use Psalm\Storage\Assertion; +use Psalm\Type\Atomic\TArray; +use Psalm\Type\Atomic\TKeyedArray; +use Psalm\Type\Atomic\TList; use UnexpectedValueException; use function array_filter; @@ -322,6 +325,9 @@ class Algebra /** * Look for clauses with only one possible value * + * doesn't infer the "unset" correctly + * + * @psalm-suppress MoreSpecificReturnType * @param list $clauses * @param array $cond_referenced_var_ids * @param array>> $active_truths @@ -388,6 +394,72 @@ class Algebra } } + foreach ($truths as $var => $anded_types) { + $has_list_or_array = false; + foreach ($anded_types as $orred_types) { + foreach ($orred_types as $assertion) { + if ($assertion->isNegation()) { + continue; + } + + if (!isset($assertion->type)) { + continue; + } + + if ($assertion->type instanceof TList + || $assertion->type instanceof TArray + || $assertion->type instanceof TKeyedArray) { + $has_list_or_array = true; + // list/array are collapsed, therefore there can only be 1 and we can abort + // otherwise we would have to remove them all individually + // e.g. array cannot be array + break 2; + } + } + } + + if ($has_list_or_array === false) { + continue; + } + + foreach ($anded_types as $key => $orred_types) { + foreach ($orred_types as $index => $assertion) { + // we only need to check negations + // due to type collapsing, any negations for arrays are irrelevant + if (!$assertion->isNegation()) { + continue; + } + + if (!isset($assertion->type)) { + continue; + } + + if ($assertion->type instanceof TList + || $assertion->type instanceof TArray + || $assertion->type instanceof TKeyedArray) { + unset($truths[$var][$key][$index]); + } + } + + /** + * doesn't infer the "unset" correctly + * + * @psalm-suppress DocblockTypeContradiction + */ + if ($truths[$var][$key] === []) { + unset($truths[$var][$key]); + } else { + /** + * doesn't infer the "unset" correctly + * + * @psalm-suppress RedundantFunctionCallGivenDocblockType + */ + $truths[$var][$key] = array_values($truths[$var][$key]); + } + } + } + + /** @psalm-suppress LessSpecificReturnStatement */ return $truths; } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/CanAlias.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/CanAlias.php index 1e23e08b..3be3d60d 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/CanAlias.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/CanAlias.php @@ -8,7 +8,6 @@ use Psalm\CodeLocation; use Psalm\FileManipulation; use Psalm\Internal\FileManipulation\FileManipulationBuffer; -use function implode; use function strtolower; /** @@ -51,7 +50,7 @@ trait CanAlias $codebase = $this->getCodebase(); foreach ($stmt->uses as $use) { - $use_path = implode('\\', $use->name->parts); + $use_path = $use->name->toString(); $use_path_lc = strtolower($use_path); $use_alias = $use->alias->name ?? $use->name->getLast(); $use_alias_lc = strtolower($use_alias); @@ -106,12 +105,12 @@ trait CanAlias public function visitGroupUse(PhpParser\Node\Stmt\GroupUse $stmt): void { - $use_prefix = implode('\\', $stmt->prefix->parts); + $use_prefix = $stmt->prefix->toString(); $codebase = $this->getCodebase(); foreach ($stmt->uses as $use) { - $use_path = $use_prefix . '\\' . implode('\\', $use->name->parts); + $use_path = $use_prefix . '\\' . $use->name->toString(); $use_alias = $use->alias->name ?? $use->name->getLast(); switch ($use->type !== PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN ? $use->type : $stmt->type) { diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassAnalyzer.php index 3d120c89..bdb35732 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassAnalyzer.php @@ -802,7 +802,20 @@ class ClassAnalyzer extends ClassLikeAnalyzer $codebase, ); - if ($property_storage->location + if ($guide_property_storage->readonly + && UnionTypeComparator::isContainedBy( + $codebase, + $property_type, + $guide_property_type, + false, + false, + null, + false, + false, + )) { + // if the original property is readonly, it cannot be written + // therefore invariance is not a problem, if the parent type contains the child type + } elseif ($property_storage->location && !$property_type->equals($guide_property_type, false) && $guide_class_storage->user_defined ) { @@ -999,6 +1012,11 @@ class ClassAnalyzer extends ClassLikeAnalyzer return; } + // abstract constructors do not have any code, therefore cannot set any properties either + if (isset($storage->methods['__construct']) && $storage->methods['__construct']->abstract) { + return; + } + $fq_class_name = $class_context->self ?: $this->fq_class_name; $fq_class_name_lc = strtolower($fq_class_name); @@ -2003,7 +2021,7 @@ class ClassAnalyzer extends ClassLikeAnalyzer . ($interface_name instanceof PhpParser\Node\Name\FullyQualified ? '\\' : $this->getNamespace() . '-') - . implode('\\', $interface_name->parts), + . $interface_name->toString(), ); $interface_location = new CodeLocation($this, $interface_name); @@ -2419,7 +2437,7 @@ class ClassAnalyzer extends ClassLikeAnalyzer . ($extended_class instanceof PhpParser\Node\Name\FullyQualified ? '\\' : $this->getNamespace() . '-') - . implode('\\', $extended_class->parts), + . $extended_class->toString(), ); } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php index 92e86998..a6c90919 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php @@ -40,7 +40,6 @@ use function array_search; use function count; use function explode; use function gettype; -use function implode; use function in_array; use function preg_match; use function preg_replace; @@ -421,15 +420,15 @@ abstract class ClassLikeAnalyzer extends SourceAnalyzer } if ($class_name instanceof PhpParser\Node\Name\FullyQualified) { - return implode('\\', $class_name->parts); + return $class_name->toString(); } - if (in_array($class_name->parts[0], ['self', 'static', 'parent'], true)) { - return $class_name->parts[0]; + if (in_array($class_name->getFirst(), ['self', 'static', 'parent'], true)) { + return $class_name->getFirst(); } return Type::getFQCLNFromString( - implode('\\', $class_name->parts), + $class_name->toString(), $aliases, ); } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/CommentAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/CommentAnalyzer.php index 00a3f8a2..9668f292 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/CommentAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/CommentAnalyzer.php @@ -34,6 +34,7 @@ use function preg_split; use function rtrim; use function str_replace; use function strlen; +use function strpos; use function substr; use function substr_count; use function trim; @@ -259,7 +260,8 @@ class CommentAnalyzer public static function sanitizeDocblockType(string $docblock_type): string { $docblock_type = preg_replace('@^[ \t]*\*@m', '', $docblock_type); - $docblock_type = preg_replace('/,\n\s+\}/', '}', $docblock_type); + $docblock_type = preg_replace('/,\n\s+}/', '}', $docblock_type); + return str_replace("\n", '', $docblock_type); } @@ -326,6 +328,22 @@ class CommentAnalyzer continue; } + if ($char === '/' && $next_char === '/') { + // Ignore the rest of the current line + $i = strpos($return_block, "\n", $i); + if ($i === false) { + throw new IncorrectDocblockException( + 'Comment lines must be terminated with a new line character (\\n).', + ); + } + + // Remove trailing whitespaces (needed for `sanitizeDocblockType`) + $type = rtrim($type); + $type .= "\n"; + + continue; + } + if ($char === '[' || $char === '{' || $char === '(' || $char === '<') { $brackets .= $char; } elseif ($char === ']' || $char === '}' || $char === ')' || $char === '>') { @@ -346,6 +364,11 @@ class CommentAnalyzer continue; } + if ($next_char === '{') { + $type .= ' '; + continue; + } + if ($next_char === '|' || $next_char === '&') { $nexter_char = $i < $l - 2 ? $return_block[$i + 2] : null; @@ -377,7 +400,7 @@ class CommentAnalyzer $remaining = trim(preg_replace('@^[ \t]*\* *@m', ' ', substr($return_block, $i + 1))); if ($remaining) { - return array_merge([rtrim($type)], preg_split('/[ \s]+/', $remaining) ?: []); + return array_merge([rtrim($type)], preg_split('/\s+/', $remaining) ?: []); } return [$type]; diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FileAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FileAnalyzer.php index 7f6ce4ce..d9879558 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FileAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FileAnalyzer.php @@ -32,7 +32,6 @@ use function array_combine; use function array_diff_key; use function array_keys; use function count; -use function implode; use function strpos; use function strtolower; @@ -283,7 +282,7 @@ class FileAnalyzer extends SourceAnalyzer } elseif ($stmt instanceof PhpParser\Node\Stmt\ClassLike) { $this->populateClassLikeAnalyzers($stmt); } elseif ($stmt instanceof PhpParser\Node\Stmt\Namespace_) { - $namespace_name = $stmt->name ? implode('\\', $stmt->name->parts) : ''; + $namespace_name = $stmt->name ? $stmt->name->toString() : ''; $namespace_analyzer = new NamespaceAnalyzer($stmt, $this); $namespace_analyzer->collectAnalyzableInformation(); diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/IssueData.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/IssueData.php index 6b273c0b..72e72b21 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/IssueData.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/IssueData.php @@ -11,6 +11,12 @@ use const STR_PAD_LEFT; */ class IssueData { + public const SEVERITY_INFO = 'info'; + public const SEVERITY_ERROR = 'error'; + + /** + * @var self::SEVERITY_* + */ public string $severity; public int $line_from; @@ -93,6 +99,7 @@ class IssueData public ?string $dupe_key = null; /** + * @param self::SEVERITY_* $severity * @param ?list $taint_trace * @param ?list $other_references */ diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php index 6b5d2809..a01318a3 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php @@ -14,7 +14,6 @@ use UnexpectedValueException; use function assert; use function count; -use function implode; use function is_string; use function preg_replace; use function strpos; @@ -49,7 +48,7 @@ class NamespaceAnalyzer extends SourceAnalyzer { $this->source = $source; $this->namespace = $namespace; - $this->namespace_name = $this->namespace->name ? implode('\\', $this->namespace->name->parts) : ''; + $this->namespace_name = $this->namespace->name ? $this->namespace->name->toString() : ''; } public function collectAnalyzableInformation(): void diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php index 6104e067..a418a52b 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php @@ -1098,6 +1098,15 @@ class ProjectAnalyzer } } + public function finish(float $start_time, string $psalm_version): void + { + $this->codebase->file_reference_provider->removeDeletedFilesFromReferences(); + + if ($this->project_cache_provider) { + $this->project_cache_provider->processSuccessfulRun($start_time, $psalm_version); + } + } + public function getConfig(): Config { return $this->config; diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php index ea9e450f..e1c5e5e4 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php @@ -238,13 +238,13 @@ class IfConditionalAnalyzer || $stmt instanceof PhpParser\Node\Expr\BinaryOp\Identical ) { if ($stmt->left instanceof PhpParser\Node\Expr\ConstFetch - && $stmt->left->name->parts === ['true'] + && $stmt->left->name->getParts() === ['true'] ) { return self::getDefinitelyEvaluatedExpressionAfterIf($stmt->right); } if ($stmt->right instanceof PhpParser\Node\Expr\ConstFetch - && $stmt->right->name->parts === ['true'] + && $stmt->right->name->getParts() === ['true'] ) { return self::getDefinitelyEvaluatedExpressionAfterIf($stmt->left); } @@ -282,13 +282,13 @@ class IfConditionalAnalyzer || $stmt instanceof PhpParser\Node\Expr\BinaryOp\Identical ) { if ($stmt->left instanceof PhpParser\Node\Expr\ConstFetch - && $stmt->left->name->parts === ['true'] + && $stmt->left->name->getParts() === ['true'] ) { return self::getDefinitelyEvaluatedExpressionInsideIf($stmt->right); } if ($stmt->right instanceof PhpParser\Node\Expr\ConstFetch - && $stmt->right->name->parts === ['true'] + && $stmt->right->name->getParts() === ['true'] ) { return self::getDefinitelyEvaluatedExpressionInsideIf($stmt->left); } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php index 4ff32acc..f55d1d0a 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php @@ -358,16 +358,6 @@ class ElseIfAnalyzer $elseif_context->inside_loop, new CodeLocation($statements_analyzer->getSource(), $elseif, $outer_context->include_location), ); - - $updated_vars = []; - - $outer_context->update( - $elseif_context, - $implied_outer_context, - false, - array_keys($negated_elseif_types), - $updated_vars, - ); } } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/SwitchCaseAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/SwitchCaseAnalyzer.php index 5fd9b4b1..e116f117 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/SwitchCaseAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/SwitchCaseAnalyzer.php @@ -209,7 +209,7 @@ class SwitchCaseAnalyzer } if ($switch_condition instanceof PhpParser\Node\Expr\ConstFetch - && $switch_condition->name->parts === ['true'] + && $switch_condition->name->getParts() === ['true'] ) { $case_equality_expr = $case->cond; } elseif (($switch_condition_type = $statements_analyzer->node_data->getType($switch_condition)) diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php index a1fd1707..bb486123 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php @@ -26,7 +26,8 @@ class WhileAnalyzer PhpParser\Node\Stmt\While_ $stmt, Context $context ): ?bool { - $while_true = ($stmt->cond instanceof PhpParser\Node\Expr\ConstFetch && $stmt->cond->name->parts === ['true']) + $while_true = ($stmt->cond instanceof PhpParser\Node\Expr\ConstFetch + && $stmt->cond->name->getParts() === ['true']) || (($t = $statements_analyzer->node_data->getType($stmt->cond)) && $t->isAlwaysTruthy()); diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php index 3396deae..fc57f217 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php @@ -830,7 +830,7 @@ class AssertionFinder $if_types[$first_var_name] = [[new IsType(new TCallableString())]]; } } elseif ($expr->name instanceof PhpParser\Node\Name - && strtolower($expr->name->parts[0]) === 'method_exists' + && strtolower($expr->name->getFirst()) === 'method_exists' && isset($expr->getArgs()[1]) && $expr->getArgs()[1]->value instanceof PhpParser\Node\Scalar\String_ ) { @@ -1233,7 +1233,7 @@ class AssertionFinder FileSource $source ): array { if ($stmt->class instanceof PhpParser\Node\Name) { - if (!in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true)) { + if (!in_array(strtolower($stmt->class->getFirst()), ['self', 'static', 'parent'], true)) { $instanceof_class = ClassLikeAnalyzer::getFQCLNFromNameObject( $stmt->class, $source->getAliases(), @@ -1248,8 +1248,8 @@ class AssertionFinder } if ($this_class_name - && (in_array(strtolower($stmt->class->parts[0]), ['self', 'static'], true))) { - $is_static = $stmt->class->parts[0] === 'static'; + && (in_array(strtolower($stmt->class->getFirst()), ['self', 'static'], true))) { + $is_static = $stmt->class->getFirst() === 'static'; $named_object = new TNamedObject($this_class_name, $is_static); if ($is_static) { @@ -1297,13 +1297,13 @@ class AssertionFinder FileSource $source ): ?int { if ($conditional->right instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($conditional->right->name->parts[0]) === 'null' + && strtolower($conditional->right->name->getFirst()) === 'null' ) { return self::ASSIGNMENT_TO_RIGHT; } if ($conditional->left instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($conditional->left->name->parts[0]) === 'null' + && strtolower($conditional->left->name->getFirst()) === 'null' ) { return self::ASSIGNMENT_TO_LEFT; } @@ -1325,13 +1325,13 @@ class AssertionFinder PhpParser\Node\Expr\BinaryOp $conditional ): ?int { if ($conditional->right instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($conditional->right->name->parts[0]) === 'false' + && strtolower($conditional->right->name->getFirst()) === 'false' ) { return self::ASSIGNMENT_TO_RIGHT; } if ($conditional->left instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($conditional->left->name->parts[0]) === 'false' + && strtolower($conditional->left->name->getFirst()) === 'false' ) { return self::ASSIGNMENT_TO_LEFT; } @@ -1346,13 +1346,13 @@ class AssertionFinder PhpParser\Node\Expr\BinaryOp $conditional ): ?int { if ($conditional->right instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($conditional->right->name->parts[0]) === 'true' + && strtolower($conditional->right->name->getFirst()) === 'true' ) { return self::ASSIGNMENT_TO_RIGHT; } if ($conditional->left instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($conditional->left->name->parts[0]) === 'true' + && strtolower($conditional->left->name->getFirst()) === 'true' ) { return self::ASSIGNMENT_TO_LEFT; } @@ -1390,7 +1390,7 @@ class AssertionFinder ) { if ($conditional->right instanceof PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof PhpParser\Node\Name - && strtolower($conditional->right->name->parts[0]) === 'gettype' + && strtolower($conditional->right->name->getFirst()) === 'gettype' && $conditional->right->getArgs() && $conditional->left instanceof PhpParser\Node\Scalar\String_ ) { @@ -1399,7 +1399,7 @@ class AssertionFinder if ($conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name - && strtolower($conditional->left->name->parts[0]) === 'gettype' + && strtolower($conditional->left->name->getFirst()) === 'gettype' && $conditional->left->getArgs() && $conditional->right instanceof PhpParser\Node\Scalar\String_ ) { @@ -1418,7 +1418,7 @@ class AssertionFinder ) { if ($conditional->right instanceof PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof PhpParser\Node\Name - && strtolower($conditional->right->name->parts[0]) === 'get_debug_type' + && strtolower($conditional->right->name->getFirst()) === 'get_debug_type' && $conditional->right->getArgs() && ($conditional->left instanceof PhpParser\Node\Scalar\String_ || $conditional->left instanceof PhpParser\Node\Expr\ClassConstFetch) @@ -1428,7 +1428,7 @@ class AssertionFinder if ($conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name - && strtolower($conditional->left->name->parts[0]) === 'get_debug_type' + && strtolower($conditional->left->name->getFirst()) === 'get_debug_type' && $conditional->left->getArgs() && ($conditional->right instanceof PhpParser\Node\Scalar\String_ || $conditional->right instanceof PhpParser\Node\Expr\ClassConstFetch) @@ -1453,11 +1453,11 @@ class AssertionFinder $right_get_class = $conditional->right instanceof PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof PhpParser\Node\Name - && strtolower($conditional->right->name->parts[0]) === 'get_class'; + && strtolower($conditional->right->name->getFirst()) === 'get_class'; $right_static_class = $conditional->right instanceof PhpParser\Node\Expr\ClassConstFetch && $conditional->right->class instanceof PhpParser\Node\Name - && $conditional->right->class->parts === ['static'] + && $conditional->right->class->getParts() === ['static'] && $conditional->right->name instanceof PhpParser\Node\Identifier && strtolower($conditional->right->name->name) === 'class'; @@ -1492,11 +1492,11 @@ class AssertionFinder $left_get_class = $conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name - && strtolower($conditional->left->name->parts[0]) === 'get_class'; + && strtolower($conditional->left->name->getFirst()) === 'get_class'; $left_static_class = $conditional->left instanceof PhpParser\Node\Expr\ClassConstFetch && $conditional->left->class instanceof PhpParser\Node\Name - && $conditional->left->class->parts === ['static'] + && $conditional->left->class->getParts() === ['static'] && $conditional->left->name instanceof PhpParser\Node\Identifier && strtolower($conditional->left->name->name) === 'class'; @@ -1542,7 +1542,7 @@ class AssertionFinder ) { if ($conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name - && in_array(strtolower($conditional->left->name->parts[0]), ['count', 'sizeof']) + && in_array(strtolower($conditional->left->name->getFirst()), ['count', 'sizeof']) && $conditional->left->getArgs() && ($conditional instanceof BinaryOp\Greater || $conditional instanceof BinaryOp\GreaterOrEqual) ) { @@ -1551,7 +1551,7 @@ class AssertionFinder $comparison_adjustment = $conditional instanceof BinaryOp\Greater ? 1 : 0; } elseif ($conditional->right instanceof PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof PhpParser\Node\Name - && in_array(strtolower($conditional->right->name->parts[0]), ['count', 'sizeof']) + && in_array(strtolower($conditional->right->name->getFirst()), ['count', 'sizeof']) && $conditional->right->getArgs() && ($conditional instanceof BinaryOp\Smaller || $conditional instanceof BinaryOp\SmallerOrEqual) ) { @@ -1584,7 +1584,7 @@ class AssertionFinder ) { $left_count = $conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name - && in_array(strtolower($conditional->left->name->parts[0]), ['count', 'sizeof']) + && in_array(strtolower($conditional->left->name->getFirst()), ['count', 'sizeof']) && $conditional->left->getArgs(); $operator_less_than_or_equal = @@ -1603,7 +1603,7 @@ class AssertionFinder $right_count = $conditional->right instanceof PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof PhpParser\Node\Name - && in_array(strtolower($conditional->right->name->parts[0]), ['count', 'sizeof']) + && in_array(strtolower($conditional->right->name->getFirst()), ['count', 'sizeof']) && $conditional->right->getArgs(); $operator_greater_than_or_equal = @@ -1633,7 +1633,7 @@ class AssertionFinder ) { $left_count = $conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name - && in_array(strtolower($conditional->left->name->parts[0]), ['count', 'sizeof']) + && in_array(strtolower($conditional->left->name->getFirst()), ['count', 'sizeof']) && $conditional->left->getArgs(); if ($left_count && $conditional->right instanceof PhpParser\Node\Scalar\LNumber) { @@ -1644,7 +1644,7 @@ class AssertionFinder $right_count = $conditional->right instanceof PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof PhpParser\Node\Name - && in_array(strtolower($conditional->right->name->parts[0]), ['count', 'sizeof']) + && in_array(strtolower($conditional->right->name->getFirst()), ['count', 'sizeof']) && $conditional->right->getArgs(); if ($right_count && $conditional->left instanceof PhpParser\Node\Scalar\LNumber) { @@ -1785,7 +1785,7 @@ class AssertionFinder ) { $left_count = $conditional->left instanceof PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof PhpParser\Node\Name - && in_array(strtolower($conditional->left->name->parts[0]), ['count', 'sizeof']); + && in_array(strtolower($conditional->left->name->getFirst()), ['count', 'sizeof']); $right_number = $conditional->right instanceof PhpParser\Node\Scalar\LNumber && $conditional->right->value === ( @@ -1841,8 +1841,8 @@ class AssertionFinder StatementsAnalyzer $source ): bool { if ($stmt->name instanceof PhpParser\Node\Name - && (strtolower($stmt->name->parts[0]) === 'is_a' - || strtolower($stmt->name->parts[0]) === 'is_subclass_of') + && (strtolower($stmt->name->getFirst()) === 'is_a' + || strtolower($stmt->name->getFirst()) === 'is_subclass_of') && isset($stmt->getArgs()[1]) ) { $second_arg = $stmt->getArgs()[1]->value; @@ -1920,7 +1920,7 @@ class AssertionFinder ): array { $if_types = []; if ($stmt->name instanceof PhpParser\Node\Name - && ($function_name = strtolower($stmt->name->parts[0])) + && ($function_name = strtolower($stmt->name->getFirst())) && ($assertion_type = self::getIsAssertion($function_name)) && $source instanceof StatementsAnalyzer && ($source->getNamespace() === null //either the namespace is null @@ -1954,7 +1954,7 @@ class AssertionFinder protected static function hasCallableCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { - return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->parts[0]) === 'is_callable'; + return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'is_callable'; } /** @@ -1963,7 +1963,7 @@ class AssertionFinder protected static function hasClassExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): int { if ($stmt->name instanceof PhpParser\Node\Name - && strtolower($stmt->name->parts[0]) === 'class_exists' + && strtolower($stmt->name->getFirst()) === 'class_exists' ) { if (!isset($stmt->getArgs()[1])) { return 2; @@ -1972,7 +1972,7 @@ class AssertionFinder $second_arg = $stmt->getArgs()[1]->value; if ($second_arg instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($second_arg->name->parts[0]) === 'true' + && strtolower($second_arg->name->getFirst()) === 'true' ) { return 2; } @@ -1989,7 +1989,7 @@ class AssertionFinder protected static function hasTraitExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): int { if ($stmt->name instanceof PhpParser\Node\Name - && strtolower($stmt->name->parts[0]) === 'trait_exists' + && strtolower($stmt->name->getFirst()) === 'trait_exists' ) { if (!isset($stmt->getArgs()[1])) { return 2; @@ -1998,7 +1998,7 @@ class AssertionFinder $second_arg = $stmt->getArgs()[1]->value; if ($second_arg instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($second_arg->name->parts[0]) === 'true' + && strtolower($second_arg->name->getFirst()) === 'true' ) { return 2; } @@ -2011,29 +2011,29 @@ class AssertionFinder protected static function hasEnumExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { - return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->parts[0]) === 'enum_exists'; + return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'enum_exists'; } protected static function hasInterfaceExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { - return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->parts[0]) === 'interface_exists'; + return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'interface_exists'; } protected static function hasFunctionExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { - return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->parts[0]) === 'function_exists'; + return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'function_exists'; } protected static function hasInArrayCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { if ($stmt->name instanceof PhpParser\Node\Name - && strtolower($stmt->name->parts[0]) === 'in_array' + && strtolower($stmt->name->getFirst()) === 'in_array' && isset($stmt->getArgs()[2]) ) { $second_arg = $stmt->getArgs()[2]->value; if ($second_arg instanceof PhpParser\Node\Expr\ConstFetch - && strtolower($second_arg->name->parts[0]) === 'true' + && strtolower($second_arg->name->getFirst()) === 'true' ) { return true; } @@ -2045,12 +2045,12 @@ class AssertionFinder protected static function hasNonEmptyCountCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { return $stmt->name instanceof PhpParser\Node\Name && - in_array(strtolower($stmt->name->parts[0]), ['count', 'sizeof']); + in_array(strtolower($stmt->name->getFirst()), ['count', 'sizeof']); } protected static function hasArrayKeyExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool { - return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->parts[0]) === 'array_key_exists'; + return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'array_key_exists'; } /** @@ -2254,6 +2254,7 @@ class AssertionFinder } /** + * @psalm-suppress MoreSpecificReturnType * @param PhpParser\Node\Expr\BinaryOp\NotIdentical|PhpParser\Node\Expr\BinaryOp\NotEqual $conditional * @return list>>> */ @@ -2325,15 +2326,45 @@ class AssertionFinder } if (count($notif_types) === 1) { - $notif_types = $notif_types[0]; + $notif_type = $notif_types[0]; - if (count($notif_types) === 1) { - $if_types = Algebra::negateTypes($notif_types); + if (count($notif_type) === 1) { + $if_types = Algebra::negateTypes($notif_type); } } $if_types = $if_types ? [$if_types] : []; + if ($if_types === [] && count($notif_types) === 2) { + $check_var_assertion = null; + $check_var = null; + foreach ($notif_types as $notif_type) { + foreach ($notif_type as $var => $assertions) { + if (count($assertions) !== 1 || count($assertions[0]) !== 1) { + $if_types = []; + break 2; + } + + $is_not_assertion = $assertions[0][0] instanceof IsNotType ? true : false; + if (!isset($check_var)) { + $check_var_assertion = $is_not_assertion; + $check_var = $var; + continue; + } + + // only if we have 1 IsType and 1 IsNotType assertion for same variable + if ($check_var !== $var + || !isset($check_var_assertion) + || $check_var_assertion === $is_not_assertion) { + $if_types = []; + break 2; + } + } + + $if_types[] = Algebra::negateTypes($notif_type); + } + } + if ($codebase && $source instanceof StatementsAnalyzer && ($var_type = $source->node_data->getType($base_conditional)) @@ -2373,6 +2404,7 @@ class AssertionFinder } } + /** @psalm-suppress LessSpecificReturnStatement */ return $if_types; } @@ -2951,6 +2983,7 @@ class AssertionFinder } /** + * @psalm-suppress MoreSpecificReturnType * @param PhpParser\Node\Expr\BinaryOp\Identical|PhpParser\Node\Expr\BinaryOp\Equal $conditional * @return list>>> */ @@ -3022,15 +3055,48 @@ class AssertionFinder } if (count($notif_types) === 1) { - $notif_types = $notif_types[0]; + $notif_type = $notif_types[0]; - if (count($notif_types) === 1) { - $if_types = Algebra::negateTypes($notif_types); + if (count($notif_type) === 1) { + $if_types = Algebra::negateTypes($notif_type); } } $if_types = $if_types ? [$if_types] : []; + // @psalm-assert-if-true and @psalm-assert-if-false for same variable in same function, e.g. array/list cases + // @todo optionally extend this to arbitrary number of assert-if cases of multiple variables in the function + // same code above too + if ($if_types === [] && count($notif_types) === 2) { + $check_var_assertion = null; + $check_var = null; + foreach ($notif_types as $notif_type) { + foreach ($notif_type as $var => $assertions) { + if (count($assertions) !== 1 || count($assertions[0]) !== 1) { + $if_types = []; + break 2; + } + + $is_not_assertion = $assertions[0][0] instanceof IsNotType ? true : false; + if (!isset($check_var)) { + $check_var_assertion = $is_not_assertion; + $check_var = $var; + continue; + } + + // only if we have 1 IsType and 1 IsNotType assertion for same variable + if ($check_var !== $var + || !isset($check_var_assertion) + || $check_var_assertion === $is_not_assertion) { + $if_types = []; + break 2; + } + } + + $if_types[] = Algebra::negateTypes($notif_type); + } + } + if ($codebase && $source instanceof StatementsAnalyzer && ($var_type = $source->node_data->getType($base_conditional)) @@ -3066,6 +3132,7 @@ class AssertionFinder } } + /** @psalm-suppress LessSpecificReturnStatement */ return $if_types; } @@ -3408,56 +3475,53 @@ class AssertionFinder throw new UnexpectedValueException('$typed_value_position value'); } - if ($var_name && $var_type) { - $identical = $conditional instanceof PhpParser\Node\Expr\BinaryOp\Identical - || ($other_type - && (($var_type->isString(true) && $other_type->isString(true)) - || ($var_type->isInt(true) && $other_type->isInt(true)) - || ($var_type->isFloat() && $other_type->isFloat()) - ) - ); + //soit on a un === explicite, soit on compare des types strictement égaux + $identical = $conditional instanceof PhpParser\Node\Expr\BinaryOp\Identical + || ($other_type && $var_type + && (($var_type->isString(true) && $other_type->isString(true)) + || ($var_type->isInt(true) && $other_type->isInt(true)) + || ($var_type->isFloat() && $other_type->isFloat()) + ) + ); - if (count($var_type->getAtomicTypes()) === 1) { - $orred_types = []; + if ($var_name + && $var_type + && !$var_type->isMixed() + && count($var_type->getAtomicTypes()) === 1 + ) { + $orred_types = []; - foreach ($var_type->getAtomicTypes() as $atomic_var_type) { - if ($identical) { - $orred_types[] = new IsIdentical($atomic_var_type); - } else { - $orred_types[] = new IsLooselyEqual($atomic_var_type); - } + foreach ($var_type->getAtomicTypes() as $atomic_var_type) { + if ($identical) { + $orred_types[] = new IsIdentical($atomic_var_type); + } else { + $orred_types[] = new IsLooselyEqual($atomic_var_type); } - - $if_types[$var_name] = [$orred_types]; } - if ($other_var_name - && $other_type - && !$other_type->isMixed() - && count($other_type->getAtomicTypes()) === 1 - ) { - $orred_types = []; - - foreach ($other_type->getAtomicTypes() as $atomic_other_type) { - if ($identical) { - $orred_types[] = new IsIdentical($atomic_other_type); - } else { - $orred_types[] = new IsLooselyEqual($atomic_other_type); - } - } - - $if_types[$other_var_name] = [$orred_types]; - } + $if_types[$var_name] = [$orred_types]; } - if ($codebase + if ($other_var_name && $other_type - && $var_type - && ($conditional instanceof PhpParser\Node\Expr\BinaryOp\Identical - || ($other_type->isString() - && $var_type->isString()) - ) + && !$other_type->isMixed() + && count($other_type->getAtomicTypes()) === 1 + && $other_var_name[0] === '$' //don't try to assert on constant or other, it's too perf consuming ) { + $orred_types = []; + + foreach ($other_type->getAtomicTypes() as $atomic_other_type) { + if ($identical) { + $orred_types[] = new IsIdentical($atomic_other_type); + } else { + $orred_types[] = new IsLooselyEqual($atomic_other_type); + } + } + + $if_types[$other_var_name] = [$orred_types]; + } + + if ($codebase && $other_type && $var_type && $identical) { self::handleParadoxicalAssertions( $source, $var_type, @@ -3486,8 +3550,8 @@ class AssertionFinder && $expr->getArgs()[0]->value->name instanceof PhpParser\Node\Identifier && strtolower($expr->getArgs()[0]->value->name->name) === 'class' && $expr->getArgs()[0]->value->class instanceof PhpParser\Node\Name - && count($expr->getArgs()[0]->value->class->parts) === 1 - && strtolower($expr->getArgs()[0]->value->class->parts[0]) === 'static' + && count($expr->getArgs()[0]->value->class->getParts()) === 1 + && strtolower($expr->getArgs()[0]->value->class->getFirst()) === 'static' ) { $first_var_name = '$this'; } @@ -3498,14 +3562,14 @@ class AssertionFinder $third_arg = $expr->getArgs()[2]->value ?? null; if ($third_arg instanceof PhpParser\Node\Expr\ConstFetch) { - if (!in_array(strtolower($third_arg->name->parts[0]), ['true', 'false'])) { + if (!in_array(strtolower($third_arg->name->getFirst()), ['true', 'false'])) { return []; } - $third_arg_value = strtolower($third_arg->name->parts[0]); + $third_arg_value = strtolower($third_arg->name->getFirst()); } else { $third_arg_value = $expr->name instanceof PhpParser\Node\Name - && strtolower($expr->name->parts[0]) === 'is_subclass_of' + && strtolower($expr->name->getFirst()) === 'is_subclass_of' ? 'true' : 'false'; } @@ -3532,18 +3596,18 @@ class AssertionFinder ) { $class_node = $second_arg->class; - if ($class_node->parts === ['static']) { + if ($class_node->getParts() === ['static']) { if ($this_class_name) { $object = new TNamedObject($this_class_name, true); $if_types[$first_var_name] = [[new IsAClass($object, $third_arg_value === 'true')]]; } - } elseif ($class_node->parts === ['self']) { + } elseif ($class_node->getParts() === ['self']) { if ($this_class_name) { $object = new TNamedObject($this_class_name); $if_types[$first_var_name] = [[new IsAClass($object, $third_arg_value === 'true')]]; } - } elseif ($class_node->parts === ['parent']) { + } elseif ($class_node->getParts() === ['parent']) { // do nothing } else { $object = new TNamedObject( diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php index 509acb41..76c7073c 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php @@ -981,17 +981,23 @@ class AssignmentAnalyzer $context->references_to_external_scope[$lhs_var_id] = true; } if (strpos($rhs_var_id, '->') !== false) { - IssueBuffer::maybeAdd(new UnsupportedPropertyReferenceUsage( - new CodeLocation($statements_analyzer->getSource(), $stmt), - )); + IssueBuffer::maybeAdd( + new UnsupportedPropertyReferenceUsage( + new CodeLocation($statements_analyzer->getSource(), $stmt), + ), + $statements_analyzer->getSuppressedIssues(), + ); // Reference to object property, we always consider object properties to be an external scope for references // TODO handle differently so it's detected as unused if the object is unused? $context->references_to_external_scope[$lhs_var_id] = true; } if (strpos($rhs_var_id, '::') !== false) { - IssueBuffer::maybeAdd(new UnsupportedPropertyReferenceUsage( - new CodeLocation($statements_analyzer->getSource(), $stmt), - )); + IssueBuffer::maybeAdd( + new UnsupportedPropertyReferenceUsage( + new CodeLocation($statements_analyzer->getSource(), $stmt), + ), + $statements_analyzer->getSuppressedIssues(), + ); } $lhs_location = new CodeLocation($statements_analyzer->getSource(), $stmt->var); diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ArithmeticOpAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ArithmeticOpAnalyzer.php index 9be82c7c..36ae21d6 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ArithmeticOpAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ArithmeticOpAnalyzer.php @@ -815,11 +815,9 @@ class ArithmeticOpAnalyzer if ($right_type_part instanceof TLiteralInt) { $literal_value_max = $right_type_part->value - 1; if ($always_positive) { - $result_type = new Union([new TIntRange(0, $literal_value_max)]); + $result_type = Type::getIntRange(0, $literal_value_max); } else { - $result_type = new Union( - [new TIntRange(-$literal_value_max, $literal_value_max)], - ); + $result_type = Type::getIntRange(-$literal_value_max, $literal_value_max); } } else { if ($always_positive) { @@ -830,7 +828,7 @@ class ArithmeticOpAnalyzer } } else { $result_type = Type::combineUnionTypes( - $always_positive ? new Union([new TIntRange(1, null)]) : Type::getInt(true), + $always_positive ? Type::getIntRange(1, null) : Type::getInt(true), $result_type, ); } @@ -1072,7 +1070,7 @@ class ArithmeticOpAnalyzer $min_value = $calculated_min_type !== null ? $calculated_min_type->getSingleIntLiteral()->value : null; $max_value = $calculated_max_type !== null ? $calculated_max_type->getSingleIntLiteral()->value : null; - $new_result_type = new Union([new TIntRange($min_value, $max_value)]); + $new_result_type = Type::getIntRange($min_value, $max_value); $result_type = Type::combineUnionTypes($new_result_type, $result_type); } @@ -1122,7 +1120,7 @@ class ArithmeticOpAnalyzer $min_value = min($x_1 * $y_1, $x_1 * $y_2, $x_2 * $y_1, $x_2 * $y_2); $max_value = max($x_1 * $y_1, $x_1 * $y_2, $x_2 * $y_1, $x_2 * $y_2); - $new_result_type = new Union([new TIntRange($min_value, $max_value)]); + $new_result_type = Type::getIntRange($min_value, $max_value); } elseif ($right_type_part->isPositiveOrZero() && $left_type_part->isPositiveOrZero()) { // both operands are positive, result will be only positive $min_operand1 = $left_type_part->min_bound; @@ -1156,7 +1154,7 @@ class ArithmeticOpAnalyzer $min_value = $calculated_min_type !== null ? $calculated_min_type->getSingleIntLiteral()->value : null; $max_value = $calculated_max_type !== null ? $calculated_max_type->getSingleIntLiteral()->value : null; - $new_result_type = new Union([new TIntRange($min_value, $max_value)]); + $new_result_type = Type::getIntRange($min_value, $max_value); } elseif ($right_type_part->isPositiveOrZero() && $left_type_part->isNegativeOrZero()) { // one operand is negative, result will be negative and we have to check min vs max $min_operand1 = $left_type_part->max_bound; @@ -1194,7 +1192,7 @@ class ArithmeticOpAnalyzer [$min_value, $max_value] = [$max_value, $min_value]; } - $new_result_type = new Union([new TIntRange($min_value, $max_value)]); + $new_result_type = Type::getIntRange($min_value, $max_value); } elseif ($right_type_part->isNegativeOrZero() && $left_type_part->isPositiveOrZero()) { // one operand is negative, result will be negative and we have to check min vs max $min_operand1 = $left_type_part->min_bound; @@ -1232,7 +1230,7 @@ class ArithmeticOpAnalyzer [$min_value, $max_value] = [$max_value, $min_value]; } - $new_result_type = new Union([new TIntRange($min_value, $max_value)]); + $new_result_type = Type::getIntRange($min_value, $max_value); } elseif ($right_type_part->isNegativeOrZero() && $left_type_part->isNegativeOrZero()) { // both operand are negative, result will be positive $min_operand1 = $left_type_part->max_bound; @@ -1266,7 +1264,7 @@ class ArithmeticOpAnalyzer $min_value = $calculated_min_type !== null ? $calculated_min_type->getSingleIntLiteral()->value : null; $max_value = $calculated_max_type !== null ? $calculated_max_type->getSingleIntLiteral()->value : null; - $new_result_type = new Union([new TIntRange($min_value, $max_value)]); + $new_result_type = Type::getIntRange($min_value, $max_value); } else { $new_result_type = Type::getInt(true); } @@ -1283,7 +1281,7 @@ class ArithmeticOpAnalyzer //If Pow second operand is negative, the result will be float, if it's 0, it will be 1/-1, else positive if ($left_type_part->isPositive()) { if ($right_type_part->isPositive()) { - $new_result_type = new Union([new TIntRange(1, null)]); + $new_result_type = Type::getIntRange(1, null); } elseif ($right_type_part->isNegative()) { $new_result_type = Type::getFloat(); } elseif ($right_type_part->min_bound === 0 && $right_type_part->max_bound === 0) { @@ -1296,9 +1294,9 @@ class ArithmeticOpAnalyzer if ($right_type_part->isPositive()) { if ($right_type_part->min_bound === $right_type_part->max_bound) { if ($right_type_part->max_bound % 2 === 0) { - $new_result_type = new Union([new TIntRange(1, null)]); + $new_result_type = Type::getIntRange(1, null); } else { - $new_result_type = new Union([new TIntRange(null, -1)]); + $new_result_type = Type::getIntRange(null, -1); } } else { $new_result_type = Type::getInt(true); @@ -1330,7 +1328,7 @@ class ArithmeticOpAnalyzer if ($right_type_part->min_bound === $right_type_part->max_bound && $right_type_part->max_bound % 2 === 0 ) { - $new_result_type = new Union([new TIntRange(1, null)]); + $new_result_type = Type::getIntRange(1, null); } else { $new_result_type = Type::getInt(true); } @@ -1361,18 +1359,18 @@ class ArithmeticOpAnalyzer if ($left_type_part->isPositiveOrZero()) { if ($right_type_part->isPositive()) { $max = $right_type_part->min_bound - 1; - $new_result_type = new Union([new TIntRange(0, $max)]); + $new_result_type = Type::getIntRange(0, $max); } else { $max = $right_type_part->min_bound + 1; - $new_result_type = new Union([new TIntRange($max, 0)]); + $new_result_type = Type::getIntRange($max, 0); } } elseif ($left_type_part->isNegativeOrZero()) { if ($right_type_part->isPositive()) { $max = $right_type_part->min_bound - 1; - $new_result_type = new Union([new TIntRange(-$max, 0)]); + $new_result_type = Type::getIntRange(-$max, 0); } else { $max = $right_type_part->min_bound + 1; - $new_result_type = new Union([new TIntRange(-$max, 0)]); + $new_result_type = Type::getIntRange(-$max, 0); } } else { if ($right_type_part->isPositive()) { @@ -1380,7 +1378,7 @@ class ArithmeticOpAnalyzer } else { $max = -$right_type_part->min_bound - 1; } - $new_result_type = new Union([new TIntRange(-$max, $max)]); + $new_result_type = Type::getIntRange(-$max, $max); } } } elseif ($right_type_part->isPositive()) { @@ -1394,15 +1392,15 @@ class ArithmeticOpAnalyzer $new_result_type = Type::getListKey(); } } elseif ($left_type_part->isNegativeOrZero()) { - $new_result_type = new Union([new TIntRange(null, 0)]); + $new_result_type = Type::getIntRange(null, 0); } else { $new_result_type = Type::getInt(true); } } elseif ($right_type_part->isNegative()) { if ($left_type_part->isPositiveOrZero()) { - $new_result_type = new Union([new TIntRange(null, 0)]); + $new_result_type = Type::getIntRange(null, 0); } elseif ($left_type_part->isNegativeOrZero()) { - $new_result_type = new Union([new TIntRange(null, 0)]); + $new_result_type = Type::getIntRange(null, 0); } else { $new_result_type = Type::getInt(true); } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php index 58e8ad5a..da8e3794 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php @@ -261,7 +261,7 @@ class BinaryOpAnalyzer || $stmt instanceof PhpParser\Node\Expr\BinaryOp\NotIdentical) && $stmt->left instanceof PhpParser\Node\Expr\FuncCall && $stmt->left->name instanceof PhpParser\Node\Name - && $stmt->left->name->parts === ['substr'] + && $stmt->left->name->getParts() === ['substr'] && isset($stmt->left->getArgs()[1]) && $stmt_right_type && $stmt_right_type->hasLiteralString() diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php index c9fdc523..653ffedc 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php @@ -268,7 +268,12 @@ class ArgumentsAnalyzer $inferred_arg_type = $statements_analyzer->node_data->getType($arg->value); - if (null !== $inferred_arg_type && null !== $template_result && null !== $param && null !== $param->type) { + if (null !== $inferred_arg_type + && null !== $template_result + && null !== $param + && null !== $param->type + && !$arg->unpack + ) { $codebase = $statements_analyzer->getCodebase(); TemplateStandinTypeReplacer::fillTemplateResult( diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php index 7ecfff03..21bdf3f9 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php @@ -102,7 +102,7 @@ class FunctionCallAnalyzer extends CallAnalyzer && isset($stmt->getArgs()[0]) && !$stmt->getArgs()[0]->unpack ) { - $original_function_id = implode('\\', $function_name->parts); + $original_function_id = implode('\\', $function_name->getParts()); if ($original_function_id === 'call_user_func') { $other_args = array_slice($stmt->getArgs(), 1); @@ -160,7 +160,7 @@ class FunctionCallAnalyzer extends CallAnalyzer $set_inside_conditional = false; if ($function_name instanceof PhpParser\Node\Name - && $function_name->parts === ['assert'] + && $function_name->getParts() === ['assert'] && !$context->inside_conditional ) { $context->inside_conditional = true; @@ -235,7 +235,10 @@ class FunctionCallAnalyzer extends CallAnalyzer $function_call_info->function_id, ); - $template_result->lower_bounds += $already_inferred_lower_bounds; + $template_result->lower_bounds = array_merge( + $template_result->lower_bounds, + $already_inferred_lower_bounds, + ); if ($function_name instanceof PhpParser\Node\Name && $function_call_info->function_id) { $stmt_type = FunctionCallReturnTypeFetcher::fetch( @@ -319,7 +322,7 @@ class FunctionCallAnalyzer extends CallAnalyzer } if ($function_name instanceof PhpParser\Node\Name - && $function_name->parts === ['assert'] + && $function_name->getParts() === ['assert'] && isset($stmt->getArgs()[0]) ) { self::processAssertFunctionEffects( @@ -437,7 +440,7 @@ class FunctionCallAnalyzer extends CallAnalyzer $codebase = $statements_analyzer->getCodebase(); $codebase_functions = $codebase->functions; - $original_function_id = implode('\\', $function_name->parts); + $original_function_id = $function_name->toString(); if (!$function_name instanceof PhpParser\Node\Name\FullyQualified) { $function_call_info->function_id = $codebase_functions->getFullyQualifiedFunctionNameFromString( @@ -487,7 +490,7 @@ class FunctionCallAnalyzer extends CallAnalyzer $is_predefined = true; $is_maybe_root_function = !$function_name instanceof PhpParser\Node\Name\FullyQualified - && count($function_name->parts) === 1; + && count($function_name->getParts()) === 1; $args = $stmt->isFirstClassCallable() ? [] : $stmt->getArgs(); diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallReturnTypeFetcher.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallReturnTypeFetcher.php index 7941941c..34dae01f 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallReturnTypeFetcher.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallReturnTypeFetcher.php @@ -383,7 +383,7 @@ class FunctionCallReturnTypeFetcher if ($min === $max) { return new Union([new TLiteralInt($max)]); } - return new Union([new TIntRange($min, $max)]); + return Type::getIntRange($min, $max); } if ($atomic_types['array'] instanceof TArray diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php index b521f8bc..45476ca2 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php @@ -58,7 +58,6 @@ use Psalm\Type\Union; use function array_map; use function array_values; -use function implode; use function in_array; use function md5; use function preg_match; @@ -94,7 +93,7 @@ class NewAnalyzer extends CallAnalyzer } if ($stmt->class instanceof PhpParser\Node\Name) { - if (!in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true)) { + if (!in_array(strtolower($stmt->class->getFirst()), ['self', 'static', 'parent'], true)) { $aliases = $statements_analyzer->getAliases(); if ($context->calling_method_id @@ -102,7 +101,7 @@ class NewAnalyzer extends CallAnalyzer ) { $codebase->file_reference_provider->addMethodReferenceToClassMember( $context->calling_method_id, - 'use:' . $stmt->class->parts[0] . ':' . md5($statements_analyzer->getFilePath()), + 'use:' . $stmt->class->getFirst() . ':' . md5($statements_analyzer->getFilePath()), false, ); } @@ -114,7 +113,7 @@ class NewAnalyzer extends CallAnalyzer $fq_class_name = $codebase->classlikes->getUnAliasedName($fq_class_name); } elseif ($context->self !== null) { - switch ($stmt->class->parts[0]) { + switch ($stmt->class->getFirst()) { case 'self': $class_storage = $codebase->classlike_storage_provider->get($context->self); $fq_class_name = $class_storage->name; @@ -152,7 +151,7 @@ class NewAnalyzer extends CallAnalyzer . ($stmt->class instanceof PhpParser\Node\Name\FullyQualified ? '\\' : $statements_analyzer->getNamespace() . '-') - . implode('\\', $stmt->class->parts), + . $stmt->class->toString(), ); } } elseif ($stmt->class instanceof PhpParser\Node\Stmt\Class_) { @@ -174,7 +173,7 @@ class NewAnalyzer extends CallAnalyzer if ($fq_class_name) { if ($codebase->alter_code && $stmt->class instanceof PhpParser\Node\Name - && !in_array($stmt->class->parts[0], ['parent', 'static']) + && !in_array($stmt->class->getFirst(), ['parent', 'static']) ) { $codebase->classlikes->handleClassLikeReferenceInMigration( $codebase, diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php index a79f2760..fa7cc498 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php @@ -56,10 +56,10 @@ class StaticCallAnalyzer extends CallAnalyzer if ($stmt->class instanceof PhpParser\Node\Name) { $fq_class_name = null; - if (count($stmt->class->parts) === 1 - && in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true) + if (count($stmt->class->getParts()) === 1 + && in_array(strtolower($stmt->class->getFirst()), ['self', 'static', 'parent'], true) ) { - if ($stmt->class->parts[0] === 'parent') { + if ($stmt->class->getFirst() === 'parent') { $child_fq_class_name = $context->self; $class_storage = $child_fq_class_name @@ -84,7 +84,7 @@ class StaticCallAnalyzer extends CallAnalyzer $fq_class_name = $class_storage->name; } elseif ($context->self) { - if ($stmt->class->parts[0] === 'static' && isset($context->vars_in_scope['$this'])) { + if ($stmt->class->getFirst() === 'static' && isset($context->vars_in_scope['$this'])) { $fq_class_name = (string) $context->vars_in_scope['$this']; $lhs_type = $context->vars_in_scope['$this']; } else { @@ -93,7 +93,7 @@ class StaticCallAnalyzer extends CallAnalyzer } else { return !IssueBuffer::accepts( new NonStaticSelfCall( - 'Cannot use ' . $stmt->class->parts[0] . ' outside class context', + 'Cannot use ' . $stmt->class->getFirst() . ' outside class context', new CodeLocation($statements_analyzer->getSource(), $stmt), ), $statements_analyzer->getSuppressedIssues(), @@ -111,7 +111,7 @@ class StaticCallAnalyzer extends CallAnalyzer ) { $codebase->file_reference_provider->addMethodReferenceToClassMember( $context->calling_method_id, - 'use:' . $stmt->class->parts[0] . ':' . md5($statements_analyzer->getFilePath()), + 'use:' . $stmt->class->getFirst() . ':' . md5($statements_analyzer->getFilePath()), false, ); } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php index 52a87e9a..b0839345 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php @@ -99,8 +99,8 @@ class AtomicStaticCallAnalyzer $statements_analyzer->getSuppressedIssues(), new ClassLikeNameOptions( $stmt->class instanceof PhpParser\Node\Name - && count($stmt->class->parts) === 1 - && in_array(strtolower($stmt->class->parts[0]), ['self', 'static'], true), + && count($stmt->class->getParts()) === 1 + && in_array(strtolower($stmt->class->getFirst()), ['self', 'static'], true), ), )) { return; @@ -284,7 +284,7 @@ class AtomicStaticCallAnalyzer && $fq_class_name && !$moved_call && $stmt->class instanceof PhpParser\Node\Name - && !in_array($stmt->class->parts[0], ['parent', 'static']) + && !in_array($stmt->class->getFirst(), ['parent', 'static']) ) { $codebase->classlikes->handleClassLikeReferenceInMigration( $codebase, @@ -293,7 +293,7 @@ class AtomicStaticCallAnalyzer $fq_class_name, $context->calling_method_id, false, - $stmt->class->parts[0] === 'self', + $stmt->class->getFirst() === 'self', ); } } @@ -718,7 +718,7 @@ class AtomicStaticCallAnalyzer if ($pseudo_method_storage->return_type) { return true; } - } elseif ($stmt->class instanceof PhpParser\Node\Name && $stmt->class->parts[0] === 'parent' + } elseif ($stmt->class instanceof PhpParser\Node\Name && $stmt->class->getFirst() === 'parent' && !$codebase->methodExists($method_id) && !$statements_analyzer->isStatic() ) { @@ -846,7 +846,7 @@ class AtomicStaticCallAnalyzer } if ((!$stmt->class instanceof PhpParser\Node\Name - || $stmt->class->parts[0] !== 'parent' + || $stmt->class->getFirst() !== 'parent' || $statements_analyzer->isStatic()) && ( !$context->self @@ -857,7 +857,7 @@ class AtomicStaticCallAnalyzer MethodAnalyzer::checkStatic( $method_id, ($stmt->class instanceof PhpParser\Node\Name - && strtolower($stmt->class->parts[0]) === 'self') + && strtolower($stmt->class->getFirst()) === 'self') || $context->self === $fq_class_name, !$statements_analyzer->isStatic(), $codebase, diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php index 0a604e08..607f5218 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php @@ -156,7 +156,7 @@ class ExistingAtomicStaticCallAnalyzer if ($found_generic_params && $stmt->class instanceof PhpParser\Node\Name - && $stmt->class->parts === ['parent'] + && $stmt->class->getParts() === ['parent'] && $context->self && ($self_class_storage = $codebase->classlike_storage_provider->get($context->self)) && $self_class_storage->template_extended_params @@ -201,7 +201,7 @@ class ExistingAtomicStaticCallAnalyzer return; } - $fq_class_name = $stmt->class instanceof PhpParser\Node\Name && $stmt->class->parts === ['parent'] + $fq_class_name = $stmt->class instanceof PhpParser\Node\Name && $stmt->class->getParts() === ['parent'] ? (string) $statements_analyzer->getFQCLN() : $fq_class_name; @@ -371,7 +371,7 @@ class ExistingAtomicStaticCallAnalyzer $new_fq_class_name, $context->calling_method_id, strtolower($old_declaring_fq_class_name) !== strtolower($new_fq_class_name), - $stmt->class->parts[0] === 'self', + $stmt->class->getFirst() === 'self', )) { $moved_call = true; } @@ -519,8 +519,8 @@ class ExistingAtomicStaticCallAnalyzer $lhs_type_part->defining_class, ); } elseif ($stmt->class instanceof PhpParser\Node\Name - && count($stmt->class->parts) === 1 - && in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true) + && count($stmt->class->getParts()) === 1 + && in_array(strtolower($stmt->class->getFirst()), ['self', 'static', 'parent'], true) && $lhs_type_part instanceof TNamedObject && $context->self ) { diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php index 348f528c..a547b291 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php @@ -505,7 +505,7 @@ class CallAnalyzer && $callable_arg->left->class instanceof Name && $callable_arg->left->name instanceof Identifier && strtolower($callable_arg->left->name->name) === 'class' - && !in_array(strtolower($callable_arg->left->class->parts[0]), ['self', 'static', 'parent']) + && !in_array(strtolower($callable_arg->left->class->getFirst()), ['self', 'static', 'parent']) && $callable_arg->right instanceof PhpParser\Node\Scalar\String_ && preg_match('/^::[A-Za-z0-9]+$/', $callable_arg->right->value) ) { diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/ClassConstAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/ClassConstAnalyzer.php index 0af910bd..2dec200f 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/ClassConstAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/ClassConstAnalyzer.php @@ -72,7 +72,7 @@ class ClassConstAnalyzer $statements_analyzer->node_data->setType($stmt, Type::getMixed()); if ($stmt->class instanceof PhpParser\Node\Name) { - $first_part_lc = strtolower($stmt->class->parts[0]); + $first_part_lc = strtolower($stmt->class->getFirst()); if ($first_part_lc === 'self' || $first_part_lc === 'static') { if (!$context->self) { @@ -128,7 +128,7 @@ class ClassConstAnalyzer $moved_class = false; if ($codebase->alter_code - && !in_array($stmt->class->parts[0], ['parent', 'static']) + && !in_array($stmt->class->getFirst(), ['parent', 'static']) ) { $moved_class = $codebase->classlikes->handleClassLikeReferenceInMigration( $codebase, @@ -137,7 +137,7 @@ class ClassConstAnalyzer $fq_class_name, $context->calling_method_id, false, - $stmt->class->parts[0] === 'self', + $stmt->class->getFirst() === 'self', ); } @@ -259,7 +259,7 @@ class ClassConstAnalyzer $class_visibility, $statements_analyzer, [], - $stmt->class->parts[0] === "static", + $stmt->class->getFirst() === "static", ); } catch (InvalidArgumentException $_) { return true; diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/ExpressionIdentifier.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/ExpressionIdentifier.php index 04b808c3..53794faa 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/ExpressionIdentifier.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/ExpressionIdentifier.php @@ -33,11 +33,11 @@ class ExpressionIdentifier && $stmt->name instanceof PhpParser\Node\Identifier && $stmt->class instanceof PhpParser\Node\Name ) { - if (count($stmt->class->parts) === 1 - && in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true) + if (count($stmt->class->getParts()) === 1 + && in_array(strtolower($stmt->class->getFirst()), ['self', 'static', 'parent'], true) ) { if (!$this_class_name) { - $fq_class_name = $stmt->class->parts[0]; + $fq_class_name = $stmt->class->getFirst(); } else { $fq_class_name = $this_class_name; } @@ -47,7 +47,7 @@ class ExpressionIdentifier $stmt->class, $source->getAliases(), ) - : implode('\\', $stmt->class->parts); + : implode('\\', $stmt->class->getParts()); } return $fq_class_name . '::$' . $stmt->name->name; @@ -124,7 +124,7 @@ class ExpressionIdentifier ) { $offset = '$' . $stmt->dim->name; } elseif ($stmt->dim instanceof PhpParser\Node\Expr\ConstFetch) { - $offset = implode('\\', $stmt->dim->name->parts); + $offset = implode('\\', $stmt->dim->name->getParts()); } elseif ($stmt->dim instanceof PhpParser\Node\Expr\PropertyFetch) { $object_id = self::getExtendedVarId($stmt->dim->var, $this_class_name, $source); @@ -134,7 +134,7 @@ class ExpressionIdentifier } elseif ($stmt->dim instanceof PhpParser\Node\Expr\ClassConstFetch && $stmt->dim->name instanceof PhpParser\Node\Identifier && $stmt->dim->class instanceof PhpParser\Node\Name - && $stmt->dim->class->parts[0] === 'static' + && $stmt->dim->class->getFirst() === 'static' ) { $offset = 'static::' . $stmt->dim->name; } elseif ($stmt->dim diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ConstFetchAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ConstFetchAnalyzer.php index 3ae0ead2..8b30a60f 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ConstFetchAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ConstFetchAnalyzer.php @@ -16,7 +16,6 @@ use Psalm\Internal\Provider\NodeDataProvider; use Psalm\Issue\UndefinedConstant; use Psalm\IssueBuffer; use Psalm\Type; -use Psalm\Type\Atomic\TIntRange; use Psalm\Type\Union; use ReflectionProperty; @@ -36,7 +35,7 @@ class ConstFetchAnalyzer PhpParser\Node\Expr\ConstFetch $stmt, Context $context ): void { - $const_name = implode('\\', $stmt->name->parts); + $const_name = $stmt->name->toString(); switch (strtolower($const_name)) { case 'null': @@ -175,7 +174,7 @@ class ConstFetchAnalyzer case 'PHP_INT_SIZE': case 'PHP_MAXPATHLEN': case 'PHP_VERSION_ID': - return new Union([new TIntRange(1, null)]); + return Type::getIntRange(1, null); case 'PHP_FLOAT_EPSILON': case 'PHP_FLOAT_MAX': diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/StaticPropertyFetchAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/StaticPropertyFetchAnalyzer.php index 84ab1558..46a4cf0f 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/StaticPropertyFetchAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/StaticPropertyFetchAnalyzer.php @@ -51,10 +51,10 @@ class StaticPropertyFetchAnalyzer $codebase = $statements_analyzer->getCodebase(); - if (count($stmt->class->parts) === 1 - && in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true) + if (count($stmt->class->getParts()) === 1 + && in_array(strtolower($stmt->class->getFirst()), ['self', 'static', 'parent'], true) ) { - if ($stmt->class->parts[0] === 'parent') { + if ($stmt->class->getFirst() === 'parent') { $fq_class_name = $statements_analyzer->getParentFQCLN(); if ($fq_class_name === null) { @@ -81,7 +81,7 @@ class StaticPropertyFetchAnalyzer ) { $codebase->file_reference_provider->addMethodReferenceToClassMember( $context->calling_method_id, - 'use:' . $stmt->class->parts[0] . ':' . md5($statements_analyzer->getFilePath()), + 'use:' . $stmt->class->getFirst() . ':' . md5($statements_analyzer->getFilePath()), false, ); } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/VariableFetchAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/VariableFetchAnalyzer.php index 98e911a0..80ad5e0e 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/VariableFetchAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/VariableFetchAnalyzer.php @@ -783,7 +783,7 @@ class VariableFetchAnalyzer 'type' => $str, 'tmp_name' => $str, 'size' => Type::getListKey(), - 'error' => new Union([new TIntRange(0, 8)]), + 'error' => Type::getIntRange(0, 8), ]; if ($files_full_path) { diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php index cfa4326c..e293afab 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php @@ -335,7 +335,7 @@ class IncludeAnalyzer } } elseif ($stmt instanceof PhpParser\Node\Expr\FuncCall && $stmt->name instanceof PhpParser\Node\Name && - $stmt->name->parts === ['dirname'] + $stmt->name->getParts() === ['dirname'] ) { if ($stmt->getArgs()) { $dir_level = 1; @@ -369,10 +369,14 @@ class IncludeAnalyzer return null; } + if ($dir_level < 1) { + return null; + } + return dirname($evaled_path, $dir_level); } } elseif ($stmt instanceof PhpParser\Node\Expr\ConstFetch) { - $const_name = implode('', $stmt->name->parts); + $const_name = implode('', $stmt->name->getParts()); if (defined($const_name)) { $constant_value = constant($const_name); diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/InstanceofAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/InstanceofAnalyzer.php index 380279b7..83b04cd9 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/InstanceofAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/InstanceofAnalyzer.php @@ -39,7 +39,7 @@ class InstanceofAnalyzer if (ExpressionAnalyzer::analyze($statements_analyzer, $stmt->class, $context) === false) { return false; } - } elseif (!in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true)) { + } elseif (!in_array(strtolower($stmt->class->getFirst()), ['self', 'static', 'parent'], true)) { if ($context->check_classes) { $codebase = $statements_analyzer->getCodebase(); @@ -62,7 +62,7 @@ class InstanceofAnalyzer . ($stmt->class instanceof PhpParser\Node\Name\FullyQualified ? '\\' : $statements_analyzer->getNamespace() . '-') - . implode('\\', $stmt->class->parts), + . implode('\\', $stmt->class->getParts()), ); } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/MagicConstAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/MagicConstAnalyzer.php index f439a59b..129266f9 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/MagicConstAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/MagicConstAnalyzer.php @@ -29,7 +29,7 @@ class MagicConstAnalyzer Context $context ): void { if ($stmt instanceof PhpParser\Node\Scalar\MagicConst\Line) { - $statements_analyzer->node_data->setType($stmt, Type::getInt()); + $statements_analyzer->node_data->setType($stmt, Type::getIntRange(1, null)); } elseif ($stmt instanceof PhpParser\Node\Scalar\MagicConst\Class_) { $codebase = $statements_analyzer->getCodebase(); diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php index 91ec38b4..a76a1990 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php @@ -78,11 +78,11 @@ class MatchAnalyzer if (!$switch_var_id) { if ($stmt->cond instanceof PhpParser\Node\Expr\FuncCall && $stmt->cond->name instanceof PhpParser\Node\Name - && ($stmt->cond->name->parts === ['get_class'] - || $stmt->cond->name->parts === ['gettype'] - || $stmt->cond->name->parts === ['get_debug_type'] - || $stmt->cond->name->parts === ['count'] - || $stmt->cond->name->parts === ['sizeof']) + && ($stmt->cond->name->getParts() === ['get_class'] + || $stmt->cond->name->getParts() === ['gettype'] + || $stmt->cond->name->getParts() === ['get_debug_type'] + || $stmt->cond->name->getParts() === ['count'] + || $stmt->cond->name->getParts() === ['sizeof']) && $stmt->cond->getArgs() ) { $first_arg = $stmt->cond->getArgs()[0]; diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/SimpleTypeInferer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/SimpleTypeInferer.php index 3ba14ca6..ab144621 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/SimpleTypeInferer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/SimpleTypeInferer.php @@ -260,7 +260,7 @@ class SimpleTypeInferer } if ($stmt instanceof PhpParser\Node\Expr\ConstFetch) { - $name = strtolower($stmt->name->parts[0]); + $name = strtolower($stmt->name->getFirst()); if ($name === 'false') { return Type::getFalse(); } @@ -273,7 +273,7 @@ class SimpleTypeInferer return Type::getNull(); } - if ($stmt->name->parts[0] === '__NAMESPACE__') { + if ($stmt->name->getFirst() === '__NAMESPACE__') { return Type::getString($aliases->namespace); } @@ -287,7 +287,7 @@ class SimpleTypeInferer } if ($stmt instanceof PhpParser\Node\Scalar\MagicConst\Line) { - return Type::getInt(); + return Type::getIntRange(1, null); } if ($stmt instanceof PhpParser\Node\Scalar\MagicConst\Class_ @@ -306,18 +306,18 @@ class SimpleTypeInferer if ($stmt->class instanceof PhpParser\Node\Name && $stmt->name instanceof PhpParser\Node\Identifier && $fq_classlike_name - && $stmt->class->parts !== ['static'] - && $stmt->class->parts !== ['parent'] + && $stmt->class->getParts() !== ['static'] + && $stmt->class->getParts() !== ['parent'] ) { if (isset($existing_class_constants[$stmt->name->name]) && $existing_class_constants[$stmt->name->name]->type ) { - if ($stmt->class->parts === ['self']) { + if ($stmt->class->getParts() === ['self']) { return $existing_class_constants[$stmt->name->name]->type; } } - if ($stmt->class->parts === ['self']) { + if ($stmt->class->getParts() === ['self']) { $const_fq_class_name = $fq_classlike_name; } else { $const_fq_class_name = ClassLikeAnalyzer::getFQCLNFromNameObject( diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/UnsetAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/UnsetAnalyzer.php index 5299d8d6..b1c12d12 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/UnsetAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/UnsetAnalyzer.php @@ -6,6 +6,7 @@ use PhpParser; use Psalm\Context; use Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier; use Psalm\Internal\Analyzer\StatementsAnalyzer; +use Psalm\Type; use Psalm\Type\Atomic\TArray; use Psalm\Type\Atomic\TIntRange; use Psalm\Type\Atomic\TKeyedArray; @@ -90,7 +91,7 @@ class UnsetAnalyzer if ($atomic_root_type->is_list && !$is_list && is_int($key_value)) { if ($key_value === 0) { - $list_key = new Union([new TIntRange(1, null)]); + $list_key = Type::getIntRange(1, null); } elseif ($key_value === 1) { $list_key = new Union([ new TLiteralInt(0), diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php index 2b43d085..f1d4044b 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php @@ -304,7 +304,7 @@ class StatementsAnalyzer extends SourceAnalyzer } elseif ($stmt instanceof PhpParser\Node\Stmt\Expression && $stmt->expr instanceof PhpParser\Node\Expr\FuncCall && $stmt->expr->name instanceof PhpParser\Node\Name - && $stmt->expr->name->parts === ['define'] + && $stmt->expr->name->getParts() === ['define'] && isset($stmt->expr->getArgs()[1]) ) { $const_name = ConstFetchAnalyzer::getConstName( diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Cache.php b/vendor/vimeo/psalm/src/Psalm/Internal/Cache.php new file mode 100644 index 00000000..88e2f570 --- /dev/null +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Cache.php @@ -0,0 +1,128 @@ +config = $config; + $this->use_igbinary = $config->use_igbinary; + } + + /** + * @return array|object|string|null + */ + public function getItem(string $path) + { + if (!file_exists($path)) { + return null; + } + + $cache = Providers::safeFileGetContents($path); + if ($cache === '') { + return null; + } + + if ($this->config->compressor === 'deflate') { + $inflated = @gzinflate($cache); + } elseif ($this->config->compressor === 'lz4') { + /** + * @psalm-suppress UndefinedFunction + * @var string|false $inflated + */ + $inflated = lz4_uncompress($cache); + } else { + $inflated = $cache; + } + + // invalid cache data + if ($inflated === false) { + $this->deleteItem($path); + + return null; + } + + if ($this->use_igbinary) { + /** @var object|false $unserialized */ + $unserialized = @igbinary_unserialize($inflated); + } else { + /** @var object|false $unserialized */ + $unserialized = @unserialize($inflated); + } + + if ($unserialized === false) { + $this->deleteItem($path); + + return null; + } + + return $unserialized; + } + + public function deleteItem(string $path): void + { + if (@is_writable($path)) { + @unlink($path); + } + } + + /** + * @param array|object|string $item + */ + public function saveItem(string $path, $item): void + { + if ($this->use_igbinary) { + $serialized = igbinary_serialize($item); + } else { + $serialized = serialize($item); + } + + if ($this->config->compressor === 'deflate') { + $compressed = gzdeflate($serialized); + } elseif ($this->config->compressor === 'lz4') { + /** + * @psalm-suppress UndefinedFunction + * @var string|false $compressed + */ + $compressed = lz4_compress($serialized, 4); + } else { + $compressed = $serialized; + } + + if ($compressed !== false) { + file_put_contents($path, $compressed, LOCK_EX); + } + // TODO: Error handling + } + + public function getCacheDirectory(): ?string + { + return $this->config->getCacheDirectory(); + } +} diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Cli/LanguageServer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Cli/LanguageServer.php index 429144b6..07d5e6f9 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Cli/LanguageServer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Cli/LanguageServer.php @@ -10,6 +10,7 @@ use Psalm\Internal\Fork\PsalmRestarter; use Psalm\Internal\IncludeCollector; use Psalm\Internal\LanguageServer\ClientConfiguration; use Psalm\Internal\LanguageServer\LanguageServer as LanguageServerLanguageServer; +use Psalm\Internal\LanguageServer\PathMapper; use Psalm\Report; use function array_key_exists; @@ -18,6 +19,7 @@ use function array_search; use function array_slice; use function chdir; use function error_log; +use function explode; use function fwrite; use function gc_disable; use function getcwd; @@ -31,6 +33,7 @@ use function is_string; use function preg_replace; use function realpath; use function setlocale; +use function strlen; use function strpos; use function strtolower; use function substr; @@ -75,6 +78,7 @@ final class LanguageServer 'find-dead-code', 'help', 'root:', + 'map-folder::', 'use-ini-defaults', 'version', 'tcp:', @@ -127,6 +131,14 @@ final class LanguageServer // get options from command line $options = getopt(implode('', $valid_short_options), $valid_long_options); + if ($options === false) { + // shouldn't really happen, but just in case + fwrite( + STDERR, + 'Failed to get CLI args' . PHP_EOL, + ); + exit(1); + } if (!array_key_exists('use-ini-defaults', $options)) { ini_set('display_errors', '1'); @@ -169,6 +181,14 @@ final class LanguageServer -r, --root If running Psalm globally you'll need to specify a project root. Defaults to cwd + --map-folder[=SERVER_FOLDER:CLIENT_FOLDER] + Specify folder to map between the client and the server. Use this when the client + and server have different views of the filesystem (e.g. in a docker container). + Defaults to mapping the rootUri provided by the client to the server's cwd, + or `-r` if provided. + + No mapping is done when this option is not specified. + --find-dead-code Look for dead code @@ -291,6 +311,8 @@ final class LanguageServer setlocale(LC_CTYPE, 'C'); + $path_mapper = self::createPathMapper($options, $current_dir); + $path_to_config = CliUtils::getPathToConfig($options); if (isset($options['tcp'])) { @@ -394,6 +416,49 @@ final class LanguageServer $clientConfiguration->TCPServerAddress = $options['tcp'] ?? null; $clientConfiguration->TCPServerMode = isset($options['tcp-server']); - LanguageServerLanguageServer::run($config, $clientConfiguration, $current_dir, $inMemory); + LanguageServerLanguageServer::run($config, $clientConfiguration, $current_dir, $path_mapper, $inMemory); + } + + /** @param array> $options */ + private static function createPathMapper(array $options, string $server_start_dir): PathMapper + { + if (!isset($options['map-folder'])) { + // dummy no-op mapper + return new PathMapper('/', '/'); + } + + $map_folder = $options['map-folder']; + + if ($map_folder === false) { + // autoconfigured mapper + return new PathMapper($server_start_dir, null); + } + + if (is_string($map_folder)) { + if (strpos($map_folder, ':') === false) { + fwrite( + STDERR, + 'invalid format for --map-folder option' . PHP_EOL, + ); + exit(1); + } + /** @psalm-suppress PossiblyUndefinedArrayOffset we just checked that we have the separator*/ + [$server_dir, $client_dir] = explode(':', $map_folder, 2); + if (!strlen($server_dir) || !strlen($client_dir)) { + fwrite( + STDERR, + 'invalid format for --map-folder option, ' + . 'neither SERVER_FOLDER nor CLIENT_FOLDER can be empty' . PHP_EOL, + ); + exit(1); + } + return new PathMapper($server_dir, $client_dir); + } + + fwrite( + STDERR, + '--map-folder option can only be specified once' . PHP_EOL, + ); + exit(1); } } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Cli/Psalm.php b/vendor/vimeo/psalm/src/Psalm/Internal/Cli/Psalm.php index 7401cd1e..4df6a9dd 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Cli/Psalm.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Cli/Psalm.php @@ -166,6 +166,7 @@ final class Psalm /** * @param array $argv + * @psalm-suppress ComplexMethod Maybe some of the option handling could be moved to its own function... */ public static function run(array $argv): void { @@ -183,6 +184,14 @@ final class Psalm throw new RuntimeException('Failed to parse CLI options'); } + // debug CI environment + if (!array_key_exists('debug', $options) + && 'true' === getenv('GITHUB_ACTIONS') + && '1' === getenv('RUNNER_DEBUG') + ) { + $options['debug'] = false; + } + self::forwardCliCall($options, $argv); self::validateCliArguments($args); @@ -403,7 +412,24 @@ final class Psalm { return isset($options['output-format']) && is_string($options['output-format']) ? $options['output-format'] - : Report::TYPE_CONSOLE; + : self::findDefaultOutputFormat(); + } + + /** + * @return Report::TYPE_* + */ + private static function findDefaultOutputFormat(): string + { + $emulator = getenv('TERMINAL_EMULATOR'); + if (is_string($emulator) && substr($emulator, 0, 9) === 'JetBrains') { + return Report::TYPE_PHP_STORM; + } + + if ('true' === getenv('GITHUB_ACTIONS')) { + return Report::TYPE_GITHUB_ACTIONS; + } + + return Report::TYPE_CONSOLE; } private static function initShowInfo(array $options): bool diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php index 7b2a8b97..ba0209ea 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php @@ -687,6 +687,16 @@ class Analyzer } } + // This could be optimized by storing method references to files + foreach ($file_reference_provider->getDeletedReferencedFiles() as $deleted_file) { + foreach ($file_reference_provider->getFilesReferencingFile($deleted_file) as $file_referencing_deleted) { + $methods_referencing_deleted = $this->analyzed_methods[$file_referencing_deleted] ?? []; + foreach ($methods_referencing_deleted as $method_referencing_deleted => $_) { + $newly_invalidated_methods[$method_referencing_deleted] = true; + } + } + } + foreach ($newly_invalidated_methods as $method_id => $_) { foreach ($method_references_to_class_members as $i => $_) { unset($method_references_to_class_members[$i][$method_id]); @@ -1552,13 +1562,13 @@ class Analyzer $has_info = false; foreach ($issues as $issue) { - if ($issue->severity === 'error') { - $has_error = true; - break; - } - - if ($issue->severity === 'info') { - $has_info = true; + switch ($issue->severity) { + case IssueData::SEVERITY_INFO: + $has_info = true; + break; + default: + $has_error = true; + break; } } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/ClassLikes.php b/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/ClassLikes.php index 696b0413..15953d98 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/ClassLikes.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/ClassLikes.php @@ -2347,15 +2347,31 @@ class ClassLikes $existing_classes, ] = $thread_data; - $this->existing_classlikes_lc = array_merge($existing_classlikes_lc, $this->existing_classlikes_lc); - $this->existing_classes_lc = array_merge($existing_classes_lc, $this->existing_classes_lc); - $this->existing_traits_lc = array_merge($existing_traits_lc, $this->existing_traits_lc); - $this->existing_traits = array_merge($existing_traits, $this->existing_traits); - $this->existing_enums_lc = array_merge($existing_enums_lc, $this->existing_enums_lc); - $this->existing_enums = array_merge($existing_enums, $this->existing_enums); - $this->existing_interfaces_lc = array_merge($existing_interfaces_lc, $this->existing_interfaces_lc); - $this->existing_interfaces = array_merge($existing_interfaces, $this->existing_interfaces); - $this->existing_classes = array_merge($existing_classes, $this->existing_classes); + $this->existing_classlikes_lc = self::mergeThreadData($existing_classlikes_lc, $this->existing_classlikes_lc); + $this->existing_classes_lc = self::mergeThreadData($existing_classes_lc, $this->existing_classes_lc); + $this->existing_traits_lc = self::mergeThreadData($existing_traits_lc, $this->existing_traits_lc); + $this->existing_traits = self::mergeThreadData($existing_traits, $this->existing_traits); + $this->existing_enums_lc = self::mergeThreadData($existing_enums_lc, $this->existing_enums_lc); + $this->existing_enums = self::mergeThreadData($existing_enums, $this->existing_enums); + $this->existing_interfaces_lc = self::mergeThreadData($existing_interfaces_lc, $this->existing_interfaces_lc); + $this->existing_interfaces = self::mergeThreadData($existing_interfaces, $this->existing_interfaces); + $this->existing_classes = self::mergeThreadData($existing_classes, $this->existing_classes); + } + + /** + * @template T as string|lowercase-string + * @param array $old + * @param array $new + * @return array + */ + private static function mergeThreadData(array $old, array $new): array + { + foreach ($new as $name => $value) { + if (!isset($old[$name]) || (!$old[$name] && $value)) { + $old[$name] = $value; + } + } + return $old; } public function getStorageFor(string $fq_class_name): ?ClassLikeStorage diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Methods.php b/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Methods.php index a67a1d38..ff78e684 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Methods.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Methods.php @@ -8,6 +8,7 @@ use Psalm\CodeLocation; use Psalm\Codebase; use Psalm\Context; use Psalm\Internal\Analyzer\SourceAnalyzer; +use Psalm\Internal\Analyzer\Statements\Expression\Call\ClassTemplateParamCollector; use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer; use Psalm\Internal\Analyzer\StatementsAnalyzer; use Psalm\Internal\MethodIdentifier; @@ -18,6 +19,8 @@ use Psalm\Internal\Provider\MethodParamsProvider; use Psalm\Internal\Provider\MethodReturnTypeProvider; use Psalm\Internal\Provider\MethodVisibilityProvider; use Psalm\Internal\Type\Comparator\UnionTypeComparator; +use Psalm\Internal\Type\TemplateInferredTypeReplacer; +use Psalm\Internal\Type\TemplateResult; use Psalm\Internal\Type\TypeExpander; use Psalm\Internal\TypeVisitor\TypeLocalizer; use Psalm\StatementsSource; @@ -768,11 +771,26 @@ class Methods $candidate_type, ); - if (((!$old_contained_by_new && !$new_contained_by_old) - || ($old_contained_by_new && $new_contained_by_old)) - && !$candidate_type->hasTemplate() - && !$overridden_storage_return_type->hasTemplate() + if ((!$old_contained_by_new && !$new_contained_by_old) + || ($old_contained_by_new && $new_contained_by_old) ) { + $found_generic_params = ClassTemplateParamCollector::collect( + $source_analyzer->getCodebase(), + $appearing_fq_class_storage, + $appearing_fq_class_storage, + $appearing_method_name, + null, + true, + ); + + if ($found_generic_params) { + $overridden_storage_return_type = TemplateInferredTypeReplacer::replace( + $overridden_storage_return_type, + new TemplateResult([], $found_generic_params), + $source_analyzer->getCodebase(), + ); + } + $attempted_intersection = null; if ($old_contained_by_new) { //implicitly $new_contained_by_old as well try { diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Diff/ClassStatementsDiffer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Diff/ClassStatementsDiffer.php index 686aeb92..5bc637b4 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Diff/ClassStatementsDiffer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Diff/ClassStatementsDiffer.php @@ -158,6 +158,22 @@ class ClassStatementsDiffer extends AstDiffer return false; } + if ($a->type xor $b->type) { + return false; + } + + if ($a->type && $b->type) { + $a_type_start = (int) $a->type->getAttribute('startFilePos'); + $a_type_end = (int) $a->type->getAttribute('endFilePos'); + $b_type_start = (int) $b->type->getAttribute('startFilePos'); + $b_type_end = (int) $b->type->getAttribute('endFilePos'); + if (substr($a_code, $a_type_start, $a_type_end - $a_type_start + 1) + !== substr($b_code, $b_type_start, $b_type_end - $b_type_start + 1) + ) { + return false; + } + } + $body_change = substr($a_code, $a_comments_end, $a_end - $a_comments_end) !== substr($b_code, $b_comments_end, $b_end - $b_comments_end); } else { diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Diff/FileStatementsDiffer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Diff/FileStatementsDiffer.php index d1864043..797b6f73 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Diff/FileStatementsDiffer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Diff/FileStatementsDiffer.php @@ -129,7 +129,7 @@ class FileStatementsDiffer extends AstDiffer if ($use->alias) { $add_or_delete[] = 'use:' . (string) $use->alias; } else { - $name_parts = $use->name->parts; + $name_parts = $use->name->getParts(); $add_or_delete[] = 'use:' . end($name_parts); } @@ -156,7 +156,7 @@ class FileStatementsDiffer extends AstDiffer if ($use->alias) { $add_or_delete[] = 'use:' . (string) $use->alias; } else { - $name_parts = $use->name->parts; + $name_parts = $use->name->getParts(); $add_or_delete[] = 'use:' . end($name_parts); } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Diff/NamespaceStatementsDiffer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Diff/NamespaceStatementsDiffer.php index 4232a405..cfeab612 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Diff/NamespaceStatementsDiffer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Diff/NamespaceStatementsDiffer.php @@ -114,7 +114,7 @@ class NamespaceStatementsDiffer extends AstDiffer if ($use->alias) { $add_or_delete[] = 'use:' . (string) $use->alias; } else { - $name_parts = $use->name->parts; + $name_parts = $use->name->getParts(); $add_or_delete[] = 'use:' . end($name_parts); } @@ -128,7 +128,7 @@ class NamespaceStatementsDiffer extends AstDiffer if ($use->alias) { $add_or_delete[] = 'use:' . (string) $use->alias; } else { - $name_parts = $use->name->parts; + $name_parts = $use->name->getParts(); $add_or_delete[] = 'use:' . end($name_parts); } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Fork/Pool.php b/vendor/vimeo/psalm/src/Psalm/Internal/Fork/Pool.php index 1d097b19..09e525dd 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Fork/Pool.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Fork/Pool.php @@ -98,6 +98,7 @@ class Pool * @param array> $process_task_data_iterator * An array of task data items to be divided up among the * workers. The size of this is the number of forked processes. + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint * @param Closure $startup_closure * A closure to execute upon starting a child * @param Closure(int, mixed):mixed $task_closure diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Client/Progress/LegacyProgress.php b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Client/Progress/LegacyProgress.php new file mode 100644 index 00000000..13eba280 --- /dev/null +++ b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Client/Progress/LegacyProgress.php @@ -0,0 +1,83 @@ +handler = $handler; + } + + public function begin(string $title, ?string $message = null, ?int $percentage = null): void + { + + if ($this->status === self::STATUS_ACTIVE) { + throw new LogicException('Progress has already been started'); + } + + if ($this->status === self::STATUS_FINISHED) { + throw new LogicException('Progress has already been finished'); + } + + $this->title = $title; + + $this->notify($message); + + $this->status = self::STATUS_ACTIVE; + } + + public function update(?string $message = null, ?int $percentage = null): void + { + if ($this->status === self::STATUS_FINISHED) { + throw new LogicException('Progress has already been finished'); + } + + if ($this->status === self::STATUS_INACTIVE) { + throw new LogicException('Progress has not been started yet'); + } + + $this->notify($message); + } + + public function end(?string $message = null): void + { + if ($this->status === self::STATUS_FINISHED) { + throw new LogicException('Progress has already been finished'); + } + + if ($this->status === self::STATUS_INACTIVE) { + throw new LogicException('Progress has not been started yet'); + } + + $this->notify($message); + + $this->status = self::STATUS_FINISHED; + } + + private function notify(?string $message): void + { + $this->handler->notify( + 'telemetry/event', + new LogMessage( + MessageType::INFO, + $this->title . (empty($message) ? '' : (': ' . $message)), + ), + ); + } +} diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Client/Progress/Progress.php b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Client/Progress/Progress.php new file mode 100644 index 00000000..8a1ca5da --- /dev/null +++ b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Client/Progress/Progress.php @@ -0,0 +1,121 @@ +handler = $handler; + $this->token = $token; + } + + public function begin( + string $title, + ?string $message = null, + ?int $percentage = null + ): void { + if ($this->status === self::STATUS_ACTIVE) { + throw new LogicException('Progress has already been started'); + } + + if ($this->status === self::STATUS_FINISHED) { + throw new LogicException('Progress has already been finished'); + } + + $notification = [ + 'token' => $this->token, + 'value' => [ + 'kind' => 'begin', + 'title' => $title, + ], + ]; + + if ($message !== null) { + $notification['value']['message'] = $message; + } + + if ($percentage !== null) { + $notification['value']['percentage'] = $percentage; + $this->withPercentage = true; + } + + $this->handler->notify('$/progress', $notification); + + $this->status = self::STATUS_ACTIVE; + } + + public function end(?string $message = null): void + { + if ($this->status === self::STATUS_FINISHED) { + throw new LogicException('Progress has already been finished'); + } + + if ($this->status === self::STATUS_INACTIVE) { + throw new LogicException('Progress has not been started yet'); + } + + $notification = [ + 'token' => $this->token, + 'value' => [ + 'kind' => 'end', + ], + ]; + + if ($message !== null) { + $notification['value']['message'] = $message; + } + + $this->handler->notify('$/progress', $notification); + + $this->status = self::STATUS_FINISHED; + } + + public function update(?string $message = null, ?int $percentage = null): void + { + if ($this->status === self::STATUS_FINISHED) { + throw new LogicException('Progress has already been finished'); + } + + if ($this->status === self::STATUS_INACTIVE) { + throw new LogicException('Progress has not been started yet'); + } + + $notification = [ + 'token' => $this->token, + 'value' => [ + 'kind' => 'report', + ], + ]; + + if ($message !== null) { + $notification['value']['message'] = $message; + } + + if ($percentage !== null) { + if (!$this->withPercentage) { + throw new LogicException( + 'Cannot update percentage for progress ' + . 'that was started without percentage', + ); + } + $notification['value']['percentage'] = $percentage; + } + + $this->handler->notify('$/progress', $notification); + } +} diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Client/Progress/ProgressInterface.php b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Client/Progress/ProgressInterface.php new file mode 100644 index 00000000..78f045c2 --- /dev/null +++ b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Client/Progress/ProgressInterface.php @@ -0,0 +1,16 @@ +server->clientCapabilities; - if ($capabilities && $capabilities->workspace && $capabilities->workspace->configuration) { + if ($capabilities->workspace->configuration ?? false) { $this->workspace->requestConfiguration('psalm')->onResolve(function ($error, $value): void { if ($error) { $this->server->logError('There was an error getting configuration'); @@ -131,6 +134,15 @@ class LanguageClient ); } + public function makeProgress(string $token): ProgressInterface + { + if ($this->server->clientCapabilities->window->workDoneProgress ?? false) { + return new Progress($this->handler, $token); + } else { + return new LegacyProgress($this->handler); + } + } + /** * Configuration Refreshed from Client * diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/LanguageServer.php b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/LanguageServer.php index daec34e8..cc358753 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/LanguageServer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/LanguageServer.php @@ -88,6 +88,7 @@ use function stream_socket_server; use function strpos; use function substr; use function trim; +use function uniqid; use function urldecode; use const JSON_PRETTY_PRINT; @@ -142,13 +143,16 @@ class LanguageServer extends Dispatcher */ protected JsonMapper $mapper; + protected PathMapper $path_mapper; + public function __construct( ProtocolReader $reader, ProtocolWriter $writer, ProjectAnalyzer $project_analyzer, Codebase $codebase, ClientConfiguration $clientConfiguration, - Progress $progress + Progress $progress, + PathMapper $path_mapper ) { parent::__construct($this, '/'); @@ -158,6 +162,8 @@ class LanguageServer extends Dispatcher $this->codebase = $codebase; + $this->path_mapper = $path_mapper; + $this->protocolWriter = $writer; $this->protocolReader = $reader; @@ -240,6 +246,7 @@ class LanguageServer extends Dispatcher $this->client = new LanguageClient($reader, $writer, $this, $clientConfiguration); + $this->logInfo("Psalm Language Server ".PSALM_VERSION." has started."); } @@ -250,6 +257,7 @@ class LanguageServer extends Dispatcher Config $config, ClientConfiguration $clientConfiguration, string $base_dir, + PathMapper $path_mapper, bool $inMemory = false ): void { $progress = new Progress(); @@ -322,6 +330,7 @@ class LanguageServer extends Dispatcher $codebase, $clientConfiguration, $progress, + $path_mapper, ); Loop::run(); } elseif ($clientConfiguration->TCPServerMode && $clientConfiguration->TCPServerAddress) { @@ -345,6 +354,7 @@ class LanguageServer extends Dispatcher $codebase, $clientConfiguration, $progress, + $path_mapper, ); Loop::run(); } @@ -358,6 +368,7 @@ class LanguageServer extends Dispatcher $codebase, $clientConfiguration, $progress, + $path_mapper, ); Loop::run(); } @@ -367,38 +378,36 @@ class LanguageServer extends Dispatcher * The initialize request is sent as the first request from the client to the server. * * @param ClientCapabilities $capabilities The capabilities provided by the client (editor) - * @param int|null $processId The process Id of the parent process that started the server. * Is null if the process has not been started by another process. If the parent process is * not alive then the server should exit (see exit notification) its process. * @param ClientInfo|null $clientInfo Information about the client - * @param string|null $locale The locale the client is currently showing the user interface - * in. This must not necessarily be the locale of the operating - * system. - * @param string|null $rootPath The rootPath of the workspace. Is null if no folder is open. - * @param mixed $initializationOptions * @param string|null $trace The initial trace setting. If omitted trace is disabled ('off'). + * @param string|null $workDoneToken The token to be used to report progress during init. * @psalm-return Promise - * @psalm-suppress PossiblyUnusedParam */ public function initialize( ClientCapabilities $capabilities, - ?int $processId = null, ?ClientInfo $clientInfo = null, - ?string $locale = null, - ?string $rootPath = null, ?string $rootUri = null, - $initializationOptions = null, - ?string $trace = null - //?array $workspaceFolders = null //error in json-dispatcher + ?string $trace = null, + ?string $workDoneToken = null ): Promise { $this->clientInfo = $clientInfo; $this->clientCapabilities = $capabilities; $this->trace = $trace; + + + if ($rootUri !== null) { + $this->path_mapper->configureClientRoot($this->getPathPart($rootUri)); + } + return call( /** @return Generator */ - function () { + function () use ($workDoneToken) { + $progress = $this->client->makeProgress($workDoneToken ?? uniqid('tkn', true)); + $this->logInfo("Initializing..."); - $this->clientStatus('initializing'); + $progress->begin('Psalm', 'initializing'); // Eventually, this might block on something. Leave it as a generator. /** @psalm-suppress TypeDoesNotContainType */ @@ -409,14 +418,14 @@ class LanguageServer extends Dispatcher $this->project_analyzer->serverMode($this); $this->logInfo("Initializing: Getting code base..."); - $this->clientStatus('initializing', 'getting code base'); + $progress->update('getting code base'); $this->logInfo("Initializing: Scanning files ({$this->project_analyzer->threads} Threads)..."); - $this->clientStatus('initializing', 'scanning files'); + $progress->update('scanning files'); $this->codebase->scanFiles($this->project_analyzer->threads); $this->logInfo("Initializing: Registering stub files..."); - $this->clientStatus('initializing', 'registering stub files'); + $progress->update('registering stub files'); $this->codebase->config->visitStubFiles($this->codebase, $this->project_analyzer->progress); if ($this->textDocument === null) { @@ -538,11 +547,7 @@ class LanguageServer extends Dispatcher * * @since LSP 3.16.0 */ - if ($this->clientCapabilities && - $this->clientCapabilities->textDocument && - $this->clientCapabilities->textDocument->publishDiagnostics && - $this->clientCapabilities->textDocument->publishDiagnostics->dataSupport - ) { + if ($this->clientCapabilities->textDocument->publishDiagnostics->dataSupport ?? false) { $serverCapabilities->codeActionProvider = true; } @@ -560,7 +565,7 @@ class LanguageServer extends Dispatcher } $this->logInfo("Initializing: Complete."); - $this->clientStatus('initialized'); + $progress->end('initialized'); /** * Information about the server. @@ -728,10 +733,9 @@ class LanguageServer extends Dispatcher new Position($end_line - 1, $end_column - 1), ); switch ($severity) { - case Config::REPORT_INFO: + case IssueData::SEVERITY_INFO: $diagnostic_severity = DiagnosticSeverity::WARNING; break; - case Config::REPORT_ERROR: default: $diagnostic_severity = DiagnosticSeverity::ERROR; break; @@ -758,11 +762,7 @@ class LanguageServer extends Dispatcher * * @since LSP 3.16.0 */ - if ($this->clientCapabilities !== null && - $this->clientCapabilities->textDocument && - $this->clientCapabilities->textDocument->publishDiagnostics && - $this->clientCapabilities->textDocument->publishDiagnostics->codeDescriptionSupport - ) { + if ($this->clientCapabilities->textDocument->publishDiagnostics->codeDescriptionSupport ?? false) { $diagnostic->codeDescription = new CodeDescription($issue_data->link); } @@ -788,7 +788,7 @@ class LanguageServer extends Dispatcher ); if ($position !== false) { - $issue_data->severity = Config::REPORT_INFO; + $issue_data->severity = IssueData::SEVERITY_INFO; /** @psalm-suppress MixedArgument */ array_splice($issue_baseline[$file][$type]['s'], $position, 1); /** @psalm-suppress MixedArrayAssignment, MixedOperand, MixedAssignment */ @@ -797,7 +797,7 @@ class LanguageServer extends Dispatcher } else { /** @psalm-suppress MixedArrayAssignment */ $issue_baseline[$file][$type]['s'] = []; - $issue_data->severity = Config::REPORT_INFO; + $issue_data->severity = IssueData::SEVERITY_INFO; /** @psalm-suppress MixedArrayAssignment, MixedOperand, MixedAssignment */ $issue_baseline[$file][$type]['o']--; } @@ -806,7 +806,7 @@ class LanguageServer extends Dispatcher }, $data[$file_path] ?? []), function (IssueData $issue_data) { //Hide Warnings - if ($issue_data->severity === Config::REPORT_INFO && + if ($issue_data->severity === IssueData::SEVERITY_INFO && $this->client->clientConfiguration->hideWarnings ) { return false; @@ -957,12 +957,15 @@ class LanguageServer extends Dispatcher /** * Transforms an absolute file path into a URI as used by the language server protocol. - * - * @psalm-pure */ - public static function pathToUri(string $filepath): string + public function pathToUri(string $filepath): string { - $filepath = trim(str_replace('\\', '/', $filepath), '/'); + $filepath = str_replace('\\', '/', $filepath); + + $filepath = $this->path_mapper->mapServerToClient($oldpath = $filepath); + $this->logDebug('Translated path to URI', ['from' => $oldpath, 'to' => $filepath]); + + $filepath = trim($filepath, '/'); $parts = explode('/', $filepath); // Don't %-encode the colon after a Windows drive letter $first = array_shift($parts); @@ -979,7 +982,29 @@ class LanguageServer extends Dispatcher /** * Transforms URI into file path */ - public static function uriToPath(string $uri): string + public function uriToPath(string $uri): string + { + $filepath = urldecode($this->getPathPart($uri)); + + if (strpos($filepath, ':') !== false) { + if ($filepath[0] === '/') { + $filepath = substr($filepath, 1); + } + $filepath = str_replace('/', '\\', $filepath); + } + + $filepath = $this->path_mapper->mapClientToServer($oldpath = $filepath); + $this->logDebug('Translated URI to path', ['from' => $oldpath, 'to' => $filepath]); + + $realpath = realpath($filepath); + if ($realpath !== false) { + return $realpath; + } + + return $filepath; + } + + private function getPathPart(string $uri): string { $fragments = parse_url($uri); if ($fragments === false @@ -989,21 +1014,21 @@ class LanguageServer extends Dispatcher ) { throw new InvalidArgumentException("Not a valid file URI: $uri"); } + return $fragments['path']; + } - $filepath = urldecode($fragments['path']); + // the methods below forward special paths + // like `$/cancelRequest` to `$this->cancelRequest()` + // and `$/a/b/c` to `$this->a->b->c()` - if (strpos($filepath, ':') !== false) { - if ($filepath[0] === '/') { - $filepath = substr($filepath, 1); - } - $filepath = str_replace('/', '\\', $filepath); - } + public function __isset(string $prop_name): bool + { + return $prop_name === '$'; + } - $realpath = realpath($filepath); - if ($realpath !== false) { - return $realpath; - } - - return $filepath; + /** @return static */ + public function __get(string $_prop_name): self + { + return $this; } } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/PathMapper.php b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/PathMapper.php new file mode 100644 index 00000000..bd4b815b --- /dev/null +++ b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/PathMapper.php @@ -0,0 +1,61 @@ +server_root = $this->sanitizeFolderPath($server_root); + $this->client_root = $this->sanitizeFolderPath($client_root); + } + + public function configureClientRoot(string $client_root): void + { + // ignore if preconfigured + if ($this->client_root === null) { + $this->client_root = $this->sanitizeFolderPath($client_root); + } + } + + public function mapClientToServer(string $client_path): string + { + if ($this->client_root === null) { + return $client_path; + } + + if (substr($client_path, 0, strlen($this->client_root)) === $this->client_root) { + return $this->server_root . substr($client_path, strlen($this->client_root)); + } + + return $client_path; + } + + public function mapServerToClient(string $server_path): string + { + if ($this->client_root === null) { + return $server_path; + } + if (substr($server_path, 0, strlen($this->server_root)) === $this->server_root) { + return $this->client_root . substr($server_path, strlen($this->server_root)); + } + return $server_path; + } + + /** @return ($path is null ? null : string) */ + private function sanitizeFolderPath(?string $path): ?string + { + if ($path === null) { + return $path; + } + return rtrim($path, '/'); + } +} diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/FileReferenceCacheProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/FileReferenceCacheProvider.php index 79d54534..ca12912e 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/FileReferenceCacheProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/FileReferenceCacheProvider.php @@ -62,7 +62,7 @@ class FileReferenceCacheProvider extends InternalFileReferenceCacheProvider public function __construct(Config $config) { - $this->config = $config; + parent::__construct($config); } public function getCachedFileReferences(): ?array diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/FileStorageCacheProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/FileStorageCacheProvider.php index c91ffcc1..8841cf40 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/FileStorageCacheProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/FileStorageCacheProvider.php @@ -19,30 +19,24 @@ class FileStorageCacheProvider extends InternalFileStorageCacheProvider { } - public function writeToCache(FileStorage $storage, string $file_contents): void + /** + * @param lowercase-string $file_path + */ + protected function storeInCache(string $file_path, FileStorage $storage): void { - $file_path = strtolower($storage->file_path); $this->cache[$file_path] = $storage; } - public function getLatestFromCache(string $file_path, string $file_contents): ?FileStorage - { - $cached_value = $this->loadFromCache(strtolower($file_path)); - - if (!$cached_value) { - return null; - } - - return $cached_value; - } - public function removeCacheForFile(string $file_path): void { unset($this->cache[strtolower($file_path)]); } - private function loadFromCache(string $file_path): ?FileStorage + /** + * @param lowercase-string $file_path + */ + protected function loadFromCache(string $file_path): ?FileStorage { - return $this->cache[strtolower($file_path)] ?? null; + return $this->cache[$file_path] ?? null; } } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Server/TextDocument.php b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Server/TextDocument.php index b9c4bcca..508af5ae 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Server/TextDocument.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Server/TextDocument.php @@ -74,7 +74,7 @@ class TextDocument ['version' => $textDocument->version, 'uri' => $textDocument->uri], ); - $file_path = LanguageServer::uriToPath($textDocument->uri); + $file_path = $this->server->uriToPath($textDocument->uri); $this->codebase->removeTemporaryFileChanges($file_path); $this->codebase->file_provider->openFile($file_path); @@ -97,7 +97,7 @@ class TextDocument ['uri' => (array) $textDocument], ); - $file_path = LanguageServer::uriToPath($textDocument->uri); + $file_path = $this->server->uriToPath($textDocument->uri); // reopen file $this->codebase->removeTemporaryFileChanges($file_path); @@ -119,7 +119,7 @@ class TextDocument ['version' => $textDocument->version, 'uri' => $textDocument->uri], ); - $file_path = LanguageServer::uriToPath($textDocument->uri); + $file_path = $this->server->uriToPath($textDocument->uri); if (count($contentChanges) === 1 && isset($contentChanges[0]) && $contentChanges[0]->range === null) { $new_content = $contentChanges[0]->text; @@ -154,7 +154,7 @@ class TextDocument ['uri' => $textDocument->uri], ); - $file_path = LanguageServer::uriToPath($textDocument->uri); + $file_path = $this->server->uriToPath($textDocument->uri); $this->codebase->file_provider->closeFile($file_path); $this->server->client->textDocument->publishDiagnostics($textDocument->uri, []); @@ -178,7 +178,7 @@ class TextDocument 'textDocument/definition', ); - $file_path = LanguageServer::uriToPath($textDocument->uri); + $file_path = $this->server->uriToPath($textDocument->uri); //This currently doesnt work right with out of project files if (!$this->codebase->config->isInProjectDirs($file_path)) { @@ -205,7 +205,7 @@ class TextDocument return new Success( new Location( - LanguageServer::pathToUri($code_location->file_path), + $this->server->pathToUri($code_location->file_path), new Range( new Position($code_location->getLineNumber() - 1, $code_location->getColumn() - 1), new Position($code_location->getEndLineNumber() - 1, $code_location->getEndColumn() - 1), @@ -232,7 +232,7 @@ class TextDocument 'textDocument/hover', ); - $file_path = LanguageServer::uriToPath($textDocument->uri); + $file_path = $this->server->uriToPath($textDocument->uri); //This currently doesnt work right with out of project files if (!$this->codebase->config->isInProjectDirs($file_path)) { @@ -288,7 +288,7 @@ class TextDocument 'textDocument/completion', ); - $file_path = LanguageServer::uriToPath($textDocument->uri); + $file_path = $this->server->uriToPath($textDocument->uri); //This currently doesnt work right with out of project files if (!$this->codebase->config->isInProjectDirs($file_path)) { @@ -301,12 +301,8 @@ class TextDocument [$recent_type, $gap, $offset] = $completion_data; if ($gap === '->' || $gap === '::') { - $snippetSupport = ($this->server->clientCapabilities && - $this->server->clientCapabilities->textDocument && - $this->server->clientCapabilities->textDocument->completion && - $this->server->clientCapabilities->textDocument->completion->completionItem && - $this->server->clientCapabilities->textDocument->completion->completionItem->snippetSupport) - ? true : false; + $snippetSupport = $this->server->clientCapabilities + ->textDocument->completion->completionItem->snippetSupport ?? false; $completion_items = $this->codebase->getCompletionItemsForClassishThing($recent_type, $gap, $snippetSupport); } elseif ($gap === '[') { @@ -360,7 +356,7 @@ class TextDocument 'textDocument/signatureHelp', ); - $file_path = LanguageServer::uriToPath($textDocument->uri); + $file_path = $this->server->uriToPath($textDocument->uri); //This currently doesnt work right with out of project files if (!$this->codebase->config->isInProjectDirs($file_path)) { @@ -402,10 +398,8 @@ class TextDocument * The code action request is sent from the client to the server to compute commands * for a given text document and range. These commands are typically code fixes to * either fix problems or to beautify/refactor code. - * - * @psalm-suppress PossiblyUnusedParam */ - public function codeAction(TextDocumentIdentifier $textDocument, Range $range, CodeActionContext $context): Promise + public function codeAction(TextDocumentIdentifier $textDocument, CodeActionContext $context): Promise { if (!$this->server->client->clientConfiguration->provideCodeActions) { return new Success(null); @@ -415,7 +409,7 @@ class TextDocument 'textDocument/codeAction', ); - $file_path = LanguageServer::uriToPath($textDocument->uri); + $file_path = $this->server->uriToPath($textDocument->uri); //Don't report code actions for files we arent watching if (!$this->codebase->config->isInProjectDirs($file_path)) { @@ -431,12 +425,12 @@ class TextDocument /** @var array{type: string, snippet: string, line_from: int, line_to: int} */ $data = (array)$diagnostic->data; - //$file_path = LanguageServer::uriToPath($textDocument->uri); + //$file_path = $this->server->uriToPath($textDocument->uri); //$contents = $this->codebase->file_provider->getContents($file_path); $snippetRange = new Range( - new Position($data['line_from']-1), - new Position($data['line_to']), + new Position($data['line_from'] - 1, 0), + new Position($data['line_to'], 0), ); $indentation = ''; diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Server/Workspace.php b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Server/Workspace.php index af49619c..6d2e1622 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Server/Workspace.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Server/Workspace.php @@ -63,7 +63,7 @@ class Workspace $realFiles = array_filter( array_map(function (FileEvent $change) { try { - return LanguageServer::uriToPath($change->uri); + return $this->server->uriToPath($change->uri); } catch (InvalidArgumentException $e) { return null; } @@ -79,7 +79,7 @@ class Workspace } foreach ($changes as $change) { - $file_path = LanguageServer::uriToPath($change->uri); + $file_path = $this->server->uriToPath($change->uri); if ($composerLockFile === $file_path) { continue; @@ -108,10 +108,9 @@ class Workspace /** * A notification sent from the client to the server to signal the change of configuration settings. * - * @param mixed $settings - * @psalm-suppress PossiblyUnusedMethod, PossiblyUnusedParam + * @psalm-suppress PossiblyUnusedMethod */ - public function didChangeConfiguration($settings): void + public function didChangeConfiguration(): void { $this->server->logDebug( 'workspace/didChangeConfiguration', @@ -140,7 +139,7 @@ class Workspace case 'psalm.analyze.uri': /** @var array{uri: string} */ $arguments = (array) $arguments; - $file = LanguageServer::uriToPath($arguments['uri']); + $file = $this->server->uriToPath($arguments['uri']); $this->codebase->reloadFiles( $this->project_analyzer, [$file], diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php b/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php index 2bc9d718..fae0c8da 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php @@ -839,10 +839,15 @@ class ClassLikeNodeScanner $classlike_storage->properties[$property_name] = new PropertyStorage(); } - $classlike_storage->properties[$property_name]->type = $property_type; - $property_id = $fq_classlike_name . '::$' . $property_name; + if ($property_id === 'DateInterval::$days') { + /** @psalm-suppress InaccessibleProperty We just parsed this type */ + $property_type->ignore_falsable_issues = true; + } + + $classlike_storage->properties[$property_name]->type = $property_type; + $classlike_storage->declaring_property_ids[$property_name] = $fq_classlike_name; $classlike_storage->appearing_property_ids[$property_name] = $property_id; } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php b/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php index 20c75007..ac05615b 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionResolver.php @@ -32,10 +32,12 @@ use Psalm\Internal\Scanner\UnresolvedConstantComponent; use ReflectionClass; use ReflectionFunction; +use function array_merge; +use function array_values; use function assert; use function class_exists; use function function_exists; -use function implode; +use function get_defined_constants; use function in_array; use function interface_exists; use function strtolower; @@ -139,7 +141,7 @@ class ExpressionResolver } if ($stmt instanceof PhpParser\Node\Expr\ConstFetch) { - $part0_lc = strtolower($stmt->name->parts[0]); + $part0_lc = strtolower($stmt->name->getFirst()); if ($part0_lc === 'false') { return new ScalarValue(false); } @@ -157,7 +159,7 @@ class ExpressionResolver } return new Constant( - implode('\\', $stmt->name->parts), + $stmt->name->toString(), $stmt->name instanceof PhpParser\Node\Name\FullyQualified, ); } @@ -190,13 +192,13 @@ class ExpressionResolver if ($stmt->class instanceof PhpParser\Node\Name && $stmt->name instanceof PhpParser\Node\Identifier && $fq_classlike_name - && $stmt->class->parts !== ['static'] - && ($stmt->class->parts !== ['parent'] || $parent_fq_class_name !== null) + && $stmt->class->getParts() !== ['static'] + && ($stmt->class->getParts() !== ['parent'] || $parent_fq_class_name !== null) ) { - if ($stmt->class->parts === ['self']) { + if ($stmt->class->getParts() === ['self']) { $const_fq_class_name = $fq_classlike_name; } else { - if ($stmt->class->parts === ['parent']) { + if ($stmt->class->getParts() === ['parent']) { assert($parent_fq_class_name !== null); $const_fq_class_name = $parent_fq_class_name; } else { @@ -305,15 +307,28 @@ class ExpressionResolver && $stmt->var->class instanceof PhpParser\Node\Name && $stmt->var->name instanceof PhpParser\Node\Identifier && $stmt->name instanceof PhpParser\Node\Identifier - && in_array($stmt->name->name, ['name', 'value', true]) + && in_array($stmt->name->name, ['name', 'value'], true) + && ($stmt->var->class->getParts() !== ['self'] || $fq_classlike_name !== null) + && $stmt->var->class->getParts() !== ['static'] + && ($stmt->var->class->getParts() !== ['parent'] || $parent_fq_class_name !== null) ) { - $enum_fq_class_name = ClassLikeAnalyzer::getFQCLNFromNameObject( - $stmt->var->class, - $aliases, - ); + if ($stmt->var->class->getParts() === ['self']) { + assert($fq_classlike_name !== null); + $enum_fq_class_name = $fq_classlike_name; + } else { + if ($stmt->var->class->getParts() === ['parent']) { + assert($parent_fq_class_name !== null); + $enum_fq_class_name = $parent_fq_class_name; + } else { + $enum_fq_class_name = ClassLikeAnalyzer::getFQCLNFromNameObject( + $stmt->var->class, + $aliases, + ); + } + } if ($stmt->name->name === 'value') { return new EnumValueFetch($enum_fq_class_name, $stmt->var->name->name); - } elseif ($stmt->name->name === 'name') { + } else /*if ($stmt->name->name === 'name')*/ { return new EnumNameFetch($enum_fq_class_name, $stmt->var->name->name); } } @@ -355,18 +370,18 @@ class ExpressionResolver ) && ( ( $expr->left instanceof PhpParser\Node\Expr\ConstFetch - && $expr->left->name->parts === ['PHP_VERSION_ID'] + && $expr->left->name->getParts() === ['PHP_VERSION_ID'] && $expr->right instanceof PhpParser\Node\Scalar\LNumber ) || ( $expr->right instanceof PhpParser\Node\Expr\ConstFetch - && $expr->right->name->parts === ['PHP_VERSION_ID'] + && $expr->right->name->getParts() === ['PHP_VERSION_ID'] && $expr->left instanceof PhpParser\Node\Scalar\LNumber ) ) ) { $php_version_id = $codebase->analysis_php_version_id; $evaluator = new ConstExprEvaluator(static function (Expr $expr) use ($php_version_id) { - if ($expr instanceof ConstFetch && $expr->name->parts === ['PHP_VERSION_ID']) { + if ($expr instanceof ConstFetch && $expr->name->getParts() === ['PHP_VERSION_ID']) { return $php_version_id; } throw new ConstExprEvaluationException('unexpected'); @@ -395,7 +410,7 @@ class ExpressionResolver return null; } - if ($function->name->parts === ['function_exists'] + if ($function->name->getParts() === ['function_exists'] && isset($function->getArgs()[0]) && $function->getArgs()[0]->value instanceof PhpParser\Node\Scalar\String_ && function_exists($function->getArgs()[0]->value->value) @@ -409,7 +424,7 @@ class ExpressionResolver return false; } - if ($function->name->parts === ['class_exists'] + if ($function->name->getParts() === ['class_exists'] && isset($function->getArgs()[0]) ) { $string_value = null; @@ -439,7 +454,7 @@ class ExpressionResolver return false; } - if ($function->name->parts === ['interface_exists'] + if ($function->name->getParts() === ['interface_exists'] && isset($function->getArgs()[0]) ) { $string_value = null; @@ -469,7 +484,7 @@ class ExpressionResolver return false; } - if ($function->name->parts === ['enum_exists'] + if ($function->name->getParts() === ['enum_exists'] && isset($function->getArgs()[0]) ) { $string_value = null; @@ -501,6 +516,19 @@ class ExpressionResolver return false; } + if ($function->name->getParts() === ['defined'] + && isset($function->getArgs()[0]) + && $function->getArgs()[0]->value instanceof PhpParser\Node\Scalar\String_ + ) { + $predefined_constants = get_defined_constants(true); + if (isset($predefined_constants['user'])) { + unset($predefined_constants['user']); + } + $predefined_constants = array_merge(...array_values($predefined_constants)); + + return isset($predefined_constants[$function->getArgs()[0]->value->value]); + } + return null; } } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php b/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php index d37bd9a9..696b7497 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/ExpressionScanner.php @@ -6,8 +6,10 @@ use PhpParser; use Psalm\Aliases; use Psalm\Codebase; use Psalm\Config; +use Psalm\Exception\DocblockParseException; use Psalm\Exception\FileIncludeException; use Psalm\Internal\Analyzer\ClassLikeAnalyzer; +use Psalm\Internal\Analyzer\CommentAnalyzer; use Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer; use Psalm\Internal\Analyzer\Statements\Expression\Fetch\ConstFetchAnalyzer; use Psalm\Internal\Analyzer\Statements\Expression\IncludeAnalyzer; @@ -23,7 +25,6 @@ use function assert; use function defined; use function dirname; use function explode; -use function implode; use function in_array; use function preg_match; use function strpos; @@ -80,7 +81,7 @@ class ExpressionScanner $file_storage->referenced_classlikes[strtolower($fq_classlike_name)] = $fq_classlike_name; } } elseif ($node instanceof PhpParser\Node\Expr\FuncCall && $node->name instanceof PhpParser\Node\Name) { - $function_id = implode('\\', $node->name->parts); + $function_id = $node->name->toString(); if (InternalCallMapHandler::inCallMap($function_id)) { self::registerClassMapFunctionCall( @@ -152,7 +153,29 @@ class ExpressionScanner $type_provider, $second_arg_value, $aliases, - ) ?? Type::getMixed(); + ); + + // allow docblocks to override the declared value to make constants in stubs configurable + $doc_comment = $second_arg_value->getDocComment(); + if ($doc_comment) { + try { + $var_comments = CommentAnalyzer::getTypeFromComment($doc_comment, $file_scanner, $aliases); + foreach ($var_comments as $var_comment) { + if ($var_comment->type) { + $const_type = $var_comment->type; + } + + // only check the first @var comment + break; + } + } catch (DocblockParseException $e) { + // do nothing + } + } + + if ($const_type === null) { + $const_type = Type::getMixed(); + } $config = Config::getInstance(); diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeNodeScanner.php b/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeNodeScanner.php index ed3463b9..e0ba4e34 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeNodeScanner.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeNodeScanner.php @@ -57,7 +57,6 @@ use function array_search; use function count; use function end; use function explode; -use function implode; use function in_array; use function is_string; use function spl_object_id; @@ -371,7 +370,7 @@ class FunctionLikeNodeScanner && $function_stmt->expr->expr instanceof PhpParser\Node\Expr\FuncCall && $function_stmt->expr->expr->name instanceof PhpParser\Node\Name ) { - $inner_function_id = implode('\\', $function_stmt->expr->expr->name->parts); + $inner_function_id = $function_stmt->expr->expr->name->toString(); if ($inner_function_id === 'func_get_arg' || $inner_function_id === 'func_get_args' @@ -385,7 +384,7 @@ class FunctionLikeNodeScanner && $function_stmt->cond->left->left instanceof PhpParser\Node\Expr\FuncCall && $function_stmt->cond->left->left->name instanceof PhpParser\Node\Name ) { - $inner_function_id = implode('\\', $function_stmt->cond->left->left->name->parts); + $inner_function_id = $function_stmt->cond->left->left->name->toString(); if ($inner_function_id === 'func_get_arg' || $inner_function_id === 'func_get_args' @@ -806,7 +805,7 @@ class FunctionLikeNodeScanner $param_type = null; $is_nullable = $param->default instanceof PhpParser\Node\Expr\ConstFetch && - strtolower($param->default->name->parts[0]) === 'null'; + strtolower($param->default->name->getFirst()) === 'null'; $param_typehint = $param->type; diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/TypeHintResolver.php b/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/TypeHintResolver.php index 7ae1e78e..3e5fcef5 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/TypeHintResolver.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/TypeHintResolver.php @@ -21,7 +21,6 @@ use Psalm\Type\Atomic\TNull; use Psalm\Type\Union; use UnexpectedValueException; -use function implode; use function strtolower; /** @@ -137,7 +136,7 @@ class TypeHintResolver $codebase->scanner->queueClassLikeForScanning($fq_type_string); $file_storage->referenced_classlikes[strtolower($fq_type_string)] = $fq_type_string; } else { - $lower_hint = strtolower($hint->parts[0]); + $lower_hint = strtolower($hint->getFirst()); if ($classlike_storage && ($lower_hint === 'self' || $lower_hint === 'static') @@ -149,7 +148,7 @@ class TypeHintResolver $fq_type_string .= '&static'; } } else { - $type_string = implode('\\', $hint->parts); + $type_string = $hint->toString(); $fq_type_string = ClassLikeAnalyzer::getFQCLNFromNameObject($hint, $aliases); $codebase->scanner->queueClassLikeForScanning($fq_type_string); diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php b/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php index 989bae6e..734c14d8 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php @@ -39,7 +39,6 @@ use function array_pop; use function end; use function explode; use function get_class; -use function implode; use function in_array; use function is_string; use function reset; @@ -395,7 +394,7 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements FileSour $this->namespace_name = $node->name; $this->aliases = new Aliases( - $node->name ? implode('\\', $node->name->parts) : '', + $node->name ? $node->name->toString() : '', $this->aliases->uses, $this->aliases->functions, $this->aliases->constants, @@ -414,7 +413,7 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements FileSour private function handleUse(PhpParser\Node\Stmt\Use_ $node): void { foreach ($node->uses as $use) { - $use_path = implode('\\', $use->name->parts); + $use_path = $use->name->toString(); $use_alias = $use->alias->name ?? $use->name->getLast(); @@ -445,10 +444,10 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements FileSour private function handleGroupUse(PhpParser\Node\Stmt\GroupUse $node): void { - $use_prefix = implode('\\', $node->prefix->parts); + $use_prefix = $node->prefix->toString(); foreach ($node->uses as $use) { - $use_path = $use_prefix . '\\' . implode('\\', $use->name->parts); + $use_path = $use_prefix . '\\' . $use->name->toString(); $use_alias = $use->alias->name ?? $use->name->getLast(); switch ($use->type !== PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN ? $use->type : $node->type) { @@ -490,13 +489,13 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements FileSour if ($this->codebase->register_stub_files && $node->name - && $node->name->parts === ['PHPSTORM_META'] + && $node->name->getParts() === ['PHPSTORM_META'] ) { foreach ($node->stmts as $meta_stmt) { if ($meta_stmt instanceof PhpParser\Node\Stmt\Expression && $meta_stmt->expr instanceof PhpParser\Node\Expr\FuncCall && $meta_stmt->expr->name instanceof Name - && $meta_stmt->expr->name->parts === ['override'] + && $meta_stmt->expr->name->getParts() === ['override'] ) { PhpStormMetaScanner::handleOverride($meta_stmt->expr->getArgs(), $this->codebase); } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/AddRemoveTaints/HtmlFunctionTainter.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/AddRemoveTaints/HtmlFunctionTainter.php index c96a50f1..1f862278 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/AddRemoveTaints/HtmlFunctionTainter.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/AddRemoveTaints/HtmlFunctionTainter.php @@ -32,13 +32,13 @@ class HtmlFunctionTainter implements AddTaintsInterface, RemoveTaintsInterface || !$item instanceof PhpParser\Node\Expr\FuncCall || $item->isFirstClassCallable() || !$item->name instanceof PhpParser\Node\Name - || count($item->name->parts) !== 1 + || count($item->name->getParts()) !== 1 || count($item->getArgs()) === 0 ) { return []; } - $function_id = strtolower($item->name->parts[0]); + $function_id = strtolower($item->name->getFirst()); if ($function_id === 'html_entity_decode' || $function_id === 'htmlspecialchars_decode' @@ -84,13 +84,13 @@ class HtmlFunctionTainter implements AddTaintsInterface, RemoveTaintsInterface || !$item instanceof PhpParser\Node\Expr\FuncCall || $item->isFirstClassCallable() || !$item->name instanceof PhpParser\Node\Name - || count($item->name->parts) !== 1 + || count($item->name->getParts()) !== 1 || count($item->getArgs()) === 0 ) { return []; } - $function_id = strtolower($item->name->parts[0]); + $function_id = strtolower($item->name->getFirst()); if ($function_id === 'htmlentities' || $function_id === 'htmlspecialchars' diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php index 7b03bb3e..82eb578f 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php @@ -3,6 +3,7 @@ namespace Psalm\Internal\Provider; use Psalm\Config; +use Psalm\Internal\Cache; use Psalm\Storage\ClassLikeStorage; use RuntimeException; use UnexpectedValueException; @@ -10,22 +11,15 @@ use UnexpectedValueException; use function array_merge; use function dirname; use function file_exists; -use function file_put_contents; use function filemtime; use function get_class; use function hash; -use function igbinary_serialize; -use function igbinary_unserialize; use function is_dir; use function is_null; use function mkdir; -use function serialize; use function strtolower; -use function unlink; -use function unserialize; use const DIRECTORY_SEPARATOR; -use const LOCK_EX; use const PHP_VERSION_ID; /** @@ -33,7 +27,7 @@ use const PHP_VERSION_ID; */ class ClassLikeStorageCacheProvider { - private Config $config; + private Cache $cache; private string $modified_timestamps = ''; @@ -41,7 +35,7 @@ class ClassLikeStorageCacheProvider public function __construct(Config $config) { - $this->config = $config; + $this->cache = new Cache($config); $storage_dir = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'Storage' . DIRECTORY_SEPARATOR; @@ -64,7 +58,7 @@ class ClassLikeStorageCacheProvider $this->modified_timestamps .= ' ' . filemtime($dependent_file_path); } - $this->modified_timestamps .= $this->config->computeHash(); + $this->modified_timestamps .= $config->computeHash(); } public function writeToCache(ClassLikeStorage $storage, string $file_path, string $file_contents): void @@ -80,11 +74,7 @@ class ClassLikeStorageCacheProvider } $cache_location = $this->getCacheLocationForClass($fq_classlike_name_lc, $file_path, true); - if ($this->config->use_igbinary) { - file_put_contents($cache_location, igbinary_serialize($storage), LOCK_EX); - } else { - file_put_contents($cache_location, serialize($storage), LOCK_EX); - } + $this->cache->saveItem($cache_location, $storage); } public function getLatestFromCache( @@ -104,7 +94,7 @@ class ClassLikeStorageCacheProvider if (@get_class($cached_value) === '__PHP_Incomplete_Class' || $cache_hash !== $cached_value->hash ) { - unlink($this->getCacheLocationForClass($fq_classlike_name_lc, $file_path)); + $this->cache->deleteItem($this->getCacheLocationForClass($fq_classlike_name_lc, $file_path)); throw new UnexpectedValueException($fq_classlike_name_lc . ' should not be outdated'); } @@ -118,31 +108,11 @@ class ClassLikeStorageCacheProvider return PHP_VERSION_ID >= 8_01_00 ? hash('xxh128', $data) : hash('md4', $data); } - /** - * @psalm-suppress MixedAssignment - */ private function loadFromCache(string $fq_classlike_name_lc, ?string $file_path): ?ClassLikeStorage { - $cache_location = $this->getCacheLocationForClass($fq_classlike_name_lc, $file_path); - - if (file_exists($cache_location)) { - if ($this->config->use_igbinary) { - $storage = igbinary_unserialize(Providers::safeFileGetContents($cache_location)); - - if ($storage instanceof ClassLikeStorage) { - return $storage; - } - - return null; - } - - $storage = unserialize(Providers::safeFileGetContents($cache_location)); - - if ($storage instanceof ClassLikeStorage) { - return $storage; - } - - return null; + $storage = $this->cache->getItem($this->getCacheLocationForClass($fq_classlike_name_lc, $file_path)); + if ($storage instanceof ClassLikeStorage) { + return $storage; } return null; @@ -153,7 +123,7 @@ class ClassLikeStorageCacheProvider ?string $file_path, bool $create_directory = false ): string { - $root_cache_directory = $this->config->getCacheDirectory(); + $root_cache_directory = $this->cache->getCacheDirectory(); if (!$root_cache_directory) { throw new UnexpectedValueException('No cache directory defined'); @@ -186,6 +156,6 @@ class ClassLikeStorageCacheProvider return $parser_cache_directory . DIRECTORY_SEPARATOR . $file_path_sha - . ($this->config->use_igbinary ? '-igbinary' : ''); + . ($this->cache->use_igbinary ? '-igbinary' : ''); } } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FakeFileProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FakeFileProvider.php index 64251084..756e0d72 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FakeFileProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FakeFileProvider.php @@ -68,6 +68,12 @@ class FakeFileProvider extends FileProvider $this->fake_file_times[$file_path] = (int)microtime(true); } + public function deleteFile(string $file_path): void + { + unset($this->fake_files[$file_path]); + unset($this->fake_file_times[$file_path]); + } + /** * @param array $file_extensions * @param null|callable(string):bool $filter diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php index 9f469a08..cb302971 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php @@ -3,6 +3,7 @@ namespace Psalm\Internal\Provider; use Psalm\Config; +use Psalm\Internal\Cache; use Psalm\Internal\Codebase\Analyzer; use Psalm\Internal\Provider\Providers; use RuntimeException; @@ -10,23 +11,19 @@ use UnexpectedValueException; use function file_exists; use function file_put_contents; -use function igbinary_serialize; -use function igbinary_unserialize; use function is_array; use function is_dir; use function is_readable; use function mkdir; -use function serialize; -use function unserialize; use const DIRECTORY_SEPARATOR; use const LOCK_EX; /** - * @psalm-import-type FileMapType from Analyzer - * * Used to determine which files reference other files, necessary for using the --diff * option from the command line. + * + * @psalm-import-type FileMapType from Analyzer * @internal */ class FileReferenceCacheProvider @@ -53,10 +50,12 @@ class FileReferenceCacheProvider private const METHOD_PARAM_USE_CACHE_NAME = 'method_param_uses'; protected Config $config; + protected Cache $cache; public function __construct(Config $config) { $this->config = $config; + $this->cache = new Cache($config); } public function hasConfigChanged(): bool @@ -65,771 +64,164 @@ class FileReferenceCacheProvider return $new_hash !== $this->getConfigHashCache(); } - /** - * @psalm-suppress MixedAssignment - */ public function getCachedFileReferences(): ?array { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return null; - } - - $reference_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::REFERENCE_CACHE_NAME; - - if (!is_readable($reference_cache_location)) { - return null; - } - - if ($this->config->use_igbinary) { - $reference_cache = igbinary_unserialize(Providers::safeFileGetContents($reference_cache_location)); - } else { - $reference_cache = unserialize(Providers::safeFileGetContents($reference_cache_location)); - } - - if (!is_array($reference_cache)) { - throw new UnexpectedValueException('The reference cache must be an array'); - } - - return $reference_cache; + return $this->getCacheItem(self::REFERENCE_CACHE_NAME); } - /** - * @psalm-suppress MixedAssignment - */ public function getCachedClassLikeFiles(): ?array { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return null; - } - - $reference_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::CLASSLIKE_FILE_CACHE_NAME; - - if (!is_readable($reference_cache_location)) { - return null; - } - - if ($this->config->use_igbinary) { - $reference_cache = igbinary_unserialize(Providers::safeFileGetContents($reference_cache_location)); - } else { - $reference_cache = unserialize(Providers::safeFileGetContents($reference_cache_location)); - } - - if (!is_array($reference_cache)) { - throw new UnexpectedValueException('The reference cache must be an array'); - } - - return $reference_cache; + return $this->getCacheItem(self::CLASSLIKE_FILE_CACHE_NAME); } - /** - * @psalm-suppress MixedAssignment - */ public function getCachedNonMethodClassReferences(): ?array { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return null; - } - - $reference_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::NONMETHOD_CLASS_REFERENCE_CACHE_NAME; - - if (!is_readable($reference_cache_location)) { - return null; - } - - if ($this->config->use_igbinary) { - $reference_cache = igbinary_unserialize(Providers::safeFileGetContents($reference_cache_location)); - } else { - $reference_cache = unserialize(Providers::safeFileGetContents($reference_cache_location)); - } - - if (!is_array($reference_cache)) { - throw new UnexpectedValueException('The reference cache must be an array'); - } - - return $reference_cache; + return $this->getCacheItem(self::NONMETHOD_CLASS_REFERENCE_CACHE_NAME); } - /** - * @psalm-suppress MixedAssignment - */ public function getCachedMethodClassReferences(): ?array { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return null; - } - - $reference_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::METHOD_CLASS_REFERENCE_CACHE_NAME; - - if (!is_readable($reference_cache_location)) { - return null; - } - - if ($this->config->use_igbinary) { - $reference_cache = igbinary_unserialize(Providers::safeFileGetContents($reference_cache_location)); - } else { - $reference_cache = unserialize(Providers::safeFileGetContents($reference_cache_location)); - } - - if (!is_array($reference_cache)) { - throw new UnexpectedValueException('The reference cache must be an array'); - } - - return $reference_cache; + return $this->getCacheItem(self::METHOD_CLASS_REFERENCE_CACHE_NAME); } - /** - * @psalm-suppress MixedAssignment - */ public function getCachedMethodMemberReferences(): ?array { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return null; - } - - $class_member_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::CLASS_METHOD_CACHE_NAME; - - if (!is_readable($class_member_cache_location)) { - return null; - } - - $class_member_reference_cache = Providers::safeFileGetContents($class_member_cache_location); - if ($this->config->use_igbinary) { - $class_member_reference_cache = igbinary_unserialize($class_member_reference_cache); - } else { - $class_member_reference_cache = unserialize($class_member_reference_cache); - } - - if (!is_array($class_member_reference_cache)) { - throw new UnexpectedValueException('The reference cache must be an array'); - } - - return $class_member_reference_cache; + return $this->getCacheItem(self::CLASS_METHOD_CACHE_NAME); } - /** - * @psalm-suppress MixedAssignment - */ public function getCachedMethodDependencies(): ?array { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return null; - } - - $method_dependencies_cache_location - = $cache_directory . DIRECTORY_SEPARATOR . self::METHOD_DEPENDENCIES_CACHE_NAME; - - if (!is_readable($method_dependencies_cache_location)) { - return null; - } - - $method_dependencies_cache = Providers::safeFileGetContents($method_dependencies_cache_location); - if ($this->config->use_igbinary) { - $method_dependencies_cache = igbinary_unserialize($method_dependencies_cache); - } else { - $method_dependencies_cache = unserialize($method_dependencies_cache); - } - - if (!is_array($method_dependencies_cache)) { - throw new UnexpectedValueException('The reference cache must be an array'); - } - - return $method_dependencies_cache; + return $this->getCacheItem(self::METHOD_DEPENDENCIES_CACHE_NAME); } - /** - * @psalm-suppress MixedAssignment - */ public function getCachedMethodPropertyReferences(): ?array { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return null; - } - - $class_member_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::CLASS_PROPERTY_CACHE_NAME; - - if (!is_readable($class_member_cache_location)) { - return null; - } - - $class_member_reference_cache = Providers::safeFileGetContents($class_member_cache_location); - if ($this->config->use_igbinary) { - $class_member_reference_cache = igbinary_unserialize($class_member_reference_cache); - } else { - $class_member_reference_cache = unserialize($class_member_reference_cache); - } - - if (!is_array($class_member_reference_cache)) { - throw new UnexpectedValueException('The reference cache must be an array'); - } - - return $class_member_reference_cache; + return $this->getCacheItem(self::CLASS_PROPERTY_CACHE_NAME); } - /** - * @psalm-suppress MixedAssignment - */ public function getCachedMethodMethodReturnReferences(): ?array { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return null; - } - - $class_member_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::CLASS_METHOD_RETURN_CACHE_NAME; - - if (!is_readable($class_member_cache_location)) { - return null; - } - - $class_member_reference_cache = Providers::safeFileGetContents($class_member_cache_location); - if ($this->config->use_igbinary) { - $class_member_reference_cache = igbinary_unserialize($class_member_reference_cache); - } else { - $class_member_reference_cache = unserialize($class_member_reference_cache); - } - - if (!is_array($class_member_reference_cache)) { - throw new UnexpectedValueException('The reference cache must be an array'); - } - - return $class_member_reference_cache; + return $this->getCacheItem(self::CLASS_METHOD_RETURN_CACHE_NAME); } - /** - * @psalm-suppress MixedAssignment - */ public function getCachedMethodMissingMemberReferences(): ?array { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return null; - } - - $class_member_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::METHOD_MISSING_MEMBER_CACHE_NAME; - - if (!is_readable($class_member_cache_location)) { - return null; - } - - $class_member_reference_cache = Providers::safeFileGetContents($class_member_cache_location); - if ($this->config->use_igbinary) { - $class_member_reference_cache = igbinary_unserialize($class_member_reference_cache); - } else { - $class_member_reference_cache = unserialize($class_member_reference_cache); - } - - if (!is_array($class_member_reference_cache)) { - throw new UnexpectedValueException('The reference cache must be an array'); - } - - return $class_member_reference_cache; + return $this->getCacheItem(self::METHOD_MISSING_MEMBER_CACHE_NAME); } - /** - * @psalm-suppress MixedAssignment - */ public function getCachedFileMemberReferences(): ?array { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return null; - } - - $file_class_member_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::FILE_CLASS_MEMBER_CACHE_NAME; - - if (!is_readable($file_class_member_cache_location)) { - return null; - } - - $file_class_member_reference_cache = Providers::safeFileGetContents($file_class_member_cache_location); - if ($this->config->use_igbinary) { - $file_class_member_reference_cache = igbinary_unserialize($file_class_member_reference_cache); - } else { - $file_class_member_reference_cache = unserialize($file_class_member_reference_cache); - } - - if (!is_array($file_class_member_reference_cache)) { - throw new UnexpectedValueException('The reference cache must be an array'); - } - - return $file_class_member_reference_cache; + return $this->getCacheItem(self::FILE_CLASS_MEMBER_CACHE_NAME); } - /** - * @psalm-suppress MixedAssignment - */ public function getCachedFilePropertyReferences(): ?array { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return null; - } - - $file_class_member_cache_location = $cache_directory - . DIRECTORY_SEPARATOR - . self::FILE_CLASS_PROPERTY_CACHE_NAME; - - if (!is_readable($file_class_member_cache_location)) { - return null; - } - - $file_class_member_reference_cache = Providers::safeFileGetContents($file_class_member_cache_location); - if ($this->config->use_igbinary) { - $file_class_member_reference_cache = igbinary_unserialize($file_class_member_reference_cache); - } else { - $file_class_member_reference_cache = unserialize($file_class_member_reference_cache); - } - - if (!is_array($file_class_member_reference_cache)) { - throw new UnexpectedValueException('The reference cache must be an array'); - } - - return $file_class_member_reference_cache; + return $this->getCacheItem(self::FILE_CLASS_PROPERTY_CACHE_NAME); } - /** - * @psalm-suppress MixedAssignment - */ public function getCachedFileMethodReturnReferences(): ?array { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return null; - } - - $file_class_member_cache_location = $cache_directory - . DIRECTORY_SEPARATOR - . self::FILE_METHOD_RETURN_CACHE_NAME; - - if (!is_readable($file_class_member_cache_location)) { - return null; - } - - $file_class_member_reference_cache = Providers::safeFileGetContents($file_class_member_cache_location); - if ($this->config->use_igbinary) { - $file_class_member_reference_cache = igbinary_unserialize($file_class_member_reference_cache); - } else { - $file_class_member_reference_cache = unserialize($file_class_member_reference_cache); - } - - if (!is_array($file_class_member_reference_cache)) { - throw new UnexpectedValueException('The reference cache must be an array'); - } - - return $file_class_member_reference_cache; + return $this->getCacheItem(self::FILE_METHOD_RETURN_CACHE_NAME); } - /** - * @psalm-suppress MixedAssignment - */ public function getCachedFileMissingMemberReferences(): ?array { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return null; - } - - $file_class_member_cache_location - = $cache_directory . DIRECTORY_SEPARATOR . self::FILE_MISSING_MEMBER_CACHE_NAME; - - if (!is_readable($file_class_member_cache_location)) { - return null; - } - - $file_class_member_reference_cache = Providers::safeFileGetContents($file_class_member_cache_location); - if ($this->config->use_igbinary) { - $file_class_member_reference_cache = igbinary_unserialize($file_class_member_reference_cache); - } else { - $file_class_member_reference_cache = unserialize($file_class_member_reference_cache); - } - - if (!is_array($file_class_member_reference_cache)) { - throw new UnexpectedValueException('The reference cache must be an array'); - } - - return $file_class_member_reference_cache; + return $this->getCacheItem(self::FILE_MISSING_MEMBER_CACHE_NAME); } - /** - * @psalm-suppress MixedAssignment - */ public function getCachedMixedMemberNameReferences(): ?array { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return null; - } - - $reference_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::UNKNOWN_MEMBER_CACHE_NAME; - - if (!is_readable($reference_cache_location)) { - return null; - } - - if ($this->config->use_igbinary) { - $reference_cache = igbinary_unserialize(Providers::safeFileGetContents($reference_cache_location)); - } else { - $reference_cache = unserialize(Providers::safeFileGetContents($reference_cache_location)); - } - - if (!is_array($reference_cache)) { - throw new UnexpectedValueException('The reference cache must be an array'); - } - - return $reference_cache; + return $this->getCacheItem(self::UNKNOWN_MEMBER_CACHE_NAME); } - /** - * @psalm-suppress MixedAssignment - */ public function getCachedMethodParamUses(): ?array { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return null; - } - - $reference_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::METHOD_PARAM_USE_CACHE_NAME; - - if (!is_readable($reference_cache_location)) { - return null; - } - - if ($this->config->use_igbinary) { - $reference_cache = igbinary_unserialize(Providers::safeFileGetContents($reference_cache_location)); - } else { - $reference_cache = unserialize(Providers::safeFileGetContents($reference_cache_location)); - } - - if (!is_array($reference_cache)) { - throw new UnexpectedValueException('The method param use cache must be an array'); - } - - return $reference_cache; + return $this->getCacheItem(self::METHOD_PARAM_USE_CACHE_NAME); } - /** - * @psalm-suppress MixedAssignment - */ public function getCachedIssues(): ?array { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return null; - } - - $issues_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::ISSUES_CACHE_NAME; - - if (!is_readable($issues_cache_location)) { - return null; - } - - if ($this->config->use_igbinary) { - $issues_cache = igbinary_unserialize(Providers::safeFileGetContents($issues_cache_location)); - } else { - $issues_cache = unserialize(Providers::safeFileGetContents($issues_cache_location)); - } - - if (!is_array($issues_cache)) { - throw new UnexpectedValueException('The reference cache must be an array'); - } - - return $issues_cache; + return $this->getCacheItem(self::ISSUES_CACHE_NAME); } public function setCachedFileReferences(array $file_references): void { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return; - } - - $reference_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::REFERENCE_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($reference_cache_location, igbinary_serialize($file_references), LOCK_EX); - } else { - file_put_contents($reference_cache_location, serialize($file_references), LOCK_EX); - } + $this->saveCacheItem(self::REFERENCE_CACHE_NAME, $file_references); } public function setCachedClassLikeFiles(array $file_references): void { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return; - } - - $reference_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::CLASSLIKE_FILE_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($reference_cache_location, igbinary_serialize($file_references), LOCK_EX); - } else { - file_put_contents($reference_cache_location, serialize($file_references), LOCK_EX); - } + $this->saveCacheItem(self::CLASSLIKE_FILE_CACHE_NAME, $file_references); } public function setCachedNonMethodClassReferences(array $file_class_references): void { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return; - } - - $reference_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::NONMETHOD_CLASS_REFERENCE_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($reference_cache_location, igbinary_serialize($file_class_references), LOCK_EX); - } else { - file_put_contents($reference_cache_location, serialize($file_class_references), LOCK_EX); - } + $this->saveCacheItem(self::NONMETHOD_CLASS_REFERENCE_CACHE_NAME, $file_class_references); } public function setCachedMethodClassReferences(array $method_class_references): void { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return; - } - - $reference_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::METHOD_CLASS_REFERENCE_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($reference_cache_location, igbinary_serialize($method_class_references), LOCK_EX); - } else { - file_put_contents($reference_cache_location, serialize($method_class_references), LOCK_EX); - } + $this->saveCacheItem(self::METHOD_CLASS_REFERENCE_CACHE_NAME, $method_class_references); } public function setCachedMethodMemberReferences(array $member_references): void { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return; - } - - $member_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::CLASS_METHOD_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($member_cache_location, igbinary_serialize($member_references), LOCK_EX); - } else { - file_put_contents($member_cache_location, serialize($member_references), LOCK_EX); - } + $this->saveCacheItem(self::CLASS_METHOD_CACHE_NAME, $member_references); } public function setCachedMethodDependencies(array $member_references): void { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return; - } - - $member_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::METHOD_DEPENDENCIES_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($member_cache_location, igbinary_serialize($member_references), LOCK_EX); - } else { - file_put_contents($member_cache_location, serialize($member_references), LOCK_EX); - } + $this->saveCacheItem(self::METHOD_DEPENDENCIES_CACHE_NAME, $member_references); } public function setCachedMethodPropertyReferences(array $property_references): void { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return; - } - - $member_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::CLASS_PROPERTY_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($member_cache_location, igbinary_serialize($property_references), LOCK_EX); - } else { - file_put_contents($member_cache_location, serialize($property_references), LOCK_EX); - } + $this->saveCacheItem(self::CLASS_PROPERTY_CACHE_NAME, $property_references); } public function setCachedMethodMethodReturnReferences(array $method_return_references): void { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return; - } - - $member_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::CLASS_METHOD_RETURN_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($member_cache_location, igbinary_serialize($method_return_references), LOCK_EX); - } else { - file_put_contents($member_cache_location, serialize($method_return_references), LOCK_EX); - } + $this->saveCacheItem(self::CLASS_METHOD_RETURN_CACHE_NAME, $method_return_references); } public function setCachedMethodMissingMemberReferences(array $member_references): void { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return; - } - - $member_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::METHOD_MISSING_MEMBER_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($member_cache_location, igbinary_serialize($member_references), LOCK_EX); - } else { - file_put_contents($member_cache_location, serialize($member_references), LOCK_EX); - } + $this->saveCacheItem(self::METHOD_MISSING_MEMBER_CACHE_NAME, $member_references); } public function setCachedFileMemberReferences(array $member_references): void { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return; - } - - $member_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::FILE_CLASS_MEMBER_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($member_cache_location, igbinary_serialize($member_references), LOCK_EX); - } else { - file_put_contents($member_cache_location, serialize($member_references), LOCK_EX); - } + $this->saveCacheItem(self::FILE_CLASS_MEMBER_CACHE_NAME, $member_references); } public function setCachedFilePropertyReferences(array $property_references): void { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return; - } - - $member_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::FILE_CLASS_PROPERTY_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($member_cache_location, igbinary_serialize($property_references), LOCK_EX); - } else { - file_put_contents($member_cache_location, serialize($property_references), LOCK_EX); - } + $this->saveCacheItem(self::FILE_CLASS_PROPERTY_CACHE_NAME, $property_references); } public function setCachedFileMethodReturnReferences(array $method_return_references): void { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return; - } - - $member_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::FILE_METHOD_RETURN_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($member_cache_location, igbinary_serialize($method_return_references), LOCK_EX); - } else { - file_put_contents($member_cache_location, serialize($method_return_references), LOCK_EX); - } + $this->saveCacheItem(self::FILE_METHOD_RETURN_CACHE_NAME, $method_return_references); } public function setCachedFileMissingMemberReferences(array $member_references): void { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return; - } - - $member_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::FILE_MISSING_MEMBER_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($member_cache_location, igbinary_serialize($member_references), LOCK_EX); - } else { - file_put_contents($member_cache_location, serialize($member_references), LOCK_EX); - } + $this->saveCacheItem(self::FILE_MISSING_MEMBER_CACHE_NAME, $member_references); } public function setCachedMixedMemberNameReferences(array $references): void { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return; - } - - $reference_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::UNKNOWN_MEMBER_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($reference_cache_location, igbinary_serialize($references), LOCK_EX); - } else { - file_put_contents($reference_cache_location, serialize($references), LOCK_EX); - } + $this->saveCacheItem(self::UNKNOWN_MEMBER_CACHE_NAME, $references); } public function setCachedMethodParamUses(array $uses): void { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return; - } - - $reference_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::METHOD_PARAM_USE_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($reference_cache_location, igbinary_serialize($uses), LOCK_EX); - } else { - file_put_contents($reference_cache_location, serialize($uses), LOCK_EX); - } + $this->saveCacheItem(self::METHOD_PARAM_USE_CACHE_NAME, $uses); } public function setCachedIssues(array $issues): void { - $cache_directory = $this->config->getCacheDirectory(); - - if (!$cache_directory) { - return; - } - - $issues_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::ISSUES_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($issues_cache_location, igbinary_serialize($issues), LOCK_EX); - } else { - file_put_contents($issues_cache_location, serialize($issues), LOCK_EX); - } + $this->saveCacheItem(self::ISSUES_CACHE_NAME, $issues); } /** @@ -837,23 +229,10 @@ class FileReferenceCacheProvider */ public function getAnalyzedMethodCache() { - $cache_directory = $this->config->getCacheDirectory(); + /** @var null|array> $cache_item */ + $cache_item = $this->getCacheItem(self::ANALYZED_METHODS_CACHE_NAME); - $analyzed_methods_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::ANALYZED_METHODS_CACHE_NAME; - - if ($cache_directory - && file_exists($analyzed_methods_cache_location) - ) { - if ($this->config->use_igbinary) { - /** @var array> */ - return igbinary_unserialize(Providers::safeFileGetContents($analyzed_methods_cache_location)); - } else { - /** @var array> */ - return unserialize(Providers::safeFileGetContents($analyzed_methods_cache_location)); - } - } - - return false; + return $cache_item ?? false; } /** @@ -861,19 +240,7 @@ class FileReferenceCacheProvider */ public function setAnalyzedMethodCache(array $analyzed_methods): void { - $cache_directory = Config::getInstance()->getCacheDirectory(); - - if ($cache_directory) { - $analyzed_methods_cache_location = $cache_directory - . DIRECTORY_SEPARATOR - . self::ANALYZED_METHODS_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($analyzed_methods_cache_location, igbinary_serialize($analyzed_methods), LOCK_EX); - } else { - file_put_contents($analyzed_methods_cache_location, serialize($analyzed_methods), LOCK_EX); - } - } + $this->saveCacheItem(self::ANALYZED_METHODS_CACHE_NAME, $analyzed_methods); } /** @@ -881,29 +248,10 @@ class FileReferenceCacheProvider */ public function getFileMapCache() { - $cache_directory = $this->config->getCacheDirectory(); + /** @var array|null $cache_item */ + $cache_item = $this->getCacheItem(self::FILE_MAPS_CACHE_NAME); - $file_maps_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::FILE_MAPS_CACHE_NAME; - - if ($cache_directory - && file_exists($file_maps_cache_location) - ) { - if ($this->config->use_igbinary) { - /** - * @var array - */ - $file_maps_cache = igbinary_unserialize(Providers::safeFileGetContents($file_maps_cache_location)); - } else { - /** - * @var array - */ - $file_maps_cache = unserialize(Providers::safeFileGetContents($file_maps_cache_location)); - } - - return $file_maps_cache; - } - - return false; + return $cache_item ?? false; } /** @@ -911,17 +259,7 @@ class FileReferenceCacheProvider */ public function setFileMapCache(array $file_maps): void { - $cache_directory = Config::getInstance()->getCacheDirectory(); - - if ($cache_directory) { - $file_maps_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::FILE_MAPS_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($file_maps_cache_location, igbinary_serialize($file_maps), LOCK_EX); - } else { - file_put_contents($file_maps_cache_location, serialize($file_maps), LOCK_EX); - } - } + $this->saveCacheItem(self::FILE_MAPS_CACHE_NAME, $file_maps); } //phpcs:disable -- Remove this once the phpstan phpdoc parser MR is merged @@ -931,29 +269,10 @@ class FileReferenceCacheProvider public function getTypeCoverage() { //phpcs:enable -- Remove this once the phpstan phpdoc parser MR is merged - $cache_directory = Config::getInstance()->getCacheDirectory(); + /** @var array|null $cache_item */ + $cache_item = $this->getCacheItem(self::TYPE_COVERAGE_CACHE_NAME); - $type_coverage_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::TYPE_COVERAGE_CACHE_NAME; - - if ($cache_directory - && file_exists($type_coverage_cache_location) - ) { - if ($this->config->use_igbinary) { - /** @var array */ - $type_coverage_cache = igbinary_unserialize( - Providers::safeFileGetContents($type_coverage_cache_location), - ); - } else { - /** @var array */ - $type_coverage_cache = unserialize( - Providers::safeFileGetContents($type_coverage_cache_location), - ); - } - - return $type_coverage_cache; - } - - return false; + return $cache_item ?? false; } /** @@ -961,17 +280,7 @@ class FileReferenceCacheProvider */ public function setTypeCoverage(array $mixed_counts): void { - $cache_directory = Config::getInstance()->getCacheDirectory(); - - if ($cache_directory) { - $type_coverage_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::TYPE_COVERAGE_CACHE_NAME; - - if ($this->config->use_igbinary) { - file_put_contents($type_coverage_cache_location, igbinary_serialize($mixed_counts), LOCK_EX); - } else { - file_put_contents($type_coverage_cache_location, serialize($mixed_counts), LOCK_EX); - } - } + $this->saveCacheItem(self::TYPE_COVERAGE_CACHE_NAME, $mixed_counts); } /** @@ -1030,4 +339,37 @@ class FileReferenceCacheProvider LOCK_EX, ); } + + private function getCacheItem(string $type): ?array + { + $cache_directory = $this->config->getCacheDirectory(); + if (!$cache_directory) { + return null; + } + + $cache_location = $cache_directory . DIRECTORY_SEPARATOR . $type; + if (!is_readable($cache_location)) { + return null; + } + + $cache_item = $this->cache->getItem($cache_location); + if ($cache_item === null) { + return null; + } elseif (!is_array($cache_item)) { + throw new UnexpectedValueException('The reference cache must be an array'); + } + + return $cache_item; + } + + private function saveCacheItem(string $type, array $cache_item): void + { + $cache_directory = $this->config->getCacheDirectory(); + if (!$cache_directory) { + return; + } + $cache_location = $cache_directory . DIRECTORY_SEPARATOR . $type; + + $this->cache->saveItem($cache_location, $cache_item); + } } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FileReferenceProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FileReferenceProvider.php index 459447bb..15950320 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FileReferenceProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FileReferenceProvider.php @@ -14,13 +14,12 @@ use function array_keys; use function array_merge; use function array_unique; use function explode; -use function file_exists; /** - * @psalm-import-type FileMapType from Analyzer - * * Used to determine which files reference other files, necessary for using the --diff * option from the command line. + * + * @psalm-import-type FileMapType from Analyzer * @internal */ class FileReferenceProvider @@ -164,10 +163,12 @@ class FileReferenceProvider */ private static array $method_param_uses = []; + private FileProvider $file_provider; public ?FileReferenceCacheProvider $cache = null; - public function __construct(?FileReferenceCacheProvider $cache = null) + public function __construct(FileProvider $file_provider, ?FileReferenceCacheProvider $cache = null) { + $this->file_provider = $file_provider; $this->cache = $cache; } @@ -179,7 +180,7 @@ class FileReferenceProvider if (self::$deleted_files === null) { self::$deleted_files = array_filter( array_keys(self::$file_references), - static fn(string $file_name): bool => !file_exists($file_name) + fn(string $file_name): bool => !$this->file_provider->fileExists($file_name) ); } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FileStorageCacheProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FileStorageCacheProvider.php index 10f2ef14..9fcb7d9d 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FileStorageCacheProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FileStorageCacheProvider.php @@ -3,6 +3,7 @@ namespace Psalm\Internal\Provider; use Psalm\Config; +use Psalm\Internal\Cache; use Psalm\Storage\FileStorage; use RuntimeException; use UnexpectedValueException; @@ -10,21 +11,14 @@ use UnexpectedValueException; use function array_merge; use function dirname; use function file_exists; -use function file_put_contents; use function filemtime; use function get_class; use function hash; -use function igbinary_serialize; -use function igbinary_unserialize; use function is_dir; use function mkdir; -use function serialize; use function strtolower; -use function unlink; -use function unserialize; use const DIRECTORY_SEPARATOR; -use const LOCK_EX; use const PHP_VERSION_ID; /** @@ -34,13 +28,13 @@ class FileStorageCacheProvider { private string $modified_timestamps = ''; - private Config $config; + private Cache $cache; private const FILE_STORAGE_CACHE_DIRECTORY = 'file_cache'; public function __construct(Config $config) { - $this->config = $config; + $this->cache = new Cache($config); $storage_dir = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'Storage' . DIRECTORY_SEPARATOR; @@ -64,20 +58,24 @@ class FileStorageCacheProvider $this->modified_timestamps .= ' ' . filemtime($dependent_file_path); } - $this->modified_timestamps .= $this->config->computeHash(); + $this->modified_timestamps .= $config->computeHash(); } public function writeToCache(FileStorage $storage, string $file_contents): void { $file_path = strtolower($storage->file_path); - $cache_location = $this->getCacheLocationForPath($file_path, true); $storage->hash = $this->getCacheHash($file_path, $file_contents); - if ($this->config->use_igbinary) { - file_put_contents($cache_location, igbinary_serialize($storage), LOCK_EX); - } else { - file_put_contents($cache_location, serialize($storage), LOCK_EX); - } + $this->storeInCache($file_path, $storage); + } + + /** + * @param lowercase-string $file_path + */ + protected function storeInCache(string $file_path, FileStorage $storage): void + { + $cache_location = $this->getCacheLocationForPath($file_path, true); + $this->cache->saveItem($cache_location, $storage); } public function getLatestFromCache(string $file_path, string $file_contents): ?FileStorage @@ -105,11 +103,7 @@ class FileStorageCacheProvider public function removeCacheForFile(string $file_path): void { - $cache_path = $this->getCacheLocationForPath($file_path); - - if (file_exists($cache_path)) { - unlink($cache_path); - } + $this->cache->deleteItem($this->getCacheLocationForPath($file_path)); } private function getCacheHash(string $_unused_file_path, string $file_contents): string @@ -122,30 +116,13 @@ class FileStorageCacheProvider } /** - * @psalm-suppress MixedAssignment + * @param lowercase-string $file_path */ - private function loadFromCache(string $file_path): ?FileStorage + protected function loadFromCache(string $file_path): ?FileStorage { - $cache_location = $this->getCacheLocationForPath($file_path); - - if (file_exists($cache_location)) { - if ($this->config->use_igbinary) { - $storage = igbinary_unserialize(Providers::safeFileGetContents($cache_location)); - - if ($storage instanceof FileStorage) { - return $storage; - } - - return null; - } - - $storage = unserialize(Providers::safeFileGetContents($cache_location)); - - if ($storage instanceof FileStorage) { - return $storage; - } - - return null; + $storage = $this->cache->getItem($this->getCacheLocationForPath($file_path)); + if ($storage instanceof FileStorage) { + return $storage; } return null; @@ -153,7 +130,7 @@ class FileStorageCacheProvider private function getCacheLocationForPath(string $file_path, bool $create_directory = false): string { - $root_cache_directory = $this->config->getCacheDirectory(); + $root_cache_directory = $this->cache->getCacheDirectory(); if (!$root_cache_directory) { throw new UnexpectedValueException('No cache directory defined'); @@ -188,6 +165,6 @@ class FileStorageCacheProvider return $parser_cache_directory . DIRECTORY_SEPARATOR . $hash - . ($this->config->use_igbinary ? '-igbinary' : ''); + . ($this->cache->use_igbinary ? '-igbinary' : ''); } } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FunctionReturnTypeProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FunctionReturnTypeProvider.php index de1e27d7..ab43dcf5 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FunctionReturnTypeProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/FunctionReturnTypeProvider.php @@ -39,6 +39,7 @@ use Psalm\Internal\Provider\ReturnTypeProvider\ParseUrlReturnTypeProvider; use Psalm\Internal\Provider\ReturnTypeProvider\PowReturnTypeProvider; use Psalm\Internal\Provider\ReturnTypeProvider\RandReturnTypeProvider; use Psalm\Internal\Provider\ReturnTypeProvider\RoundReturnTypeProvider; +use Psalm\Internal\Provider\ReturnTypeProvider\SprintfReturnTypeProvider; use Psalm\Internal\Provider\ReturnTypeProvider\StrReplaceReturnTypeProvider; use Psalm\Internal\Provider\ReturnTypeProvider\StrTrReturnTypeProvider; use Psalm\Internal\Provider\ReturnTypeProvider\TriggerErrorReturnTypeProvider; @@ -105,6 +106,7 @@ class FunctionReturnTypeProvider $this->registerClass(MbInternalEncodingReturnTypeProvider::class); $this->registerClass(DateReturnTypeProvider::class); $this->registerClass(PowReturnTypeProvider::class); + $this->registerClass(SprintfReturnTypeProvider::class); } /** diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ParserCacheProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ParserCacheProvider.php index 17aa7e5e..55aa13e0 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ParserCacheProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ParserCacheProvider.php @@ -6,6 +6,7 @@ use JsonException; use PhpParser; use PhpParser\Node\Stmt; use Psalm\Config; +use Psalm\Internal\Cache; use RuntimeException; use UnexpectedValueException; @@ -15,20 +16,15 @@ use function file_put_contents; use function filemtime; use function gettype; use function hash; -use function igbinary_serialize; -use function igbinary_unserialize; use function is_array; use function is_dir; use function is_readable; -use function is_writable; +use function is_string; use function json_decode; use function json_encode; use function mkdir; use function scandir; -use function serialize; use function touch; -use function unlink; -use function unserialize; use const DIRECTORY_SEPARATOR; use const JSON_THROW_ON_ERROR; @@ -45,7 +41,7 @@ class ParserCacheProvider private const PARSER_CACHE_DIRECTORY = 'php-parser'; private const FILE_CONTENTS_CACHE_DIRECTORY = 'file-caches'; - private Config $config; + private Cache $cache; /** * A map of filename hashes to contents hashes @@ -65,7 +61,7 @@ class ParserCacheProvider public function __construct(Config $config, bool $use_file_cache = true) { - $this->config = $config; + $this->cache = new Cache($config); $this->use_file_cache = $use_file_cache; } @@ -92,15 +88,12 @@ class ParserCacheProvider && is_readable($cache_location) && filemtime($cache_location) > $file_modified_time ) { - if ($this->config->use_igbinary) { - /** @var list */ - $stmts = igbinary_unserialize(Providers::safeFileGetContents($cache_location)); - } else { - /** @var list */ - $stmts = unserialize(Providers::safeFileGetContents($cache_location)); - } + $stmts = $this->cache->getItem($cache_location); - return $stmts; + if (is_array($stmts)) { + /** @var list $stmts */ + return $stmts; + } } return null; @@ -118,13 +111,12 @@ class ParserCacheProvider $cache_location = $this->getCacheLocationForPath($file_path, self::PARSER_CACHE_DIRECTORY); if (is_readable($cache_location)) { - if ($this->config->use_igbinary) { - /** @var list */ - return igbinary_unserialize(Providers::safeFileGetContents($cache_location)) ?: null; - } + $stmts = $this->cache->getItem($cache_location); - /** @var list */ - return unserialize(Providers::safeFileGetContents($cache_location)) ?: null; + if (is_array($stmts)) { + /** @var list $stmts */ + return $stmts; + } } return null; @@ -138,11 +130,13 @@ class ParserCacheProvider $cache_location = $this->getCacheLocationForPath($file_path, self::FILE_CONTENTS_CACHE_DIRECTORY); - if (is_readable($cache_location)) { - return Providers::safeFileGetContents($cache_location); + $cache_item = $this->cache->getItem($cache_location); + + if (!is_string($cache_item)) { + return null; } - return null; + return $cache_item; } /** @@ -155,7 +149,7 @@ class ParserCacheProvider } if ($this->existing_file_content_hashes === null) { - $root_cache_directory = $this->config->getCacheDirectory(); + $root_cache_directory = $this->cache->getCacheDirectory(); $file_hashes_path = $root_cache_directory . DIRECTORY_SEPARATOR . self::FILE_HASHES; if (!$root_cache_directory) { @@ -234,11 +228,7 @@ class ParserCacheProvider if ($touch_only) { touch($cache_location); } else { - if ($this->config->use_igbinary) { - file_put_contents($cache_location, igbinary_serialize($stmts), LOCK_EX); - } else { - file_put_contents($cache_location, serialize($stmts), LOCK_EX); - } + $this->cache->saveItem($cache_location, $stmts); $file_cache_key = $this->getParserCacheKey($file_path); $this->new_file_content_hashes[$file_cache_key] = $file_content_hash; @@ -267,7 +257,7 @@ class ParserCacheProvider return; } - $root_cache_directory = $this->config->getCacheDirectory(); + $root_cache_directory = $this->cache->getCacheDirectory(); if (!$root_cache_directory) { return; @@ -299,13 +289,12 @@ class ParserCacheProvider } $cache_location = $this->getCacheLocationForPath($file_path, self::FILE_CONTENTS_CACHE_DIRECTORY, true); - - file_put_contents($cache_location, $file_contents, LOCK_EX); + $this->cache->saveItem($cache_location, $file_contents); } public function deleteOldParserCaches(float $time_before): int { - $cache_directory = $this->config->getCacheDirectory(); + $cache_directory = $this->cache->getCacheDirectory(); $this->existing_file_content_hashes = null; $this->new_file_content_hashes = []; @@ -328,8 +317,8 @@ class ParserCacheProvider continue; } - if (filemtime($full_path) < $time_before && is_writable($full_path)) { - unlink($full_path); + if (filemtime($full_path) < $time_before) { + $this->cache->deleteItem($full_path); ++$removed_count; } } @@ -346,7 +335,7 @@ class ParserCacheProvider $hash = hash('md4', $file_path); } - return $hash . ($this->config->use_igbinary ? '-igbinary' : '') . '-r'; + return $hash . ($this->cache->use_igbinary ? '-igbinary' : '') . '-r'; } @@ -355,7 +344,7 @@ class ParserCacheProvider string $subdirectory, bool $create_directory = false ): string { - $root_cache_directory = $this->config->getCacheDirectory(); + $root_cache_directory = $this->cache->getCacheDirectory(); if (!$root_cache_directory) { throw new UnexpectedValueException('No cache directory defined'); diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ProjectCacheProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ProjectCacheProvider.php index b97b0c31..4948acc5 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ProjectCacheProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ProjectCacheProvider.php @@ -78,20 +78,19 @@ class ProjectCacheProvider public function hasLockfileChanged(): bool { - if (!file_exists($this->composer_lock_location)) { - return true; - } + if (file_exists($this->composer_lock_location)) { + $lockfile_contents = Providers::safeFileGetContents($this->composer_lock_location); + if (!$lockfile_contents) { + return true; + } - $lockfile_contents = Providers::safeFileGetContents($this->composer_lock_location); - - if (!$lockfile_contents) { - return true; - } - - if (PHP_VERSION_ID >= 8_01_00) { - $hash = hash('xxh128', $lockfile_contents); + if (PHP_VERSION_ID >= 8_01_00) { + $hash = hash('xxh128', $lockfile_contents); + } else { + $hash = hash('md4', $lockfile_contents); + } } else { - $hash = hash('md4', $lockfile_contents); + $hash = ''; } $changed = $hash !== $this->getComposerLockHash(); diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/Providers.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/Providers.php index 57f5f848..b3a5a2a8 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/Providers.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/Providers.php @@ -51,7 +51,7 @@ class Providers $parser_cache_provider, $file_storage_cache_provider, ); - $this->file_reference_provider = new FileReferenceProvider($file_reference_cache_provider); + $this->file_reference_provider = new FileReferenceProvider($file_provider, $file_reference_cache_provider); } public static function safeFileGetContents(string $path): string diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFillReturnTypeProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFillReturnTypeProvider.php index f7f0cd24..3d0a08f2 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFillReturnTypeProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFillReturnTypeProvider.php @@ -7,7 +7,6 @@ use Psalm\Plugin\EventHandler\Event\FunctionReturnTypeProviderEvent; use Psalm\Plugin\EventHandler\FunctionReturnTypeProviderInterface; use Psalm\Type; use Psalm\Type\Atomic\TArray; -use Psalm\Type\Atomic\TIntRange; use Psalm\Type\Atomic\TKeyedArray; use Psalm\Type\Atomic\TNonEmptyArray; use Psalm\Type\Union; @@ -99,10 +98,10 @@ class ArrayFillReturnTypeProvider implements FunctionReturnTypeProviderInterface ) { return new Union([ new TNonEmptyArray([ - new Union([new TIntRange( + Type::getIntRange( $first_arg_type->getSingleIntLiteral()->value, $second_arg_type->getSingleIntLiteral()->value, - )]), + ), $value_type_from_third_arg, ]), ]); diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/DirnameReturnTypeProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/DirnameReturnTypeProvider.php index c8867999..6d96bf81 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/DirnameReturnTypeProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/DirnameReturnTypeProvider.php @@ -9,6 +9,7 @@ use Psalm\Plugin\EventHandler\Event\FunctionReturnTypeProviderEvent; use Psalm\Plugin\EventHandler\FunctionReturnTypeProviderInterface; use Psalm\Type; use Psalm\Type\Atomic\TLiteralInt; +use Psalm\Type\Atomic\TNonEmptyString; use Psalm\Type\Union; use function array_values; @@ -61,6 +62,16 @@ class DirnameReturnTypeProvider implements FunctionReturnTypeProviderInterface $statements_source->getCodebase()->config, ); + if ($evaled_path === null) { + $type = $node_type_provider->getType($call_args[0]->value); + if ($type !== null && $type->isSingle()) { + $atomic_type = array_values($type->getAtomicTypes())[0]; + if ($atomic_type instanceof TNonEmptyString) { + return Type::getNonEmptyString(); + } + } + } + if ($evaled_path === null) { return Type::getString(); } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/ImagickPixelColorReturnTypeProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/ImagickPixelColorReturnTypeProvider.php index 384f5572..b756e98a 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/ImagickPixelColorReturnTypeProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/ImagickPixelColorReturnTypeProvider.php @@ -6,7 +6,6 @@ use Psalm\Internal\Analyzer\StatementsAnalyzer; use Psalm\Plugin\EventHandler\Event\MethodReturnTypeProviderEvent; use Psalm\Plugin\EventHandler\MethodReturnTypeProviderInterface; use Psalm\Type; -use Psalm\Type\Atomic\TIntRange; use Psalm\Type\Atomic\TKeyedArray; use Psalm\Type\Atomic\TLiteralInt; use Psalm\Type\Union; @@ -57,10 +56,10 @@ class ImagickPixelColorReturnTypeProvider implements MethodReturnTypeProviderInt if (isset($formats[0])) { $types []= new Union([ new TKeyedArray([ - 'r' => new Union([new TIntRange(0, 255)]), - 'g' => new Union([new TIntRange(0, 255)]), - 'b' => new Union([new TIntRange(0, 255)]), - 'a' => new Union([new TIntRange(0, 1)]), + 'r' => Type::getIntRange(0, 255), + 'g' => Type::getIntRange(0, 255), + 'b' => Type::getIntRange(0, 255), + 'a' => Type::getIntRange(0, 1), ]), ]); } @@ -77,10 +76,10 @@ class ImagickPixelColorReturnTypeProvider implements MethodReturnTypeProviderInt if (isset($formats[2])) { $types []= new Union([ new TKeyedArray([ - 'r' => new Union([new TIntRange(0, 255)]), - 'g' => new Union([new TIntRange(0, 255)]), - 'b' => new Union([new TIntRange(0, 255)]), - 'a' => new Union([new TIntRange(0, 255)]), + 'r' => Type::getIntRange(0, 255), + 'g' => Type::getIntRange(0, 255), + 'b' => Type::getIntRange(0, 255), + 'a' => Type::getIntRange(0, 255), ]), ]); } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/MinMaxReturnTypeProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/MinMaxReturnTypeProvider.php index 516b8b5f..2f4b7fff 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/MinMaxReturnTypeProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/MinMaxReturnTypeProvider.php @@ -127,7 +127,7 @@ class MinMaxReturnTypeProvider implements FunctionReturnTypeProviderInterface return Type::getInt(false, $min_potential_int); } - return new Union([new TIntRange($min_potential_int, $max_potential_int)]); + return Type::getIntRange($min_potential_int, $max_potential_int); } //if we're dealing with non-int elements, just combine them all together diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/PdoStatementReturnTypeProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/PdoStatementReturnTypeProvider.php index 0e09aa85..3edc2342 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/PdoStatementReturnTypeProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/PdoStatementReturnTypeProvider.php @@ -27,88 +27,268 @@ class PdoStatementReturnTypeProvider implements MethodReturnTypeProviderInterfac public static function getMethodReturnType(MethodReturnTypeProviderEvent $event): ?Union { $config = Config::getInstance(); + $method_name_lowercase = $event->getMethodNameLowercase(); + + if (!$config->php_extensions["pdo"]) { + return null; + } + + if ($method_name_lowercase === 'fetch') { + return self::handleFetch($event); + } + + if ($method_name_lowercase === 'fetchall') { + return self::handleFetchAll($event); + } + + return null; + } + + private static function handleFetch(MethodReturnTypeProviderEvent $event): ?Union + { $source = $event->getSource(); $call_args = $event->getCallArgs(); - $method_name_lowercase = $event->getMethodNameLowercase(); - if ($method_name_lowercase === 'fetch' - && $config->php_extensions["pdo"] - && isset($call_args[0]) + $fetch_mode = 0; + + if (isset($call_args[0]) && ($first_arg_type = $source->getNodeTypeProvider()->getType($call_args[0]->value)) && $first_arg_type->isSingleIntLiteral() ) { $fetch_mode = $first_arg_type->getSingleIntLiteral()->value; + } - switch ($fetch_mode) { - case 2: // PDO::FETCH_ASSOC - array|false - return new Union([ - new TArray([ - Type::getString(), - new Union([ - new TScalar(), - new TNull(), + switch ($fetch_mode) { + case 2: // PDO::FETCH_ASSOC - array|false + return new Union([ + new TArray([ + Type::getString(), + new Union([ + new TScalar(), + new TNull(), + ]), + ]), + new TFalse(), + ]); + + case 4: // PDO::FETCH_BOTH - array|false + return new Union([ + new TArray([ + Type::getArrayKey(), + new Union([ + new TScalar(), + new TNull(), + ]), + ]), + new TFalse(), + ]); + + case 6: // PDO::FETCH_BOUND - bool + return Type::getBool(); + + case 7: // PDO::FETCH_COLUMN - scalar|null|false + return new Union([ + new TScalar(), + new TNull(), + new TFalse(), + ]); + + case 8: // PDO::FETCH_CLASS - object|false + return new Union([ + new TObject(), + new TFalse(), + ]); + + case 1: // PDO::FETCH_LAZY - object|false + // This actually returns a PDORow object, but that class is + // undocumented, and its attributes are all dynamic anyway + return new Union([ + new TObject(), + new TFalse(), + ]); + + case 11: // PDO::FETCH_NAMED - array>|false + return new Union([ + new TArray([ + Type::getString(), + new Union([ + new TScalar(), + new TNull(), + Type::getListAtomic( + new Union([ + new TScalar(), + new TNull(), + ]), + ), + ]), + ]), + new TFalse(), + ]); + + case 12: // PDO::FETCH_KEY_PAIR - array + return new Union([ + new TArray([ + Type::getArrayKey(), + new Union([ + new TScalar(), + new TNull(), + ]), + ]), + ]); + + case 3: // PDO::FETCH_NUM - list|false + return new Union([ + Type::getListAtomic( + new Union([ + new TScalar(), + new TNull(), + ]), + ), + new TFalse(), + ]); + + case 5: // PDO::FETCH_OBJ - stdClass|false + return new Union([ + new TNamedObject('stdClass'), + new TFalse(), + ]); + } + + return null; + } + + private static function handleFetchAll(MethodReturnTypeProviderEvent $event): ?Union + { + $source = $event->getSource(); + $call_args = $event->getCallArgs(); + $fetch_mode = 0; + + if (isset($call_args[0]) + && ($first_arg_type = $source->getNodeTypeProvider()->getType($call_args[0]->value)) + && $first_arg_type->isSingleIntLiteral() + ) { + $fetch_mode = $first_arg_type->getSingleIntLiteral()->value; + } + + $fetch_class_name = null; + + if (isset($call_args[1]) + && ($second_arg_type = $source->getNodeTypeProvider()->getType($call_args[1]->value)) + && $second_arg_type->isSingleStringLiteral() + ) { + $fetch_class_name = $second_arg_type->getSingleStringLiteral()->value; + } + + switch ($fetch_mode) { + case 2: // PDO::FETCH_ASSOC - list> + return new Union([ + Type::getListAtomic( + new Union([ + new TArray([ + Type::getString(), + new Union([ + new TScalar(), + new TNull(), + ]), ]), ]), - new TFalse(), - ]); + ), + ]); - case 4: // PDO::FETCH_BOTH - array|false - return new Union([ - new TArray([ - Type::getArrayKey(), - new Union([ - new TScalar(), - new TNull(), + case 4: // PDO::FETCH_BOTH - list> + return new Union([ + Type::getListAtomic( + new Union([ + new TArray([ + Type::getArrayKey(), + new Union([ + new TScalar(), + new TNull(), + ]), ]), ]), - new TFalse(), - ]); + ), + ]); - case 6: // PDO::FETCH_BOUND - bool - return Type::getBool(); + case 6: // PDO::FETCH_BOUND - list + return new Union([ + Type::getListAtomic( + Type::getBool(), + ), + ]); - case 8: // PDO::FETCH_CLASS - object|false - return new Union([ - new TObject(), - new TFalse(), - ]); + case 7: // PDO::FETCH_COLUMN - list + return new Union([ + Type::getListAtomic( + new Union([ + new TScalar(), + new TNull(), + ]), + ), + ]); - case 1: // PDO::FETCH_LAZY - object|false - // This actually returns a PDORow object, but that class is - // undocumented, and its attributes are all dynamic anyway - return new Union([ - new TObject(), - new TFalse(), - ]); + case 8: // PDO::FETCH_CLASS - list + return new Union([ + Type::getListAtomic( + new Union([ + $fetch_class_name ? new TNamedObject($fetch_class_name) : new TObject(), + ]), + ), + ]); - case 11: // PDO::FETCH_NAMED - array>|false - return new Union([ - new TArray([ - Type::getString(), - new Union([ - new TScalar(), - Type::getListAtomic(Type::getScalar()), + case 11: // PDO::FETCH_NAMED - list>> + return new Union([ + Type::getListAtomic( + new Union([ + new TArray([ + Type::getString(), + new Union([ + new TScalar(), + new TNull(), + Type::getListAtomic( + new Union([ + new TScalar(), + new TNull(), + ]), + ), + ]), ]), ]), - new TFalse(), - ]); + ), + ]); - case 3: // PDO::FETCH_NUM - list|false - return new Union([ - Type::getListAtomic( - new Union([ - new TScalar(), - new TNull(), - ]), - ), - new TFalse(), - ]); + case 12: // PDO::FETCH_KEY_PAIR - array + return new Union([ + new TArray([ + Type::getArrayKey(), + new Union([ + new TScalar(), + new TNull(), + ]), + ]), + ]); - case 5: // PDO::FETCH_OBJ - stdClass|false - return new Union([ - new TNamedObject('stdClass'), - new TFalse(), - ]); - } + case 3: // PDO::FETCH_NUM - list> + return new Union([ + Type::getListAtomic( + new Union([ + Type::getListAtomic( + new Union([ + new TScalar(), + new TNull(), + ]), + ), + ]), + ), + ]); + + case 5: // PDO::FETCH_OBJ - list + return new Union([ + Type::getListAtomic( + new Union([ + new TNamedObject('stdClass'), + ]), + ), + ]); } return null; diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/RandReturnTypeProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/RandReturnTypeProvider.php index 7ccfce13..ea6184e7 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/RandReturnTypeProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/RandReturnTypeProvider.php @@ -63,6 +63,6 @@ class RandReturnTypeProvider implements FunctionReturnTypeProviderInterface } } - return new Union([new TIntRange($min_value, $max_value)]); + return Type::getIntRange($min_value, $max_value); } } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/SprintfReturnTypeProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/SprintfReturnTypeProvider.php new file mode 100644 index 00000000..8c9af941 --- /dev/null +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/SprintfReturnTypeProvider.php @@ -0,0 +1,329 @@ + + */ + public static function getFunctionIds(): array + { + return [ + 'printf', + 'sprintf', + ]; + } + + public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $event): ?Union + { + $statements_source = $event->getStatementsSource(); + $call_args = $event->getCallArgs(); + + $has_splat_args = false; + $node_type_provider = $statements_source->getNodeTypeProvider(); + foreach ($call_args as $call_arg) { + $type = $node_type_provider->getType($call_arg->value); + if ($type === null) { + continue; + } + + // if it's an array, used with splat operator + // we cannot validate it reliably below and report false positive errors + if ($type->isArray()) { + $has_splat_args = true; + break; + } + } + + // there is only 1 array argument, fall back to the default handling + // eventually this could be refined + // to check if it's an array with literal string as first element for further checking + if (count($call_args) === 1 && $has_splat_args === true) { + return null; + } + + // it makes no sense to use sprintf when there is only 1 arg (the format) + // as it wouldn't have any placeholders + if (count($call_args) === 1 && $event->getFunctionId() === 'sprintf') { + IssueBuffer::maybeAdd( + new TooFewArguments( + 'Too few arguments for ' . $event->getFunctionId() . ', expecting at least 2 arguments', + $event->getCodeLocation(), + $event->getFunctionId(), + ), + $statements_source->getSuppressedIssues(), + ); + + return null; + } + + // PHP 7 handling for formats that do not contain anything but placeholders + $is_falsable = true; + foreach ($call_args as $index => $call_arg) { + $type = $node_type_provider->getType($call_arg->value); + if ($type === null && $index === 0 && $event->getFunctionId() === 'printf') { + break; + } + + if ($type === null) { + continue; + } + + if ($index === 0 && $type->isSingleStringLiteral()) { + if ($type->getSingleStringLiteral()->value === '') { + IssueBuffer::maybeAdd( + new InvalidArgument( + 'Argument 1 of ' . $event->getFunctionId() . ' must not be an empty string', + $event->getCodeLocation(), + $event->getFunctionId(), + ), + $statements_source->getSuppressedIssues(), + ); + + if ($event->getFunctionId() === 'printf') { + return Type::getInt(false, 0); + } + + return Type::getString(''); + } + + // there are probably additional formats that return an empty string, this is just a starting point + if (preg_match('/^%(?:\d+\$)?[-+]?0(?:\.0)?s$/', $type->getSingleStringLiteral()->value) === 1) { + IssueBuffer::maybeAdd( + new InvalidArgument( + 'The pattern of argument 1 of ' . $event->getFunctionId() + . ' will always return an empty string', + $event->getCodeLocation(), + $event->getFunctionId(), + ), + $statements_source->getSuppressedIssues(), + ); + + if ($event->getFunctionId() === 'printf') { + return Type::getInt(false, 0); + } + + return Type::getString(''); + } + + // these placeholders are too complex to handle for now + if (preg_match( + '/%(?:\d+\$)?[-+]?(?:\d+|\*)(?:\.(?:\d+|\*))?[bcdouxXeEfFgGhHs]/', + $type->getSingleStringLiteral()->value, + ) === 1) { + return null; + } + + // assume a random, high number for tests + $provided_placeholders_count = $has_splat_args === true ? 100 : count($call_args) - 1; + $dummy = array_fill(0, $provided_placeholders_count, ''); + + // check if we have enough/too many arguments and a valid format + $initial_result = null; + while (count($dummy) > -1) { + $result = null; + try { + // before PHP 8, an uncatchable Warning is thrown if too few arguments are passed + // which is ignored and handled below instead + $result = @sprintf($type->getSingleStringLiteral()->value, ...$dummy); + if ($initial_result === null) { + $initial_result = $result; + + if ($result === $type->getSingleStringLiteral()->value) { + IssueBuffer::maybeAdd( + new InvalidArgument( + 'Argument 1 of ' . $event->getFunctionId() + . ' does not contain any placeholders', + $event->getCodeLocation(), + $event->getFunctionId(), + ), + $statements_source->getSuppressedIssues(), + ); + + return null; + } + } + } catch (ValueError $value_error) { + // PHP 8 + // the format is invalid + IssueBuffer::maybeAdd( + new InvalidArgument( + 'Argument 1 of ' . $event->getFunctionId() . ' is invalid - ' + . $value_error->getMessage(), + $event->getCodeLocation(), + $event->getFunctionId(), + ), + $statements_source->getSuppressedIssues(), + ); + + break 2; + } catch (ArgumentCountError $error) { + // PHP 8 + if (count($dummy) === $provided_placeholders_count) { + IssueBuffer::maybeAdd( + new TooFewArguments( + 'Too few arguments for ' . $event->getFunctionId(), + $event->getCodeLocation(), + $event->getFunctionId(), + ), + $statements_source->getSuppressedIssues(), + ); + + break 2; + } + } + + if ($result === false && count($dummy) === $provided_placeholders_count) { + // could be invalid format or too few arguments + // we cannot distinguish this in PHP 7 without additional checks + $max_dummy = array_fill(0, 100, ''); + $result = @sprintf($type->getSingleStringLiteral()->value, ...$max_dummy); + if ($result === false) { + // the format is invalid + IssueBuffer::maybeAdd( + new InvalidArgument( + 'Argument 1 of ' . $event->getFunctionId() . ' is invalid', + $event->getCodeLocation(), + $event->getFunctionId(), + ), + $statements_source->getSuppressedIssues(), + ); + } else { + IssueBuffer::maybeAdd( + new TooFewArguments( + 'Too few arguments for ' . $event->getFunctionId(), + $event->getCodeLocation(), + $event->getFunctionId(), + ), + $statements_source->getSuppressedIssues(), + ); + } + + return Type::getFalse(); + } + + // we can only validate the format and arg 1 when using splat + if ($has_splat_args === true) { + break; + } + + if (is_string($result) && count($dummy) + 1 <= $provided_placeholders_count) { + IssueBuffer::maybeAdd( + new TooManyArguments( + 'Too many arguments for the number of placeholders in ' . $event->getFunctionId(), + $event->getCodeLocation(), + $event->getFunctionId(), + ), + $statements_source->getSuppressedIssues(), + ); + + break; + } + + if (!is_string($result)) { + break; + } + + // abort if it's empty, since we checked everything + if (array_pop($dummy) === null) { + break; + } + } + + if ($event->getFunctionId() === 'printf') { + // printf only has the format validated above + // don't change the return type + return null; + } + + if ($initial_result !== null && $initial_result !== false && $initial_result !== '') { + return Type::getNonEmptyString(); + } + + // if we didn't have any valid result + // the pattern is invalid or not yet supported by the return type provider + if ($initial_result === null || $initial_result === false) { + return null; + } + + // the initial result is an empty string + // which means the format is valid and it depends on the args, whether it is non-empty-string or not + $is_falsable = false; + } + + if ($index === 0 && $event->getFunctionId() === 'printf') { + // printf only has the format validated above + // don't change the return type + break; + } + + if ($index === 0) { + continue; + } + + // if the function has more arguments than the pattern has placeholders, this could be a false positive + // if the param is not used in the pattern + if ($type->isNonEmptyString() || $type->isInt() || $type->isFloat()) { + return Type::getNonEmptyString(); + } + + // check for unions of either + $atomic_types = $type->getAtomicTypes(); + if ($atomic_types === []) { + continue; + } + + foreach ($atomic_types as $atomic_type) { + if ($atomic_type instanceof TNonEmptyString + || $atomic_type instanceof TClassString + || ($atomic_type instanceof TLiteralString && $atomic_type->value !== '') + || $atomic_type instanceof TInt + || $atomic_type instanceof TFloat + || $atomic_type instanceof TNumeric) { + // valid non-empty types, potentially there are more though + continue; + } + + // empty or generic string + // or other unhandled type + continue 2; + } + + return Type::getNonEmptyString(); + } + + if ($is_falsable === false) { + return Type::getString(); + } + + return null; + } +} diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/StrReplaceReturnTypeProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/StrReplaceReturnTypeProvider.php index f56f8279..c7d64270 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/StrReplaceReturnTypeProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ReturnTypeProvider/StrReplaceReturnTypeProvider.php @@ -6,13 +6,10 @@ use Psalm\Internal\Analyzer\StatementsAnalyzer; use Psalm\Plugin\EventHandler\Event\FunctionReturnTypeProviderEvent; use Psalm\Plugin\EventHandler\FunctionReturnTypeProviderInterface; use Psalm\Type; -use Psalm\Type\Atomic\TNull; -use Psalm\Type\Atomic\TString; use Psalm\Type\Union; use function call_user_func; use function count; -use function in_array; /** * @internal @@ -27,13 +24,10 @@ class StrReplaceReturnTypeProvider implements FunctionReturnTypeProviderInterfac return [ 'str_replace', 'str_ireplace', - 'substr_replace', - 'preg_replace', - 'preg_replace_callback', ]; } - public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $event): Union + public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $event): ?Union { $statements_source = $event->getStatementsSource(); $call_args = $event->getCallArgs(); @@ -41,47 +35,34 @@ class StrReplaceReturnTypeProvider implements FunctionReturnTypeProviderInterfac if (!$statements_source instanceof StatementsAnalyzer || count($call_args) < 3 ) { - return Type::getMixed(); + // use the defaults, it will already report an error for the invalid params + return null; } if ($subject_type = $statements_source->node_data->getType($call_args[2]->value)) { - if (!$subject_type->hasString() && $subject_type->hasArray()) { - return Type::getArray(); + if (!$subject_type->isSingleStringLiteral()) { + return null; } - $return_type = Type::getString(); - - if (in_array($function_id, ['str_replace', 'str_ireplace'], true) - && $subject_type->isSingleStringLiteral() + $first_arg = $statements_source->node_data->getType($call_args[0]->value); + $second_arg = $statements_source->node_data->getType($call_args[1]->value); + if ($first_arg + && $second_arg && $first_arg->isSingleStringLiteral() + && $second_arg->isSingleStringLiteral() ) { - $first_arg = $statements_source->node_data->getType($call_args[0]->value); - $second_arg = $statements_source->node_data->getType($call_args[1]->value); - if ($first_arg - && $second_arg && $first_arg->isSingleStringLiteral() - && $second_arg->isSingleStringLiteral() - ) { - /** - * @var string $replaced_string - */ - $replaced_string = call_user_func( - $function_id, - $first_arg->getSingleStringLiteral()->value, - $second_arg->getSingleStringLiteral()->value, - $subject_type->getSingleStringLiteral()->value, - ); - $return_type = Type::getString($replaced_string); - } - } elseif (in_array($function_id, ['preg_replace', 'preg_replace_callback'], true)) { - $codebase = $statements_source->getCodebase(); - - $return_type = new Union([new TString, new TNull()], [ - 'ignore_nullable_issues' => $codebase->config->ignore_internal_nullable_issues, - ]); + /** + * @var string $replaced_string + */ + $replaced_string = call_user_func( + $function_id, + $first_arg->getSingleStringLiteral()->value, + $second_arg->getSingleStringLiteral()->value, + $subject_type->getSingleStringLiteral()->value, + ); + return Type::getString($replaced_string); } - - return $return_type; } - return Type::getMixed(); + return null; } } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/StatementsProvider.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/StatementsProvider.php index 6393cd34..21bccd1c 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/StatementsProvider.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/StatementsProvider.php @@ -52,8 +52,6 @@ class StatementsProvider private ?FileStorageCacheProvider $file_storage_cache_provider = null; - private StatementsVolatileCache $statements_volatile_cache; - /** * @var array> */ @@ -97,7 +95,6 @@ class StatementsProvider $this->parser_cache_provider = $parser_cache_provider; $this->this_modified_time = filemtime(__FILE__); $this->file_storage_cache_provider = $file_storage_cache_provider; - $this->statements_volatile_cache = StatementsVolatileCache::getInstance(); } /** @@ -132,20 +129,11 @@ class StatementsProvider if (!$this->parser_cache_provider || (!$config->isInProjectDirs($file_path) && strpos($file_path, 'vendor')) ) { - $cache_key = "{$file_content_hash}:{$analysis_php_version_id}"; - if ($this->statements_volatile_cache->has($cache_key)) { - return $this->statements_volatile_cache->get($cache_key); - } - $progress->debug('Parsing ' . $file_path . "\n"); $has_errors = false; - $stmts = self::parseStatements($file_contents, $analysis_php_version_id, $has_errors, $file_path); - - $this->statements_volatile_cache->set($cache_key, $stmts); - - return $stmts; + return self::parseStatements($file_contents, $analysis_php_version_id, $has_errors, $file_path); } $stmts = $this->parser_cache_provider->loadStatementsFromCache( diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/StatementsVolatileCache.php b/vendor/vimeo/psalm/src/Psalm/Internal/Provider/StatementsVolatileCache.php deleted file mode 100644 index e9fef387..00000000 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Provider/StatementsVolatileCache.php +++ /dev/null @@ -1,100 +0,0 @@ -> - */ - protected array $cache = []; - - /** - * @var array - */ - protected array $access = []; - - protected int $max_size; - - protected static ?StatementsVolatileCache $instance = null; - - public function __construct(int $max_size = 4096) - { - $this->max_size = $max_size; - } - - public static function getInstance(): StatementsVolatileCache - { - if (is_null(self::$instance)) { - self::$instance = new self(); - } - - return self::$instance; - } - - public function has(string $key): bool - { - return array_key_exists($key, $this->cache); - } - - /** - * @return list - * @throws InvalidArgumentException - */ - public function get(string $key): array - { - if (! $this->has($key)) { - throw new InvalidArgumentException('Given $key does not exists'); - } - - $access_index = array_search($key, $this->access); - if (false !== $access_index) { - array_splice($this->access, $access_index, 1); - } - $this->access[] = $key; - - return $this->cache[$key]; - } - - /** - * @param list $content - */ - public function set(string $key, array $content): void - { - if (count($this->cache) > $this->max_size) { - reset($this->access); - - $oldest_key_index = key($this->access); - - if (! is_null($oldest_key_index)) { - $oldest_key = $this->access[$oldest_key_index]; - unset($this->cache[$oldest_key]); - unset($this->access[$oldest_key_index]); - } - } - - $this->cache[$key] = $content; - $this->access[] = $key; - } - - public function clearCache(): void - { - $this->cache = []; - $this->access = []; - } -} diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/RuntimeCaches.php b/vendor/vimeo/psalm/src/Psalm/Internal/RuntimeCaches.php index 2d63da00..694b49e4 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/RuntimeCaches.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/RuntimeCaches.php @@ -14,7 +14,6 @@ use Psalm\Internal\Provider\ClassLikeStorageProvider; use Psalm\Internal\Provider\FileReferenceProvider; use Psalm\Internal\Provider\FileStorageProvider; use Psalm\Internal\Provider\StatementsProvider; -use Psalm\Internal\Provider\StatementsVolatileCache; use Psalm\Internal\Scanner\ParsedDocblock; use Psalm\Internal\Type\TypeTokenizer; use Psalm\IssueBuffer; @@ -42,6 +41,5 @@ abstract class RuntimeCaches StatementsProvider::clearLexer(); StatementsProvider::clearParser(); ParsedDocblock::resetNewlineBetweenAnnotations(); - StatementsVolatileCache::getInstance()->clearCache(); } } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Scanner/DocblockParser.php b/vendor/vimeo/psalm/src/Psalm/Internal/Scanner/DocblockParser.php index 2aca637e..0c052346 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Scanner/DocblockParser.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Scanner/DocblockParser.php @@ -12,6 +12,7 @@ use function count; use function explode; use function implode; use function is_string; +use function ltrim; use function min; use function preg_match; use function preg_replace; @@ -54,7 +55,8 @@ class DocblockParser } // Normalize multi-line @specials. - $lines = explode("\n", $docblock); + $lines = explode("\n", str_replace("\t", ' ', $docblock)); + $has_r = strpos($docblock, "\r") === false ? false : true; $special = []; @@ -62,9 +64,9 @@ class DocblockParser $last = false; foreach ($lines as $k => $line) { - if (preg_match('/^[ \t]*\*?\s*@\w/i', $line)) { + if (strpos($line, '@') !== false && preg_match('/^ *\*?\s*@\w/', $line)) { $last = $k; - } elseif (preg_match('/^\s*\r?$/', $line)) { + } elseif (trim($line) === '') { $last = false; } elseif ($last !== false) { $old_last_line = $lines[$last]; @@ -78,26 +80,29 @@ class DocblockParser foreach ($lines as $k => $line) { $original_line_length = strlen($line); - - $line = str_replace("\r", '', $line); + if ($has_r === true) { + $line = str_replace("\r", '', $line); + } if ($first_line_padding === null) { $asterisk_pos = strpos($line, '*'); - if ($asterisk_pos) { + if ($asterisk_pos === 0 || $asterisk_pos === 1) { + $first_line_padding = ''; + } elseif ($asterisk_pos > 1) { $first_line_padding = substr($line, 0, $asterisk_pos - 1); } } - if (preg_match('/^[ \t]*\*?\s*@([\w\-\\\:]+)[\t ]*(.*)$/sm', $line, $matches, PREG_OFFSET_CAPTURE)) { + if (preg_match('/^ *\*?\s*@([\w\-\\\:]+) *(.*)$/sm', $line, $matches, PREG_OFFSET_CAPTURE)) { /** @var array $matches */ [, $type_info, $data_info] = $matches; [$type] = $type_info; [$data, $data_offset] = $data_info; - if (strpos($data, '*')) { - $data = rtrim(preg_replace('/^[ \t]*\*\s*$/m', '', $data)); + if (strpos($data, '*') !== false) { + $data = rtrim(preg_replace('/^ *\*\s*$/m', '', $data)); } if (empty($special[$type])) { @@ -111,10 +116,9 @@ class DocblockParser unset($lines[$k]); } else { // Strip the leading *, if present. - $text = $lines[$k]; - $text = str_replace("\t", ' ', $text); - $text = preg_replace('/^ *\*/', '', $text, 1); - $lines[$k] = $text; + // technically only need to preg_replace('/^ *\*/', '', $lines[$k], 1) + // however it's slower and removing all spaces and * is fine + $lines[$k] = ltrim($lines[$k], ' *'); } $line_offset += $original_line_length + 1; @@ -122,13 +126,20 @@ class DocblockParser // Smush the whole docblock to the left edge. $min_indent = 80; + $reached_first_non_empty_line = false; foreach ($lines as $k => $line) { $indent = strspn($line, ' '); if ($indent === strlen($line)) { // This line consists of only spaces. Trim it completely. + if ($reached_first_non_empty_line === false) { + // remove any leading empty lines here, to avoid a preg_replace later + unset($lines[$k]); + continue; + } $lines[$k] = ''; continue; } + $reached_first_non_empty_line = true; $min_indent = min($indent, $min_indent); } if ($min_indent > 0) { @@ -142,10 +153,6 @@ class DocblockParser $docblock = implode("\n", $lines); $docblock = rtrim($docblock); - // Trim any empty lines off the front, but leave the indent level if there - // is one. - $docblock = preg_replace('/^\s*\n/', '', $docblock, 1); - $parsed = new ParsedDocblock($docblock, $special, $first_line_padding ?: ''); self::resolveTags($parsed); diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Scanner/PhpStormMetaScanner.php b/vendor/vimeo/psalm/src/Psalm/Internal/Scanner/PhpStormMetaScanner.php index 5058e67c..b812456d 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Scanner/PhpStormMetaScanner.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Scanner/PhpStormMetaScanner.php @@ -15,7 +15,6 @@ use Psalm\Type\Union; use ReflectionProperty; use function count; -use function implode; use function is_string; use function str_replace; use function strpos; @@ -45,7 +44,7 @@ class PhpStormMetaScanner $map = []; - if ($args[1]->value->name->parts === ['map'] + if ($args[1]->value->name->getParts() === ['map'] && $args[1]->value->getArgs() && $args[1]->value->getArgs()[0]->value instanceof PhpParser\Node\Expr\Array_ ) { @@ -59,7 +58,7 @@ class PhpStormMetaScanner && strtolower($array_item->value->name->name) ) { $map[$array_item->key->value] = new Union([ - new TNamedObject(implode('\\', $array_item->value->class->parts)), + new TNamedObject($array_item->value->class->toString()), ]); } elseif ($array_item->value instanceof PhpParser\Node\Scalar\String_) { $map[$array_item->key->value] = $array_item->value->value; @@ -93,7 +92,7 @@ class PhpStormMetaScanner && strtolower($array_item->value->name->name) ) { $map[$meta_key] = new Union([ - new TNamedObject(implode('\\', $array_item->value->class->parts)), + new TNamedObject($array_item->value->class->toString()), ]); } elseif ($array_item->value instanceof PhpParser\Node\Scalar\String_) { $map[$meta_key] = $array_item->value->value; @@ -104,7 +103,7 @@ class PhpStormMetaScanner $type_offset = null; - if ($args[1]->value->name->parts === ['type'] + if ($args[1]->value->name->getParts() === ['type'] && $args[1]->value->getArgs() && $args[1]->value->getArgs()[0]->value instanceof PhpParser\Node\Scalar\LNumber ) { @@ -113,7 +112,7 @@ class PhpStormMetaScanner $element_type_offset = null; - if ($args[1]->value->name->parts === ['elementType'] + if ($args[1]->value->name->getParts() === ['elementType'] && $args[1]->value->getArgs() && $args[1]->value->getArgs()[0]->value instanceof PhpParser\Node\Scalar\LNumber ) { @@ -128,7 +127,7 @@ class PhpStormMetaScanner || $identifier->getArgs()[0]->value instanceof PhpParser\Node\Scalar\LNumber ) ) { - $meta_fq_classlike_name = implode('\\', $identifier->class->parts); + $meta_fq_classlike_name = $identifier->class->toString(); $meta_method_name = strtolower($identifier->name->name); @@ -280,7 +279,7 @@ class PhpStormMetaScanner || $identifier->getArgs()[0]->value instanceof PhpParser\Node\Scalar\LNumber ) ) { - $function_id = strtolower(implode('\\', $identifier->name->parts)); + $function_id = strtolower($identifier->name->toString()); if ($map) { $offset = 0; diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Type/AssertionReconciler.php b/vendor/vimeo/psalm/src/Psalm/Internal/Type/AssertionReconciler.php index ac8419f3..85410c4c 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Type/AssertionReconciler.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Type/AssertionReconciler.php @@ -771,12 +771,25 @@ class AssertionReconciler extends Reconciler } if ($type_1_param->getId() !== $type_2_param->getId()) { - $type_1_param = $type_2_param; + $type_1_param = $type_2_param->setPossiblyUndefined($type_1_param->possibly_undefined); } } unset($type_1_param); - $matching_atomic_type = $type_1_atomic->setProperties($type_1_properties); + if ($type_1_atomic->fallback_params === null) { + $fallback_types = null; + } else { + //any fallback type is now the value of iterable + $fallback_types = [$type_1_atomic->fallback_params[0], $type_2_param]; + } + + $matching_atomic_type = new TKeyedArray( + $type_1_properties, + $type_1_atomic->class_strings, + $fallback_types, + $type_1_atomic->is_list, + $type_1_atomic->from_docblock, + ); $atomic_comparison_results->type_coerced = true; } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Type/ClosedInheritanceToUnion.php b/vendor/vimeo/psalm/src/Psalm/Internal/Type/ClosedInheritanceToUnion.php new file mode 100644 index 00000000..541f690f --- /dev/null +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Type/ClosedInheritanceToUnion.php @@ -0,0 +1,81 @@ +getAtomicTypes() as $atomic_type) { + if ($atomic_type instanceof TNamedObject) { + $storage = $codebase->classlikes->getStorageFor($atomic_type->value); + + if (null === $storage || null === $storage->inheritors) { + $new_types[] = $atomic_type; + continue; + } + + $template_result = self::getTemplateResult($atomic_type, $codebase); + + $replaced_inheritors = TemplateInferredTypeReplacer::replace( + $storage->inheritors, + $template_result, + $codebase, + ); + + foreach ($replaced_inheritors->getAtomicTypes() as $replaced_atomic_type) { + $new_types[] = $replaced_atomic_type; + } + + $meet_inheritors = true; + } else { + $new_types[] = $atomic_type; + } + } + + if (!$meet_inheritors) { + return $input; + } + + return $new_types ? $input->setTypes($new_types) : $input; + } + + private static function getTemplateResult(TNamedObject $object, Codebase $codebase): TemplateResult + { + if (!$object instanceof TGenericObject) { + return new TemplateResult([], []); + } + + $storage = $codebase->classlikes->getStorageFor($object->value); + + if (null === $storage || null === $storage->template_types) { + return new TemplateResult([], []); + } + + $lower_bounds = []; + $offset = 0; + + foreach ($storage->template_types as $template_name => $templates) { + foreach (array_keys($templates) as $defining_class) { + $lower_bounds[$template_name][$defining_class] = $object->type_params[$offset++]; + } + } + + return new TemplateResult($storage->template_types, $lower_bounds); + } +} diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Type/Comparator/CallableTypeComparator.php b/vendor/vimeo/psalm/src/Psalm/Internal/Type/Comparator/CallableTypeComparator.php index fa3b5328..2999480d 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Type/Comparator/CallableTypeComparator.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Type/Comparator/CallableTypeComparator.php @@ -29,6 +29,7 @@ use Psalm\Type\Atomic\TTemplateParam; use Psalm\Type\Union; use UnexpectedValueException; +use function array_slice; use function end; use function strtolower; use function substr; @@ -65,6 +66,8 @@ class CallableTypeComparator return false; } + $input_variadic_param_idx = null; + if ($input_type_part->params !== null && $container_type_part->params !== null) { foreach ($input_type_part->params as $i => $input_param) { $container_param = null; @@ -79,7 +82,15 @@ class CallableTypeComparator } } + if ($input_param->is_variadic) { + $input_variadic_param_idx = $i; + } + if (!$container_param) { + if ($input_param->is_variadic) { + break; + } + if ($input_param->is_optional) { break; } @@ -103,6 +114,26 @@ class CallableTypeComparator } } + if ($input_variadic_param_idx && isset($input_type_part->params[$input_variadic_param_idx])) { + $input_param = $input_type_part->params[$input_variadic_param_idx]; + + foreach (array_slice($container_type_part->params ?? [], $input_variadic_param_idx) as $container_param) { + if ($container_param->type + && !$container_param->type->hasMixed() + && !UnionTypeComparator::isContainedBy( + $codebase, + $container_param->type, + $input_param->type ?: Type::getMixed(), + false, + false, + $atomic_comparison_result, + ) + ) { + return false; + } + } + } + if (isset($container_type_part->return_type)) { if (!isset($input_type_part->return_type)) { if ($atomic_comparison_result) { diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Type/NegatedAssertionReconciler.php b/vendor/vimeo/psalm/src/Psalm/Internal/Type/NegatedAssertionReconciler.php index 3ce8aedd..f4de672c 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Type/NegatedAssertionReconciler.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Type/NegatedAssertionReconciler.php @@ -59,6 +59,11 @@ class NegatedAssertionReconciler extends Reconciler int &$failed_reconciliation, bool $inside_loop ): Union { + $existing_var_type = ClosedInheritanceToUnion::map( + $existing_var_type, + $statements_analyzer->getCodebase(), + ); + $is_equality = $assertion->hasEquality(); $assertion_type = $assertion->getAtomicType(); diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Type/SimpleAssertionReconciler.php b/vendor/vimeo/psalm/src/Psalm/Internal/Type/SimpleAssertionReconciler.php index 57dd5c2b..0602fff8 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Type/SimpleAssertionReconciler.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Type/SimpleAssertionReconciler.php @@ -2441,7 +2441,9 @@ class SimpleAssertionReconciler extends Reconciler $redundant = false; } elseif ($type instanceof TIterable) { - $array_types[] = Type::getListAtomic($type->type_params[1]); + $array_types[] = $is_non_empty + ? Type::getNonEmptyListAtomic($type->type_params[1]) + : Type::getListAtomic($type->type_params[1]); $redundant = false; } else { diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Type/TemplateStandinTypeReplacer.php b/vendor/vimeo/psalm/src/Psalm/Internal/Type/TemplateStandinTypeReplacer.php index e824e76f..9fa51c42 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Type/TemplateStandinTypeReplacer.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Type/TemplateStandinTypeReplacer.php @@ -36,6 +36,7 @@ use Psalm\Type\Atomic\TTemplateValueOf; use Psalm\Type\Union; use function array_fill; +use function array_filter; use function array_keys; use function array_merge; use function array_search; @@ -1253,6 +1254,7 @@ class TemplateStandinTypeReplacer Atomic $container_type_part, ?array &$container_type_params_covariant = null ): array { + $_ = null; if ($input_type_part instanceof TGenericObject || $input_type_part instanceof TIterable) { $input_type_params = $input_type_part->type_params; } elseif ($codebase->classlike_storage_provider->has($input_type_part->value)) { @@ -1316,40 +1318,43 @@ class TemplateStandinTypeReplacer foreach ($params as $extended_input_param_type) { $new_input_param = null; - foreach ($extended_input_param_type->getAtomicTypes() as $et) { - if ($et instanceof TTemplateParam) { - $ets = Methods::getExtendedTemplatedTypes( - $et, - $template_extends, - ); - } else { - $ets = []; - } - - if ($ets - && $ets[0] instanceof TTemplateParam - && isset( - $input_class_storage->template_types - [$ets[0]->param_name] - [$ets[0]->defining_class], + foreach ($extended_input_param_type->getAtomicTypes() as $extended_template) { + $extended_templates = $extended_template instanceof TTemplateParam + ? array_values( + array_filter( + Methods::getExtendedTemplatedTypes($extended_template, $template_extends), + static fn(Atomic $a) => $a instanceof TTemplateParam, + ), ) - ) { - $old_params_offset = (int) array_search( - $ets[0]->param_name, - array_keys($input_class_storage->template_types), - ); + : []; - $candidate_param_type = $input_type_params[$old_params_offset] ?? Type::getMixed(); - $candidate_param_type = $candidate_param_type->setProperties([ - 'from_template_default' => true, - ]); - } else { - $candidate_param_type = new Union([$et], ['from_template_default' => true]); + $candidate_param_types = []; + + if ($extended_templates) { + foreach ($extended_templates as $template) { + if (!isset( + $input_class_storage->template_types + [$template->param_name] + [$template->defining_class], + )) { + continue; + } + + $old_params_offset = (int) array_search( + $template->param_name, + array_keys($input_class_storage->template_types), + ); + + $candidate_param_types[] = ($input_type_params[$old_params_offset] ?? Type::getMixed()) + ->setProperties(['from_template_default' => true]); + } } $new_input_param = Type::combineUnionTypes( $new_input_param, - $candidate_param_type, + $candidate_param_types + ? Type::combineUnionTypeArray($candidate_param_types, $codebase) + : new Union([$extended_template], ['from_template_default' => true]), ); } diff --git a/vendor/vimeo/psalm/src/Psalm/Internal/Type/TypeCombiner.php b/vendor/vimeo/psalm/src/Psalm/Internal/Type/TypeCombiner.php index 0daa9d29..ee1dd03c 100644 --- a/vendor/vimeo/psalm/src/Psalm/Internal/Type/TypeCombiner.php +++ b/vendor/vimeo/psalm/src/Psalm/Internal/Type/TypeCombiner.php @@ -130,7 +130,9 @@ class TypeCombiner if (count($combination->value_types) === 1 && !count($combination->objectlike_entries) && (!$combination->array_type_params - || $combination->array_type_params[1]->isNever() + || ( $overwrite_empty_array + && $combination->array_type_params[1]->isNever() + ) ) && !$combination->builtin_type_params && !$combination->object_type_params @@ -1031,14 +1033,12 @@ class TypeCombiner && strtolower($type->value) === $type->value ) { // do nothing - } elseif (isset($combination->value_types['string']) - && $combination->value_types['string'] instanceof TNonFalsyString - && $type->value - ) { - // do nothing } elseif (isset($combination->value_types['string']) && $combination->value_types['string'] instanceof TNonEmptyString - && $type->value !== '' + && ($combination->value_types['string'] instanceof TNonFalsyString + ? $type->value + : $type->value !== '' + ) ) { // do nothing } else { diff --git a/vendor/vimeo/psalm/src/Psalm/Issue/CodeIssue.php b/vendor/vimeo/psalm/src/Psalm/Issue/CodeIssue.php index 08645794..ce4fcbc4 100644 --- a/vendor/vimeo/psalm/src/Psalm/Issue/CodeIssue.php +++ b/vendor/vimeo/psalm/src/Psalm/Issue/CodeIssue.php @@ -68,6 +68,9 @@ abstract class CodeIssue return array_pop($fqcn_parts); } + /** + * @param IssueData::SEVERITY_* $severity + */ public function toIssueData(string $severity): IssueData { $location = $this->code_location; diff --git a/vendor/vimeo/psalm/src/Psalm/IssueBuffer.php b/vendor/vimeo/psalm/src/Psalm/IssueBuffer.php index 0c40288a..8adb31ea 100644 --- a/vendor/vimeo/psalm/src/Psalm/IssueBuffer.php +++ b/vendor/vimeo/psalm/src/Psalm/IssueBuffer.php @@ -302,7 +302,7 @@ final class IssueBuffer if ($reporting_level === Config::REPORT_INFO) { if ($is_tainted || !self::alreadyEmitted($emitted_key)) { - self::$issues_data[$e->getFilePath()][] = $e->toIssueData(Config::REPORT_INFO); + self::$issues_data[$e->getFilePath()][] = $e->toIssueData(IssueData::SEVERITY_INFO); if ($is_fixable) { self::addFixableIssue($issue_type); @@ -331,7 +331,7 @@ final class IssueBuffer if ($is_tainted || !self::alreadyEmitted($emitted_key)) { ++self::$error_count; - self::$issues_data[$e->getFilePath()][] = $e->toIssueData(Config::REPORT_ERROR); + self::$issues_data[$e->getFilePath()][] = $e->toIssueData(IssueData::SEVERITY_ERROR); if ($is_fixable) { self::addFixableIssue($issue_type); @@ -570,9 +570,8 @@ final class IssueBuffer foreach (self::$issues_data as $file_path => $file_issues) { usort( $file_issues, - static fn(IssueData $d1, IssueData $d2): int => - [$d1->file_path, $d1->line_from, $d1->column_from] - <=> + static fn(IssueData $d1, IssueData $d2): int => [$d1->file_path, $d1->line_from, $d1->column_from] + <=> [$d2->file_path, $d2->line_from, $d2->column_from] ); self::$issues_data[$file_path] = $file_issues; @@ -580,68 +579,68 @@ final class IssueBuffer // make a copy so what gets saved in cache is unaffected by baseline $issues_data = self::$issues_data; + } - if (!empty($issue_baseline)) { - // Set severity for issues in baseline to INFO - foreach ($issues_data as $file_path => $file_issues) { - foreach ($file_issues as $key => $issue_data) { - $file = $issue_data->file_name; - $file = str_replace('\\', '/', $file); - $type = $issue_data->type; + if (!empty($issue_baseline)) { + // Set severity for issues in baseline to INFO + foreach ($issues_data as $file_path => $file_issues) { + foreach ($file_issues as $key => $issue_data) { + $file = $issue_data->file_name; + $file = str_replace('\\', '/', $file); + $type = $issue_data->type; - if (isset($issue_baseline[$file][$type]) && $issue_baseline[$file][$type]['o'] > 0) { - if ($issue_baseline[$file][$type]['o'] === count($issue_baseline[$file][$type]['s'])) { - $position = array_search( - str_replace("\r\n", "\n", trim($issue_data->selected_text)), - $issue_baseline[$file][$type]['s'], - true, - ); + if (isset($issue_baseline[$file][$type]) && $issue_baseline[$file][$type]['o'] > 0) { + if ($issue_baseline[$file][$type]['o'] === count($issue_baseline[$file][$type]['s'])) { + $position = array_search( + str_replace("\r\n", "\n", trim($issue_data->selected_text)), + $issue_baseline[$file][$type]['s'], + true, + ); - if ($position !== false) { - $issue_data->severity = Config::REPORT_INFO; - array_splice($issue_baseline[$file][$type]['s'], $position, 1); - $issue_baseline[$file][$type]['o']--; - } - } else { - $issue_baseline[$file][$type]['s'] = []; - $issue_data->severity = Config::REPORT_INFO; + if ($position !== false) { + $issue_data->severity = IssueData::SEVERITY_INFO; + array_splice($issue_baseline[$file][$type]['s'], $position, 1); $issue_baseline[$file][$type]['o']--; } + } else { + $issue_baseline[$file][$type]['s'] = []; + $issue_data->severity = IssueData::SEVERITY_INFO; + $issue_baseline[$file][$type]['o']--; } - - $issues_data[$file_path][$key] = $issue_data; } - } - if ($codebase->config->find_unused_baseline_entry) { - foreach ($issue_baseline as $file_path => $issues) { - foreach ($issues as $issue_name => $issue) { - if ($issue['o'] !== 0) { - $issues_data[$file_path][] = new IssueData( - Config::REPORT_ERROR, - 0, - 0, - UnusedBaselineEntry::getIssueType(), - sprintf( - 'Baseline for issue "%s" has %d extra %s.', - $issue_name, - $issue['o'], - $issue['o'] === 1 ? 'entry' : 'entries', - ), - $file_path, - '', - '', - '', - 0, - 0, - 0, - 0, - 0, - 0, - UnusedBaselineEntry::SHORTCODE, - UnusedBaselineEntry::ERROR_LEVEL, - ); - } + $issues_data[$file_path][$key] = $issue_data; + } + } + + if ($codebase->config->find_unused_baseline_entry) { + foreach ($issue_baseline as $file_path => $issues) { + foreach ($issues as $issue_name => $issue) { + if ($issue['o'] !== 0) { + $issues_data[$file_path][] = new IssueData( + IssueData::SEVERITY_ERROR, + 0, + 0, + UnusedBaselineEntry::getIssueType(), + sprintf( + 'Baseline for issue "%s" has %d extra %s.', + $issue_name, + $issue['o'], + $issue['o'] === 1 ? 'entry' : 'entries', + ), + $file_path, + '', + '', + '', + 0, + 0, + 0, + 0, + 0, + 0, + UnusedBaselineEntry::SHORTCODE, + UnusedBaselineEntry::ERROR_LEVEL, + ); } } } @@ -792,11 +791,7 @@ final class IssueBuffer } if ($is_full && $start_time) { - $codebase->file_reference_provider->removeDeletedFilesFromReferences(); - - if ($project_analyzer->project_cache_provider) { - $project_analyzer->project_cache_provider->processSuccessfulRun($start_time, PSALM_VERSION); - } + $project_analyzer->finish($start_time, PSALM_VERSION); } if ($error_count diff --git a/vendor/vimeo/psalm/src/Psalm/Plugin/EventHandler/Event/AfterAnalysisEvent.php b/vendor/vimeo/psalm/src/Psalm/Plugin/EventHandler/Event/AfterAnalysisEvent.php index 92ac8ae9..60db9473 100644 --- a/vendor/vimeo/psalm/src/Psalm/Plugin/EventHandler/Event/AfterAnalysisEvent.php +++ b/vendor/vimeo/psalm/src/Psalm/Plugin/EventHandler/Event/AfterAnalysisEvent.php @@ -10,7 +10,7 @@ final class AfterAnalysisEvent { private Codebase $codebase; /** - * @var IssueData[][] + * @var array> where string key is a filepath */ private array $issues; private array $build_info; @@ -19,7 +19,7 @@ final class AfterAnalysisEvent /** * Called after analysis is complete * - * @param array> $issues + * @param array> $issues where string key is a filepath * @internal */ public function __construct( @@ -40,7 +40,7 @@ final class AfterAnalysisEvent } /** - * @return IssueData[][] + * @return array> where string key is a filepath */ public function getIssues(): array { diff --git a/vendor/vimeo/psalm/src/Psalm/Plugin/Shepherd.php b/vendor/vimeo/psalm/src/Psalm/Plugin/Shepherd.php index 73cbdac4..096a17bb 100644 --- a/vendor/vimeo/psalm/src/Psalm/Plugin/Shepherd.php +++ b/vendor/vimeo/psalm/src/Psalm/Plugin/Shepherd.php @@ -5,6 +5,7 @@ namespace Psalm\Plugin; use BadMethodCallException; use Psalm\Config; use Psalm\Internal\Analyzer\IssueData; +use Psalm\Internal\VersionUtils; use Psalm\Plugin\EventHandler\AfterAnalysisInterface; use Psalm\Plugin\EventHandler\Event\AfterAnalysisEvent; @@ -95,7 +96,14 @@ final class Shepherd implements AfterAnalysisInterface } /** - * @return array{build: array, git: array, issues: array, coverage: list, level: int<1,8>}|null + * @return array{ + * build: array, + * git: array, + * issues: array, + * coverage: list, + * level: int<1, 8>, + * versions: array + * }|null */ private static function collectPayloadToSend(AfterAnalysisEvent $event): ?array { @@ -120,11 +128,11 @@ final class Shepherd implements AfterAnalysisInterface return null; } - $issues = $event->getIssues(); - $normalized_data = $issues === [] ? [] : array_filter( - array_merge(...array_values($issues)), - static fn(IssueData $i): bool => $i->severity === 'error', - ); + $issues_grouped_by_filename = $event->getIssues(); + $normalized_data = $issues_grouped_by_filename === [] ? [] : array_values(array_filter( + array_merge(...array_values($issues_grouped_by_filename)), // flatten an array + static fn(IssueData $i): bool => $i->severity === IssueData::SEVERITY_ERROR, + )); $codebase = $event->getCodebase(); @@ -134,6 +142,10 @@ final class Shepherd implements AfterAnalysisInterface 'issues' => $normalized_data, 'coverage' => $codebase->analyzer->getTotalTypeCoverage($codebase), 'level' => Config::getInstance()->level, + 'versions' => [ + 'psalm' => VersionUtils::getPsalmVersion(), + 'parser' => VersionUtils::getPhpParserVersion(), + ], ]; } diff --git a/vendor/vimeo/psalm/src/Psalm/Report.php b/vendor/vimeo/psalm/src/Psalm/Report.php index a7b9268d..fddfd452 100644 --- a/vendor/vimeo/psalm/src/Psalm/Report.php +++ b/vendor/vimeo/psalm/src/Psalm/Report.php @@ -74,7 +74,7 @@ abstract class Report if (!$report_options->show_info) { $this->issues_data = array_filter( $issues_data, - static fn(IssueData $issue_data): bool => $issue_data->severity !== Config::REPORT_INFO, + static fn(IssueData $issue_data): bool => $issue_data->severity !== IssueData::SEVERITY_INFO, ); } else { $this->issues_data = $issues_data; diff --git a/vendor/vimeo/psalm/src/Psalm/Report/CompactReport.php b/vendor/vimeo/psalm/src/Psalm/Report/CompactReport.php index d351b5ba..11416eb2 100644 --- a/vendor/vimeo/psalm/src/Psalm/Report/CompactReport.php +++ b/vendor/vimeo/psalm/src/Psalm/Report/CompactReport.php @@ -3,6 +3,7 @@ namespace Psalm\Report; use Psalm\Config; +use Psalm\Internal\Analyzer\IssueData; use Psalm\Report; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Output\BufferedOutput; @@ -31,7 +32,7 @@ final class CompactReport extends Report $output = []; foreach ($this->issues_data as $i => $issue_data) { - if (!$this->show_info && $issue_data->severity === Config::REPORT_INFO) { + if (!$this->show_info && $issue_data->severity === IssueData::SEVERITY_INFO) { continue; } diff --git a/vendor/vimeo/psalm/src/Psalm/Report/EmacsReport.php b/vendor/vimeo/psalm/src/Psalm/Report/EmacsReport.php index d022fe5d..c1cb008e 100644 --- a/vendor/vimeo/psalm/src/Psalm/Report/EmacsReport.php +++ b/vendor/vimeo/psalm/src/Psalm/Report/EmacsReport.php @@ -2,7 +2,7 @@ namespace Psalm\Report; -use Psalm\Config; +use Psalm\Internal\Analyzer\IssueData; use Psalm\Report; use function sprintf; @@ -18,7 +18,7 @@ final class EmacsReport extends Report $issue_data->file_path, $issue_data->line_from, $issue_data->column_from, - ($issue_data->severity === Config::REPORT_ERROR ? 'error' : 'warning'), + ($issue_data->severity === IssueData::SEVERITY_ERROR ? 'error' : 'warning'), $issue_data->type, $issue_data->message, $issue_data->link, diff --git a/vendor/vimeo/psalm/src/Psalm/Report/GithubActionsReport.php b/vendor/vimeo/psalm/src/Psalm/Report/GithubActionsReport.php index 71a7a0f6..9d7c617f 100644 --- a/vendor/vimeo/psalm/src/Psalm/Report/GithubActionsReport.php +++ b/vendor/vimeo/psalm/src/Psalm/Report/GithubActionsReport.php @@ -2,7 +2,7 @@ namespace Psalm\Report; -use Psalm\Config; +use Psalm\Internal\Analyzer\IssueData; use Psalm\Report; use function sprintf; @@ -34,7 +34,7 @@ final class GithubActionsReport extends Report $output .= sprintf( '::%1$s %2$s::%3$s', - ($issue_data->severity === Config::REPORT_ERROR ? 'error' : 'warning'), + ($issue_data->severity === IssueData::SEVERITY_ERROR ? 'error' : 'warning'), $properties, $data, ) . "\n"; diff --git a/vendor/vimeo/psalm/src/Psalm/Report/JunitReport.php b/vendor/vimeo/psalm/src/Psalm/Report/JunitReport.php index f917aa50..dfef6208 100644 --- a/vendor/vimeo/psalm/src/Psalm/Report/JunitReport.php +++ b/vendor/vimeo/psalm/src/Psalm/Report/JunitReport.php @@ -27,8 +27,8 @@ final class JunitReport extends Report $ndata = []; foreach ($this->issues_data as $error) { - $is_error = $error->severity === Config::REPORT_ERROR; - $is_warning = $error->severity === Config::REPORT_INFO; + $is_error = $error->severity === IssueData::SEVERITY_ERROR; + $is_warning = $error->severity === IssueData::SEVERITY_INFO; if (!$is_error && !$is_warning) { continue; diff --git a/vendor/vimeo/psalm/src/Psalm/Report/TextReport.php b/vendor/vimeo/psalm/src/Psalm/Report/TextReport.php index d2fa2382..2ee578fd 100644 --- a/vendor/vimeo/psalm/src/Psalm/Report/TextReport.php +++ b/vendor/vimeo/psalm/src/Psalm/Report/TextReport.php @@ -2,7 +2,7 @@ namespace Psalm\Report; -use Psalm\Config; +use Psalm\Internal\Analyzer\IssueData; use Psalm\Report; use function sprintf; @@ -18,7 +18,7 @@ final class TextReport extends Report $issue_data->file_path, $issue_data->line_from, $issue_data->column_from, - ($issue_data->severity === Config::REPORT_ERROR ? 'error' : 'warning'), + ($issue_data->severity === IssueData::SEVERITY_ERROR ? 'error' : 'warning'), $issue_data->type, $issue_data->message, ) . "\n"; diff --git a/vendor/vimeo/psalm/src/Psalm/Type.php b/vendor/vimeo/psalm/src/Psalm/Type.php index 3b98f05c..fbc3e7e7 100644 --- a/vendor/vimeo/psalm/src/Psalm/Type.php +++ b/vendor/vimeo/psalm/src/Psalm/Type.php @@ -190,6 +190,14 @@ abstract class Type ]); } + /** + * @psalm-pure + */ + public static function getIntRange(?int $min, ?int $max): Union + { + return new Union([new TIntRange($min, $max)]); + } + /** * @psalm-pure */ @@ -495,7 +503,7 @@ abstract class Type if ($from_docblock) { return self::$listKeyFromDocblock ??= new Union([new TIntRange(0, null, true)]); } - return self::$listKey ??= new Union([new TIntRange(0, null)]); + return self::$listKey ??= self::getIntRange(0, null); } /** diff --git a/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TCallableList.php b/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TCallableList.php index 8ff15012..764f1ca2 100644 --- a/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TCallableList.php +++ b/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TCallableList.php @@ -7,9 +7,9 @@ use Psalm\Type; use function array_fill; /** - * @deprecated Will be removed in Psalm v6, please use TCallableKeyedArrays with is_list=true instead. - * * Denotes a list that is _also_ `callable`. + * + * @deprecated Will be removed in Psalm v6, please use TCallableKeyedArrays with is_list=true instead. * @psalm-immutable */ final class TCallableList extends TNonEmptyList diff --git a/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TDependentListKey.php b/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TDependentListKey.php index 042c95d4..338136d8 100644 --- a/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TDependentListKey.php +++ b/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TDependentListKey.php @@ -3,9 +3,9 @@ namespace Psalm\Type\Atomic; /** - * @deprecated Will be removed in Psalm v6, use TIntRange instead - * * Represents a list key created from foreach ($list as $key => $value) + * + * @deprecated Will be removed in Psalm v6, use TIntRange instead * @psalm-immutable */ final class TDependentListKey extends TInt implements DependentType diff --git a/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TKeyedArray.php b/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TKeyedArray.php index 8510b83d..dfddbe81 100644 --- a/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TKeyedArray.php +++ b/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TKeyedArray.php @@ -310,7 +310,7 @@ class TKeyedArray extends Atomic if (count($this->properties) === 1) { return new Union([new TLiteralInt(0)]); } - return new Union([new TIntRange(0, count($this->properties)-1)]); + return Type::getIntRange(0, count($this->properties)-1); } $key_types = []; diff --git a/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TList.php b/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TList.php index 9e2c611c..13c44e5b 100644 --- a/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TList.php +++ b/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TList.php @@ -14,16 +14,15 @@ use Psalm\Type\Union; use function get_class; /** - * @deprecated Will be removed in Psalm v6, please use TKeyedArrays with is_list=true instead. - * * You may also use the \Psalm\Type::getListAtomic shortcut, which creates unsealed list-like shaped arrays * with all elements optional, semantically equivalent to a TList. * - * * Represents an array that has some particularities: * - its keys are integers * - they start at 0 * - they are consecutive and go upwards (no negative int) + * + * @deprecated Will be removed in Psalm v6, please use TKeyedArrays with is_list=true instead. * @psalm-immutable */ class TList extends Atomic diff --git a/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TNonEmptyList.php b/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TNonEmptyList.php index e6c02940..47c628cc 100644 --- a/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TNonEmptyList.php +++ b/vendor/vimeo/psalm/src/Psalm/Type/Atomic/TNonEmptyList.php @@ -8,13 +8,12 @@ use Psalm\Type\Union; use function array_fill; /** - * @deprecated Will be removed in Psalm v6, please use TKeyedArrays with is_list=true instead. - * * You may also use the \Psalm\Type::getNonEmptyListAtomic shortcut, which creates unsealed list-like shaped arrays * with one non-optional element, semantically equivalent to a TNonEmptyList. * - * * Represents a non-empty list + * + * @deprecated Will be removed in Psalm v6, please use TKeyedArrays with is_list=true instead. * @psalm-immutable */ class TNonEmptyList extends TList diff --git a/vendor/vimeo/psalm/stubs/CoreGenericAttributes.phpstub b/vendor/vimeo/psalm/stubs/CoreGenericAttributes.phpstub new file mode 100644 index 00000000..7aa6400d --- /dev/null +++ b/vendor/vimeo/psalm/stubs/CoreGenericAttributes.phpstub @@ -0,0 +1,13 @@ + $array + * @param non-empty-string $pattern + * @param array $array * @param 0|1 $flags 1=PREG_GREP_INVERT - * @return array + * @return array */ function preg_grep($pattern, array $array, $flags = 0) { @@ -619,7 +619,7 @@ function strtoupper(string $string) : string {} * @param int|array $offset * @param null|int|array $length * - * @return ($string is array ? array : string) + * @return ($string is array ? array : string) * * @psalm-flow ($string, $replace) -> return */ @@ -786,6 +786,8 @@ function explode(string $separator, string $string, int $limit = -1) : array {} /** * @psalm-pure * + * @param non-empty-string $pattern + * * @psalm-flow ($subject) -(array-assignment)-> return * * @template TFlags as int-mask<0, 1, 2, 4> @@ -998,11 +1000,13 @@ function strlen(string $string) : int {} /** * @psalm-pure * + * @template TKey of array-key + * * @param string|array $search * @param string|array $replace - * @param string|array $subject - * @param int $count - * @return ($subject is array ? array : string) + * @param string|array $subject + * @param int<0, max> $count + * @return ($subject is array ? array : string) * * @psalm-flow ($replace, $subject) -> return */ @@ -1011,11 +1015,13 @@ function str_replace($search, $replace, $subject, &$count = null) {} /** * @psalm-pure * + * @template TKey of array-key + * * @param string|array $search * @param string|array $replace - * @param string|array $subject - * @param int $count - * @return ($subject is array ? array : string) + * @param string|array $subject + * @param int<0, max> $count + * @return ($subject is array ? array : string) * * @psalm-flow ($replace, $subject) -> return */ @@ -1169,10 +1175,10 @@ function str_word_count(string $string, int $format = 0, string|null $characters /** * @psalm-pure * - * @param string|string[] $pattern + * @param non-empty-string|non-empty-string[] $pattern * @param string|array $replacement * @param string|array $subject - * @param int $count + * @param int<0, max> $count * @return ($subject is array ? array : string|null) * * @psalm-flow ($replacement, $subject) -> return @@ -1182,22 +1188,30 @@ function preg_filter($pattern, $replacement, $subject, int $limit = -1, &$count /** * @psalm-pure * - * @param string|string[] $pattern + * @template TKey of array-key + * + * @param non-empty-string|non-empty-string[] $pattern * @param string|array $replacement - * @param string|array $subject - * @param int $count - * @return ($subject is array ? array|null : string|null) + * @param string|array $subject + * @param int<0, max> $count + * @return ($subject is array ? array|null : string|null) + * + * @psalm-ignore-nullable-return * * @psalm-flow ($replacement, $subject) -> return */ function preg_replace($pattern, $replacement, $subject, int $limit = -1, &$count = null) {} /** - * @param string|string[] $pattern + * @template TKey of array-key + * + * @param non-empty-string|non-empty-string[] $pattern * @param callable(string[]):string $callback - * @param string|array $subject - * @param int $count - * @return ($subject is array ? array|null : string|null) + * @param string|array $subject + * @param int<0, max> $count + * @return ($subject is array ? array|null : string|null) + * + * @psalm-ignore-nullable-return * * @psalm-taint-specialize * @psalm-flow ($subject) -> return @@ -1208,7 +1222,7 @@ function preg_replace_callback($pattern, $callback, $subject, int $limit = -1, & * @psalm-pure * @template TFlags as int * - * @param string $pattern + * @param non-empty-string $pattern * @param string $subject * @param mixed $matches * @param TFlags $flags @@ -1244,7 +1258,7 @@ function preg_match_all($pattern, $subject, &$matches = [], int $flags = 1, int * @psalm-pure * @template TFlags as int-mask<0, 256, 512> * - * @param string $pattern + * @param non-empty-string $pattern * @param string $subject * @param mixed $matches * @param TFlags $flags @@ -1279,17 +1293,17 @@ function preg_quote(string $str, ?string $delimiter = null) : string {} * @psalm-pure * * @param string|int|float $values - * @return ($format is non-empty-string - * ? ($values is non-empty-string|int|float ? non-empty-string : string) - * : string) + * @return (PHP_MAJOR_VERSION is 8 ? string : string|false) + * @psalm-ignore-falsable-return * * @psalm-flow ($format, $values) -> return */ -function sprintf(string $format, ...$values) : string {} +function sprintf(string $format, ...$values) {} /** * @psalm-pure - * @return string|false + * @param array $values + * @return (PHP_MAJOR_VERSION is 8 ? string : string|false) * @psalm-ignore-falsable-return * * @psalm-flow ($format, $values) -> return @@ -1308,20 +1322,27 @@ function wordwrap(string $string, int $width = 75, string $break = "\n", bool $c * @psalm-pure * * @param string|int|float $values + * @return (PHP_MAJOR_VERSION is 8 ? int<0, max> : int<0, max>|false) + * @psalm-ignore-falsable-return * * @psalm-taint-specialize * @psalm-flow ($format, $values) -> return * @psalm-taint-sink html $format * @psalm-taint-sink html $values */ -function printf(string $format, ...$values) : string {} +function printf(string $format, ...$values) {} /** + * @param array $values + * @return (PHP_MAJOR_VERSION is 8 ? int<0, max> : int<0, max>|false) + * @psalm-ignore-falsable-return + * + * @psalm-pure * @psalm-taint-specialize * @psalm-taint-sink html $format * @psalm-taint-sink html $values */ -function vprintf(string $format, array $values) : int {} +function vprintf(string $format, array $values) {} /** * @psalm-pure @@ -1364,11 +1385,11 @@ function str_getcsv(string $string, string $separator = ',', string $enclosure = /** * @template TKey as array-key - * @template TArray as array + * @template TArray as array * * @param TArray $array * - * @return (TArray is non-empty-array ? non-empty-array : array) + * @return (TArray is non-empty-array ? non-empty-array> : array>) * * @psalm-pure */ @@ -1508,7 +1529,7 @@ function ldap_escape(string $value, string $ignore = "", int $flags = 0) : strin function json_decode(string $json, ?bool $associative = null, int $depth = 512, int $flags = 0) {} /** - * The conditional return type below relies on the fact that JSON_THROW_ON_ERROR is + * The conditional return type below relies on the fact that JSON_THROW_ON_ERROR is * the highest-valued of JSON constants * @psalm-pure * @@ -1542,6 +1563,8 @@ function sapi_windows_cp_conv($in_codepage, $out_codepage, string $subject) : ?s /** * @psalm-pure * + * @return non-empty-string + * * @psalm-flow ($prefix) -> return */ function uniqid(string $prefix = "", bool $more_entropy = false) : string {} @@ -1559,7 +1582,10 @@ function unpack(string $format, string $string, int $offset = 0) {} /** * @psalm-pure * + * @template T of bool + * @param T $strict * @return string|false + * @psalm-return (T is false ? string : string|false) * * @psalm-flow ($string) -> return * @psalm-ignore-falsable-return @@ -1704,3 +1730,58 @@ function pg_escape_literal($string1, $string2 = null) {} * @psalm-flow ($string1, $string2) -> return */ function pg_escape_string($string1, $string2 = null) {} + +if (defined('GLOB_BRACE')) { + /** + * @psalm-template P of string + * @psalm-template F of int-mask + * @psalm-param P $pattern + * @psalm-param F $flags + * @psalm-return ( + * P is '' + * ? (F is int-mask + * ? false|list + * : (F is int-mask + * ? false|list{0:''} + * : false|list + * ) + * ) + * : (F is int-mask + * ? false|list + * : (F is int-mask + * ? false|list{0:non-empty-string, ...} + * : false|list + * ) + * ) + * ) + * @psalm-ignore-falsable-return + */ + function glob (string $pattern, int $flags = 0): array|false {} +} else { + /** + * @psalm-template P of string + * @psalm-template F of int-mask + * @psalm-param P $pattern + * @psalm-param F $flags + * @psalm-return ( + * P is '' + * ? (F is int-mask + * ? false|list + * : (F is int-mask + * ? false|list{0:''} + * : false|list + * ) + * ) + * : (F is int-mask + * ? false|list + * : (F is int-mask + * ? false|list{0:non-empty-string, ...} + * : false|list + * ) + * ) + * ) + * @psalm-ignore-falsable-return + */ + function glob (string $pattern, int $flags = 0): array|false {} +} + diff --git a/vendor/vimeo/psalm/stubs/Php82.phpstub b/vendor/vimeo/psalm/stubs/Php82.phpstub index 8696bd08..81b99f91 100644 --- a/vendor/vimeo/psalm/stubs/Php82.phpstub +++ b/vendor/vimeo/psalm/stubs/Php82.phpstub @@ -34,18 +34,6 @@ namespace { public function getIterator(): Iterator {} } - #[Attribute(Attribute::TARGET_PARAMETER)] - final class SensitiveParameter - { - public function __construct() {} - } - - #[Attribute(Attribute::TARGET_CLASS)] - final class AllowDynamicProperties - { - public function __construct() {} - } - /** * @psalm-pure * @param positive-int $length diff --git a/vendor/vimeo/psalm/stubs/extensions/mongodb.phpstub b/vendor/vimeo/psalm/stubs/extensions/mongodb.phpstub index ad6f34d5..00d9f203 100644 --- a/vendor/vimeo/psalm/stubs/extensions/mongodb.phpstub +++ b/vendor/vimeo/psalm/stubs/extensions/mongodb.phpstub @@ -1,59 +1,251 @@ - */ -interface CursorInterface extends Traversable +namespace MongoDB\BSON { + use IteratorAggregate; + use Serializable; + /** - * @return array + * @template TValue + * @template-implements IteratorAggregate */ - public function toArray(); + final class Document implements IteratorAggregate, Serializable + { + private function __construct() + { + } + + final static public function fromBSON(string $bson): Document + { + } + + final static public function fromJSON(string $json): Document + { + } + + /** @param array|object $value */ + final static public function fromPHP($value): Document + { + } + + /** @return TValue */ + final public function get(string $key) + { + } + + /** @return Iterator */ + final public function getIterator(): Iterator + { + } + + final public function has(string $key): bool + { + } + + /** @return array|object */ + final public function toPHP(?array $typeMap = null) + { + } + + final public function toCanonicalExtendedJSON(): string + { + } + + final public function toRelaxedExtendedJSON(): string + { + } + + final public function __toString(): string + { + } + + final public static function __set_state(array $properties): Document + { + } + + final public function serialize(): string + { + } + + /** @param string $serialized */ + final public function unserialize($serialized): void + { + } + + final public function __unserialize(array $data): void + { + } + + final public function __serialize(): array + { + } + } + + /** + * @psalm-template TKey of int|string + * @psalm-template TValue + * $psalm-implements \Iterator + */ + final class Iterator implements \Iterator + { + final private function __construct() + { + } + + /** @return TValue */ + final public function current() + { + } + + /** @return TKey */ + final public function key() + { + } + + final public function next(): void + { + } + + final public function rewind(): void + { + } + + final public function valid(): bool + { + } + + final public function __wakeup(): void + { + } + } + + /** + * @template TValue + * @template-implements IteratorAggregate + */ + final class PackedArray implements IteratorAggregate, Serializable + { + private function __construct() + { + } + + final static public function fromPHP(array $value): PackedArray + { + } + + /** @return TValue */ + final public function get(int $index) + { + } + + /** @return Iterator */ + final public function getIterator(): Iterator + { + } + + final public function has(int $index): bool + { + } + + /** @return array|object */ + final public function toPHP(?array $typeMap = null) + { + } + + final public function __toString(): string + { + } + + final public static function __set_state(array $properties): PackedArray + { + } + + final public function serialize(): string + { + } + + /** @param string $serialized */ + final public function unserialize($serialized): void + { + } + + final public function __unserialize(array $data): void + { + } + + final public function __serialize(): array + { + } + } } -/** - * @template-covariant TValue of array|object - * - * @template-implements Iterator - * @template-implements CursorInterface - */ -final class Cursor implements CursorInterface, Iterator +namespace MongoDB\Driver { - /** - * @return TValue - */ - public function current() {} + use Iterator; + use Traversable; /** - * @return void + * @template-covariant TKey + * @template-covariant TValue + * + * @template-extends Traversable */ - public function next() {} + interface CursorInterface extends Traversable + { + /** + * @return array + */ + public function toArray(); + } /** - * @return int + * @template-covariant TValue of array|object + * + * @template-implements Iterator + * @template-implements CursorInterface */ - public function key() {} + final class Cursor implements CursorInterface, Iterator + { + /** + * @return TValue + */ + public function current() + { + } - /** - * @return bool - */ - public function valid() {} + /** + * @return void + */ + public function next() + { + } - /** - * @return void - */ - public function rewind() {} + /** + * @return int + */ + public function key() + { + } - /** - * @return array - */ - public function toArray() {} + /** + * @return bool + */ + public function valid() + { + } + + /** + * @return void + */ + public function rewind() + { + } + + /** + * @return array + */ + public function toArray() + { + } + } } diff --git a/vendor/vimeo/psalm/stubs/extensions/pdo.phpstub b/vendor/vimeo/psalm/stubs/extensions/pdo.phpstub index 039b565e..aec49654 100644 --- a/vendor/vimeo/psalm/stubs/extensions/pdo.phpstub +++ b/vendor/vimeo/psalm/stubs/extensions/pdo.phpstub @@ -150,6 +150,16 @@ class PDOStatement implements Traversable * @return false|T */ public function fetchObject($class = \stdclass::class, array $ctorArgs = array()) {} + + /** + * @psalm-taint-sink sql $value + */ + public function bindValue(string|int $param, mixed $value, int $type = PDO::PARAM_STR): bool {} + + /** + * @psalm-taint-sink sql $var + */ + public function bindParam(string|int $param, mixed &$var, int $type = PDO::PARAM_STR, int $maxLength = 0, mixed $driverOptions = null): bool {} } class PDOException extends RuntimeException { diff --git a/vendor/vimeo/psalm/stubs/phpparser.phpstub b/vendor/vimeo/psalm/stubs/phpparser.phpstub index 856cd2fe..18fd86b3 100644 --- a/vendor/vimeo/psalm/stubs/phpparser.phpstub +++ b/vendor/vimeo/psalm/stubs/phpparser.phpstub @@ -20,3 +20,21 @@ abstract class CallLike extends Expr { */ public function getArgs(): array {} } + + +namespace PhpParser\Node; + +use PhpParser\NodeAbstract; + +class Name extends NodeAbstract { + /** + * @param string|string[]|self $name + * @param array $attributes + */ + public function __construct($name, array $attributes = []) {} + + /** + * @return non-empty-string + */ + public function toString(): string {} +}